diff options
Diffstat (limited to 'src/tacmap/camera.rs')
| -rw-r--r-- | src/tacmap/camera.rs | 83 |
1 files changed, 43 insertions, 40 deletions
diff --git a/src/tacmap/camera.rs b/src/tacmap/camera.rs index c6ee5c0..c573cfb 100644 --- a/src/tacmap/camera.rs +++ b/src/tacmap/camera.rs @@ -1,9 +1,9 @@ use std::{cell::RefCell, time::Duration}; -use cgmath::{EuclideanSpace, InnerSpace, Point3, Rad, Vector2, Vector3, Vector4, Zero, perspective}; +use cgmath::{EuclideanSpace, InnerSpace, Point2, Point3, Rad, Vector2, Vector3, Vector4, Zero, perspective}; use winit::{event::ElementState, keyboard::KeyCode}; -use crate::{GameState, solar_system, wgpuctx::WgpuCtx, window::ui::GameWindowUiState}; +use crate::{GameState, solar_system::{self, Kilometers}, ui, wgpuctx::WgpuCtx}; pub const OPENGL_TO_WGPU_MATRIX: cgmath::Matrix4<f32> = cgmath::Matrix4::from_cols( Vector4::new(1.0, 0.0, 0.0, 0.0), @@ -14,8 +14,8 @@ pub const OPENGL_TO_WGPU_MATRIX: cgmath::Matrix4<f32> = cgmath::Matrix4::from_co pub struct Camera { - abs_position: Point3<f32>, - rel_position: Point3<f32>, + abs_position: Vector3<Kilometers>, + rel_position: Vector3<f32>, pitch: Rad<f32>, yaw: Rad<f32>, scale: f32, @@ -55,7 +55,7 @@ pub struct Projection impl Camera { pub fn new< - V: Into<Point3<f32>>, + V: Into<Vector3<Kilometers>>, Y: Into<Rad<f32>>, P: Into<Rad<f32>> >( @@ -98,11 +98,11 @@ impl Camera ); Self { abs_position: position.into(), - rel_position: Point3::new(0.0, 0.0, 0.0), + rel_position: Vector3::new(0.0, 0.0, 0.0), yaw: yaw.into(), pitch: pitch.into(), - scale: 1.0, - target: None, + scale: 1e-7, + target: Some(0), buffer: buffer, staging_buffer: staging_buffer, bindgroup: bind_group @@ -112,12 +112,17 @@ impl Camera pub fn get_scale(&self) -> f32 { self.scale } - pub fn get_position(&self) -> Point3<f32> + pub fn get_abs_position(&self) -> Vector3<Kilometers> + { self.abs_position } + + pub fn get_combined_position(&self) -> Vector3<Kilometers> + { + self.abs_position + self.rel_position.map(|v| { v as f64 }) + } + + pub fn get_rotation(&self) -> Vector2<Rad<f32>> { - Point3::new( - self.abs_position.x + self.rel_position.x, - self.abs_position.y + self.rel_position.y, - self.abs_position.z + self.rel_position.z) + Vector2::new(self.yaw, self.pitch) } pub fn bindgroup_layout(wgpuctx: &WgpuCtx) @@ -168,15 +173,12 @@ impl Camera { if target == self.target { return; } if !target.is_some() || !self.target.is_some() { - self.abs_position = self.get_position(); - self.rel_position = Point3::new(0.0, 0.0, 0.0); + self.abs_position = self.get_combined_position(); + self.rel_position = Vector3::new(0.0, 0.0, 0.0); } self.target = target; } - pub fn get_target(&self) -> Option<solar_system::BodyId> - { self.target } - pub fn view_matrix( &self) -> cgmath::Matrix4<f32> { @@ -186,12 +188,12 @@ impl Camera if self.target.is_some() { cgmath::Matrix4::look_at_rh( - self.get_position(), - self.abs_position, + Point3::new(self.rel_position.x, self.rel_position.y, self.rel_position.z), + Point3::new(0.0, 0.0, 0.0), Vector3::unit_y()) }else{ cgmath::Matrix4::look_to_rh( - self.get_position(), + Point3::new(0.0, 0.0, 0.0), Vector3::new( pitch_cos * yaw_cos, pitch_sin, @@ -250,25 +252,26 @@ impl CameraController fn update_orbit( &mut self, camera: &mut Camera, - target: Point3<f32>, + target: Vector3<Kilometers>, min_radius: f32, dt: Duration) { - camera.abs_position = target * camera.scale; + camera.abs_position = target; let dt = dt.as_secs_f32(); let speed = 1.0; - let current_radius = camera.rel_position.to_vec().magnitude(); + let current_radius = camera.rel_position.magnitude(); let polar_diff = (self.position_pos_delta.z - self.position_neg_delta.z) * speed * dt; let azimuth_diff = (self.position_pos_delta.x - self.position_neg_delta.x) * speed * dt; let dist_diff = (self.position_pos_delta.y - self.position_neg_delta.y) * speed * dt; - camera.pitch.0 += polar_diff; - let polar_cap = cgmath::Deg(179.999).0; - if camera.pitch.0 > polar_cap { camera.pitch.0 = polar_cap; } - if camera.pitch.0 < -polar_cap { camera.pitch.0 = -polar_cap; } + let polar_final = camera.pitch.0 + polar_diff; + let polar_cap = Into::<Rad<f32>>::into(cgmath::Deg(89.999)).0; + if polar_final > polar_cap { camera.pitch.0 = polar_cap; } else + if polar_final < -polar_cap { camera.pitch.0 = -polar_cap; } else + { camera.pitch.0 = polar_final; } camera.yaw.0 += azimuth_diff; @@ -276,7 +279,7 @@ impl CameraController let (p_sin, p_cos) = camera.pitch.0.sin_cos(); let radius = f32::max(min_radius * camera.scale, current_radius + dist_diff); - camera.rel_position = Point3::new( + camera.rel_position = Vector3::new( radius * p_cos * az_cos, radius * p_sin, radius * p_cos * az_sin @@ -296,12 +299,12 @@ impl CameraController let right = Vector3::new(-yaw_sin, 0.0, yaw_cos).normalize(); let up = Vector3::new(0.0, 1.0, 0.0); - - camera.rel_position += forward * (self.position_pos_delta.z - self.position_neg_delta.z) * speed * dt; - camera.rel_position += right * (self.position_pos_delta.x - self.position_neg_delta.x) * speed * dt; - camera.rel_position += up * (self.position_pos_delta.y - self.position_neg_delta.y) * speed * dt; - - camera.abs_position = camera.rel_position; + camera.abs_position += (forward * (self.position_pos_delta.z - self.position_neg_delta.z) * speed * dt) + .map(|v| { v as f64 } ); + camera.abs_position += (right * (self.position_pos_delta.x - self.position_neg_delta.x) * speed * dt) + .map(|v| { v as f64 }); + camera.abs_position += (up * (self.position_pos_delta.y - self.position_neg_delta.y) * speed * dt) + .map(|v| { v as f64 }); camera.pitch.0 += (self.rotation_pos_delta.x - self.rotation_neg_delta.x) * speed * dt; camera.yaw.0 += (self.rotation_pos_delta.y - self.rotation_neg_delta.y) * speed * dt; @@ -311,13 +314,13 @@ impl CameraController &mut self, camera: &mut Camera, game_state: &RefCell<GameState>, - ui_state: &mut GameWindowUiState, + ui_state: &mut ui::State, dt: Duration) { camera.scale *= 1.0 + ((self.scale_delta.y - self.scale_delta.x) * 0.1); - camera.scale = f32::max(1e-16, f32::min(1.0, camera.scale)); + camera.scale = f32::max(1e-16, f32::min(1e-6, camera.scale)); - match ui_state.camera_target { + match ui_state.camera_info.target { Some(body_id) => { let game_state = game_state.borrow(); let solar_systems = game_state.solar_systems(); @@ -329,8 +332,8 @@ impl CameraController let body = ¤t_system.bodies()[body_id]; self.update_orbit( camera, - body.position().cast().unwrap(), - body.radius(), + current_system.body_position(body).cast().unwrap(), + body.radius() * 2.0, dt); } None => self.update_pan(camera, dt) |
