diff options
Diffstat (limited to 'src/tacmap/camera.rs')
| -rw-r--r-- | src/tacmap/camera.rs | 100 |
1 files changed, 56 insertions, 44 deletions
diff --git a/src/tacmap/camera.rs b/src/tacmap/camera.rs index 57856e2..af163b8 100644 --- a/src/tacmap/camera.rs +++ b/src/tacmap/camera.rs @@ -1,16 +1,17 @@ use std::time::Duration; -use cgmath::{InnerSpace, Point3, Rad, Vector2, Vector3, perspective}; +use cgmath::{InnerSpace, Point3, Rad, Vector2, Vector3, Zero, perspective}; use winit::event::ElementState; use winit::keyboard::KeyCode; +use crate::solar_system::body::OrbitalBody; use crate::solar_system::{self, Kilometers, SolarSystem}; use crate::ui; use crate::wgpuctx::WgpuCtx; pub struct Camera { - abs_position: Vector3<Kilometers>, + origin_position: Vector3<Kilometers>, rel_position: Vector3<f32>, pitch: Rad<f32>, yaw: Rad<f32>, @@ -38,8 +39,10 @@ pub struct CameraUniform { view: [[f32;4];4], proj: [[f32;4];4], - pos: [f32;3], - scale: f32 + origin_pos: [f32;3], + _pad0: u32, + rel_pos: [f32;3], + scale: f32, } pub struct Projection @@ -94,7 +97,7 @@ impl Camera } ); Self { - abs_position: position.into(), + origin_position: position.into(), rel_position: Vector3::new(0.0, 0.0, 0.0), yaw: yaw.into(), pitch: pitch.into(), @@ -109,12 +112,12 @@ impl Camera pub fn get_scale(&self) -> f32 { self.scale } - pub fn get_abs_position(&self) -> Vector3<Kilometers> - { self.abs_position } + pub fn get_origin_position(&self) -> Vector3<Kilometers> + { self.origin_position } pub fn get_combined_position(&self) -> Vector3<Kilometers> { - self.abs_position + self.rel_position.map(|v| { v as f64 }) + self.origin_position + self.rel_position.map(|v| { v as f64 }) } pub fn get_rotation(&self) -> Vector2<Rad<f32>> @@ -170,7 +173,7 @@ impl Camera { if target == self.target { return; } if !target.is_some() || !self.target.is_some() { - self.abs_position = self.get_combined_position(); + self.origin_position = self.get_combined_position(); self.rel_position = Vector3::new(0.0, 0.0, 0.0); } self.target = target; @@ -180,21 +183,25 @@ impl Camera &self) -> cgmath::Matrix4<f32> { - let (yaw_sin, yaw_cos) = self.pitch.0.sin_cos(); - let (pitch_sin, pitch_cos) = self.yaw.0.sin_cos(); + let (yaw_sin, yaw_cos) = self.yaw.0.sin_cos(); + let (pitch_sin, pitch_cos) = self.pitch.0.sin_cos(); + + let eye_pos = cgmath::point3( + pitch_cos * yaw_cos, + pitch_sin, + pitch_cos * yaw_sin + ); if self.target.is_some() { cgmath::Matrix4::look_at_rh( - Point3::new(self.rel_position.x, self.rel_position.y, self.rel_position.z), - Point3::new(0.0, 0.0, 0.0), + eye_pos, + cgmath::point3(0.0, 0.0, 0.0), Vector3::unit_y()) }else{ cgmath::Matrix4::look_to_rh( - Point3::new(0.0, 0.0, 0.0), - Vector3::new( - pitch_cos * yaw_cos, - pitch_sin, - pitch_cos * yaw_sin + cgmath::point3(0.0, 0.0, 0.0), + cgmath::vec3( + eye_pos.x, eye_pos.y, eye_pos.z ).normalize(), Vector3::unit_y() ) @@ -209,10 +216,17 @@ impl Camera CameraUniform { view: (self.view_matrix()).into(), proj: projection.projection_matrix().into(), - pos: [ self.abs_position.x as f32, - self.abs_position.y as f32, - self.abs_position.z as f32 ], - scale: self.scale + origin_pos: [ + self.origin_position.x as f32, + self.origin_position.y as f32, + self.origin_position.z as f32 ], + rel_pos: [ + self.rel_position.x as f32, + self.rel_position.y as f32, + self.rel_position.z as f32 ], + scale: self.scale, + + _pad0: 0 } } } //impl Camera @@ -252,14 +266,25 @@ impl CameraController fn update_orbit( &mut self, camera: &mut Camera, - target: Vector3<Kilometers>, - target_radius: f32, + solar_system: &SolarSystem, + target: &OrbitalBody, dt: Duration) { + let target_radius = (target.radius() * 2.0).max(1.0); camera.scale *= 1.0 + ((self.scale_delta.y - self.scale_delta.x) * 0.1); camera.scale = f32::max(1e-16, f32::min(1.0 / target_radius, camera.scale)); - camera.abs_position = target; + match target.get_orbit() { + Some(orbit) => { + let parent = solar_system.body(orbit.parent()); + camera.origin_position = parent.absolute_position(solar_system); + camera.rel_position = target.relative_position().map(|v| { v as f32 }); + }, + None => { + camera.origin_position = target.absolute_position(solar_system); + camera.rel_position.set_zero(); + } + } let dt = dt.as_secs_f32(); let speed = 1.0; @@ -274,16 +299,6 @@ impl CameraController { camera.pitch.0 = polar_final; } camera.yaw.0 += azimuth_diff; - - let (az_sin, az_cos) = camera.yaw.0.sin_cos(); - let (p_sin, p_cos) = camera.pitch.0.sin_cos(); - - let radius = 1.0; - camera.rel_position = Vector3::new( - radius * p_cos * az_cos, - radius * p_sin, - radius * p_cos * az_sin - ); } fn update_pan( @@ -302,12 +317,9 @@ impl CameraController let right = Vector3::new(-yaw_sin, 0.0, yaw_cos).normalize(); let up = Vector3::new(0.0, 1.0, 0.0); - 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.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.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; @@ -320,14 +332,14 @@ impl CameraController ui_state: &mut ui::State, dt: Duration) { - match ui_state.camera_info.target { + match ui_state.camera_target { Some(body_id) => { let body = &solar_system.bodies()[body_id]; self.update_orbit( camera, - solar_system.body_position(body).cast().unwrap(), - (body.radius() * 2.0).max(1.0), + solar_system, + body, dt); } None => self.update_pan(camera, dt) |
