From b695ba770115ef242954df32038b01f24cf786bc Mon Sep 17 00:00:00 2001 From: hut Date: Wed, 1 May 2024 22:14:35 +0200 Subject: [PATCH] fix floating point errors in map mode on far away targets --- src/camera.rs | 54 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/src/camera.rs b/src/camera.rs index a62cfa5..775b10b 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -165,8 +165,8 @@ pub fn update_map_camera( settings: Res, mut mapcam: ResMut, mut q_camera: Query<&mut Transform, (With, Without)>, - q_playercam: Query<&Transform, (With, Without)>, - q_target: Query<&Transform, (With, Without, Without)>, + q_playercam: Query<(&Transform, &Position), (With, Without)>, + q_target: Query<(&Transform, &Position), (With, Without, Without)>, q_target_changed: Query<(), Changed>, mut mouse_events: EventReader, mut er_mousewheel: EventReader, @@ -176,11 +176,11 @@ pub fn update_map_camera( return; } let mut camera_transform = q_camera.get_single_mut().unwrap(); - let player_transform = q_playercam.get_single().unwrap(); - let target = if let Ok(target) = q_target.get_single() { + let (player_trans, player_pos) = q_playercam.get_single().unwrap(); + let (target_trans, target_pos) = if let Ok(target) = q_target.get_single() { target } else { - player_transform + (player_trans, player_pos) }; // Get mouse movement @@ -192,7 +192,7 @@ pub fn update_map_camera( // direction parameter for the Transform.look_at function is ambiguous // at the extreme values and the orientation will flicker back/forth. let epsilon = 0.001; - let min_zoom: f64 = target.scale.x as f64 * 2.0; + let min_zoom: f64 = target_trans.scale.x as f64 * 2.0; let max_zoom: f64 = 17e18; // at this point, camera starts glitching mapcam.pitch = (mapcam.pitch + mouse_delta.y as f64 / 180.0 * settings.mouse_sensitivity as f64).clamp(-PI64 / 2.0 + epsilon, PI64 / 2.0 - epsilon); mapcam.yaw += mouse_delta.x as f64 / 180.0 * settings.mouse_sensitivity as f64; @@ -225,9 +225,9 @@ pub fn update_map_camera( // Update zoom level if !mapcam.initialized { - let factor: f64 = if target == player_transform { 7.0 } else { 1.0 }; - mapcam.target_zoom_level *= target.scale.x as f64 * factor; - mapcam.zoom_level *= target.scale.x as f64 * factor; + let factor: f64 = if target_trans == player_trans { 7.0 } else { 1.0 }; + mapcam.target_zoom_level *= target_trans.scale.x as f64 * factor; + mapcam.zoom_level *= target_trans.scale.x as f64 * factor; mapcam.initialized = true; } let mut change_zoom: f64 = 0.0; @@ -247,7 +247,7 @@ pub fn update_map_camera( // Update point of view let pov_rotation = DQuat::from_euler(EulerRot::XYZ, 0.0, mapcam.yaw as f64, mapcam.pitch as f64); let offset = DVec3::new(mapcam.offset_x, 0.0, mapcam.offset_z); - let point_of_view = offset + pov_rotation * (mapcam.zoom_level as f64 * DVec3::new(1.0, 0.0, 0.0)); + let point_of_view = pov_rotation * (mapcam.zoom_level as f64 * DVec3::new(1.0, 0.0, 0.0)); // Update movement offset let mut direction = pov_rotation * DVec3::new(offset_x, 0.0, offset_z); @@ -259,9 +259,9 @@ pub fn update_map_camera( mapcam.offset_z += 0.01 * (direction.z * mapcam.zoom_level); // Apply updates to camera - mapcam.center = target.translation.as_dvec3() + offset; - camera_transform.translation = target.translation + point_of_view.as_vec3(); - camera_transform.look_at(mapcam.center.as_vec3(), Vec3::Y); + mapcam.center = **target_pos + offset; + camera_transform.translation = point_of_view.as_vec3(); + camera_transform.look_at(Vec3::ZERO, Vec3::Y); } pub fn update_fov( @@ -691,17 +691,27 @@ pub fn calc_angular_diameter( // the rendering position to center entities at the player camera. // This avoids rendering glitches when very far away from the origin. pub fn position_to_transform( + mapcam: Res, + settings: Res, q_player: Query<&Position, With>, mut q_trans: Query<(&'static mut Transform, &'static Position, &'static Rotation), Without>, ) { - if let Ok(player_pos) = q_player.get_single() { - for (mut transform, pos, rot) in &mut q_trans { - transform.translation = Vec3::new( - (pos.x - player_pos.x) as f32, - (pos.y - player_pos.y) as f32, - (pos.z - player_pos.z) as f32, - ); - transform.rotation = rot.as_quat(); - } + let center: DVec3 = if settings.map_active { + mapcam.center + } + else if let Ok(player_pos) = q_player.get_single() { + **player_pos + } else { + error!("Can't find player's position"); + return; + }; + + for (mut transform, pos, rot) in &mut q_trans { + transform.translation = Vec3::new( + (pos.x - center.x) as f32, + (pos.y - center.y) as f32, + (pos.z - center.z) as f32, + ); + transform.rotation = rot.as_quat(); } }