diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/main.rs | 9 | ||||
| -rw-r--r-- | src/solar_system.rs | 22 | ||||
| -rw-r--r-- | src/tacmap.rs | 71 | ||||
| -rw-r--r-- | src/tacmap/camera.rs | 33 | ||||
| -rw-r--r-- | src/tacmap/render.rs | 268 | ||||
| -rw-r--r-- | src/ui.rs | 11 | ||||
| -rw-r--r-- | src/ui/camera_info.rs | 12 | ||||
| -rw-r--r-- | src/wgpuctx/pipeline.rs | 19 | ||||
| -rw-r--r-- | src/window.rs | 36 |
9 files changed, 354 insertions, 127 deletions
diff --git a/src/main.rs b/src/main.rs index d872cc1..7a7e3a1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -64,7 +64,7 @@ impl GameState pub fn new() -> Self { let timeman = TimeMan::new(0); - let sol_system = match SolarSystem::new_from_known_star("sol") + let sol_system = match SolarSystem::new_from_known_star(0, "sol") { Ok(system) => system, Err(e) => panic!("Unable to create sol system : {}", e) @@ -139,9 +139,8 @@ impl ApplicationHandler for SystemicApp self.last_render_time = now; game_state.borrow_mut().update(delta_time); - { - window.update(game_state, delta_time); - } + window.update(game_state, delta_time); + match window.render(game_state) { Ok(_) => {} Err(wgpu::SurfaceError::Outdated | wgpu::SurfaceError::Lost) => { @@ -164,7 +163,7 @@ impl ApplicationHandler for SystemicApp }, .. } => { - window.keyboard_input(game_state, key_code, key_state); + window.keyboard_input(key_code, key_state); } _ => {} } diff --git a/src/solar_system.rs b/src/solar_system.rs index c98a0e8..cf6a36a 100644 --- a/src/solar_system.rs +++ b/src/solar_system.rs @@ -1,6 +1,6 @@ use serde::{Deserialize}; use crate::{GameState, known_stars::{KNOWN_STARS, StarNotFoundError}, timeman::{Second, TimeMan}}; -use std::{cell::RefCell, error::Error}; +use std::{cell::RefCell, error::Error, f64::consts::PI}; const GRAVITATIONAL_CONSTANT: f64 = 6.67408e-20; @@ -33,11 +33,13 @@ pub struct SerialOrbitalBody pub struct OrbitalBody { body: SerialOrbitalBody, + id: BodyId, position: Option<cgmath::Vector3<Kilometers>> } pub struct SolarSystem { + id: SystemId, name: String, bodies: Vec<OrbitalBody>, time: Option<Second> @@ -46,6 +48,7 @@ pub struct SolarSystem impl SolarSystem { pub fn new_from_csv( + id: SystemId, data: &'static str) -> Result<Self, Box<dyn Error>> { let data_reader = stringreader::StringReader::new(data); @@ -68,11 +71,13 @@ impl SolarSystem bodies.push(OrbitalBody { body: record, + id: bodies.len(), position: None }); } Ok(Self { + id: id, name: bodies[0].name().clone(), bodies: bodies, time: None @@ -80,15 +85,18 @@ impl SolarSystem } pub fn new_from_known_star( + id: SystemId, star: &'static str) -> Result<Self, Box<dyn Error>> { let star_csv = match KNOWN_STARS.get(star).copied() { Some(csv) => csv, None => return Err(Box::new(StarNotFoundError { star: star })) }; - SolarSystem::new_from_csv(star_csv) + SolarSystem::new_from_csv(id, star_csv) } + pub fn id(&self) -> SystemId { self.id } + pub fn name(&self) -> &String { &self.name } pub fn bodies(&self) @@ -140,18 +148,24 @@ impl SolarSystem impl OrbitalBody { + pub fn id(&self) -> BodyId { self.id } pub fn name(&self) -> &String { &self.body.name } pub fn radius(&self) -> f32 { self.body.radius as f32 } pub fn position(&self) -> cgmath::Vector3<f64> { self.position.unwrap() } + pub fn does_orbit(&self) -> bool { self.body.orbits.is_some() } + pub fn get_orbits(&self) -> Option<BodyId> { self.body.orbits } - fn calculate_orbit_at( + pub fn orbital_period(&self) -> Second + { ((self.body.semi_major_axis.powf(3.0) / self.body.sgp).sqrt() * std::f64::consts::TAU) as u64 } + + pub fn calculate_orbit_at( &self, time: Second) -> cgmath::Vector3<f64> { if self.body.orbits.is_none() { return cgmath::Vector3::<f64>::new(0.0, 0.0, 0.0); - } +} let eccentricity = self.body.eccentricity; diff --git a/src/tacmap.rs b/src/tacmap.rs index abae50e..de2ddcd 100644 --- a/src/tacmap.rs +++ b/src/tacmap.rs @@ -16,6 +16,7 @@ use crate::GameState; use crate::canvas::Canvas; use crate::solar_system::SolarSystem; use crate::solar_system::SystemId; +use crate::timeman::TimeMan; use crate::ui; use crate::wgpuctx::RenderPassBuilder; use crate::wgpuctx::SceneCtx; @@ -30,8 +31,11 @@ pub struct TacticalMap pmatrix: Projection, camera_controller: CameraController, - body_renderer: Option<(SystemId, BodyRenderer)>, - grid_renderer: GridRenderer + + system_for_render: Option<SystemId>, + body_renderer: BodyRenderer, + grid_renderer: GridRenderer, + orbit_renderer: OrbitRenderer } impl TacticalMap @@ -69,8 +73,11 @@ impl TacticalMap camera: camera, pmatrix: projection, camera_controller: CameraController::new(), - body_renderer: None, - grid_renderer: GridRenderer::new(wgpuctx) + + system_for_render: None, + body_renderer: BodyRenderer::new(wgpuctx), + grid_renderer: GridRenderer::new(wgpuctx), + orbit_renderer: OrbitRenderer::new(wgpuctx), } } @@ -86,7 +93,7 @@ impl TacticalMap pub fn update( &mut self, - game_state: &RefCell<GameState>, + solar_system: &SolarSystem, ui_state: &mut ui::State, dt: Duration) { @@ -95,12 +102,11 @@ impl TacticalMap ui_state.camera_info.camera_rot = Some(self.camera.get_rotation()); self.camera.set_target(ui_state.camera_info.target); - self.camera_controller.update(&mut self.camera, game_state, ui_state, dt); + self.camera_controller.update(&mut self.camera, solar_system, ui_state, dt); } pub fn keyboard_input( &mut self, - game_state: &RefCell<GameState>, key_code: KeyCode, key_state: ElementState) { @@ -110,41 +116,27 @@ impl TacticalMap pub fn draw( &mut self, wgpuctx: &WgpuCtx, - game_state: &RefCell<GameState>, - current_system: Option<SystemId>) - -> Result<(), wgpu::SurfaceError> + solar_system: &SolarSystem, + timeman: &TimeMan, + ) -> Result<(), wgpu::SurfaceError> { - let game_state = game_state.borrow(); - - let current_system_id = match current_system { - Some(system) => system, - None => return Ok(()) - }; - let solar_systems = game_state.solar_systems(); - let current_system = &solar_systems[current_system_id]; - self.camera.update_buffer(wgpuctx, &self.pmatrix); + + if self.system_for_render.is_none() + || self.system_for_render.unwrap() != solar_system.id() { - let body_renderer = match &mut self.body_renderer { - Some((id, render)) => { - if *id != current_system_id { - *id = current_system_id; - render.mark_to_rebuild(); - } - render - }, - None => { - let tmp = render::BodyRenderer::new(wgpuctx); - self.body_renderer = Some((current_system_id, tmp)); - &mut self.body_renderer.as_mut().unwrap().1 - } - }; + self.body_renderer.mark_to_rebuild(); + self.orbit_renderer.mark_to_rebuild(); + } + self.system_for_render = Some(solar_system.id()); //Update buffers for the current system and time. - body_renderer.rebuild(wgpuctx, current_system); - match body_renderer.update( - wgpuctx, current_system, &self.camera, - game_state.timeman().seconds()) + self.body_renderer.rebuild(wgpuctx, solar_system); + self.orbit_renderer.rebuild(wgpuctx, solar_system); + + self.orbit_renderer.update(wgpuctx, solar_system, timeman.seconds()); + match self.body_renderer.update( + wgpuctx, solar_system, timeman.seconds()) { Ok(()) => {}, Err(e) => println!("Tactical map render update error: {}", e) @@ -158,8 +150,9 @@ impl TacticalMap { let mut pass = pass_builder.build_from_scene(&mut scene); - self.grid_renderer.render(wgpuctx, &mut pass, &self.camera); - body_renderer.render(wgpuctx, &mut pass, &self.camera); + self.grid_renderer.render(&mut pass, &self.camera); + self.orbit_renderer.render(&mut pass, &self.camera); + self.body_renderer.render(&mut pass, &self.camera); } scene.submit(wgpuctx); diff --git a/src/tacmap/camera.rs b/src/tacmap/camera.rs index 895fa1e..ae9bcfa 100644 --- a/src/tacmap/camera.rs +++ b/src/tacmap/camera.rs @@ -3,7 +3,7 @@ use std::{cell::RefCell, time::Duration}; use cgmath::{EuclideanSpace, InnerSpace, Point2, Point3, Rad, Vector2, Vector3, Vector4, Zero, perspective}; use winit::{event::ElementState, keyboard::KeyCode}; -use crate::{GameState, solar_system::{self, Kilometers}, ui, wgpuctx::WgpuCtx}; +use crate::{GameState, solar_system::{self, Kilometers, SolarSystem}, 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), @@ -42,6 +42,7 @@ pub struct CameraUniform { view: [[f32;4];4], proj: [[f32;4];4], + pos: [f32;3], scale: f32 } @@ -68,7 +69,7 @@ impl Camera let buffer = wgpuctx.create_buffer( &wgpu::BufferDescriptor { label: Some("Camera buffer"), - size: 144, + size: size_of::<CameraUniform>() as _, usage: BufferUsages::UNIFORM | BufferUsages::COPY_DST, mapped_at_creation: false } @@ -77,7 +78,7 @@ impl Camera let staging_buffer = wgpuctx.create_buffer( &wgpu::wgt::BufferDescriptor { label: Some("Camera staging buffer"), - size: 144, + size: size_of::<CameraUniform>() as _, usage: BufferUsages::COPY_SRC | BufferUsages::COPY_DST, mapped_at_creation: false } @@ -212,6 +213,9 @@ 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 } } @@ -256,6 +260,9 @@ impl CameraController target_radius: f32, 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 / target_radius, camera.scale)); + camera.abs_position = target; let dt = dt.as_secs_f32(); @@ -294,6 +301,9 @@ impl CameraController let dt = dt.as_secs_f32(); let speed = 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, camera.scale)); + let (yaw_sin, yaw_cos) = camera.yaw.0.sin_cos(); let forward = Vector3::new(yaw_cos, 0.0, yaw_sin).normalize(); let right = Vector3::new(-yaw_sin, 0.0, yaw_cos).normalize(); @@ -313,26 +323,17 @@ impl CameraController pub fn update( &mut self, camera: &mut Camera, - game_state: &RefCell<GameState>, + solar_system: &SolarSystem, 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(1e-6, camera.scale)); - match ui_state.camera_info.target { Some(body_id) => { - let game_state = game_state.borrow(); - let solar_systems = game_state.solar_systems(); - let current_system = match ui_state.current_system { - Some(id) => &solar_systems[id], - None => return -}; - - let body = ¤t_system.bodies()[body_id]; + + let body = &solar_system.bodies()[body_id]; self.update_orbit( camera, - current_system.body_position(body).cast().unwrap(), + solar_system.body_position(body).cast().unwrap(), (body.radius() * 2.0).max(1.0), dt); } diff --git a/src/tacmap/render.rs b/src/tacmap/render.rs index c1256ff..c2bd354 100644 --- a/src/tacmap/render.rs +++ b/src/tacmap/render.rs @@ -38,11 +38,9 @@ pub struct BodyRenderer { needs_rebuild: bool, last_time: Option<Second>, - last_pos: Option<cgmath::Vector3<Kilometers>>, pipeline: wgpu::RenderPipeline, - body_vertex_buffer: wgpu::Buffer, body_instance_buffer: Option<(usize, wgpu::Buffer)> } @@ -51,34 +49,22 @@ impl BodyRenderer pub fn new( wgpuctx: &WgpuCtx) -> Self { - let quad_vertices = vertex::QUAD_VERTICES; - - let body_vertex_buffer = wgpuctx.create_buffer_init( - &wgpu::util::BufferInitDescriptor { - label: None, - contents: bytemuck::cast_slice(quad_vertices), - usage: wgpu::BufferUsages::VERTEX - } - ); - let shader = wgpuctx.create_shader( wgpu::include_wgsl!(concat!( env!("CARGO_MANIFEST_DIR"), - "/assets/shaders/tacbody.wgsl") + "/assets/shaders/tacmap/body.wgsl") )); let render_pipeline = RenderPipelineBuilder::new(&shader) .add_bindgroup(&Camera::bindgroup_layout(wgpuctx)) - .add_vertex_layout(Vertex::descr()) .add_vertex_layout(BodyInstanceRaw::descr()) + .cull_mode(None) .build(Some("Tactical map render pipeline"), wgpuctx); Self { needs_rebuild: true, last_time: None, - last_pos: None, pipeline: render_pipeline, - body_vertex_buffer, body_instance_buffer: None } } @@ -94,6 +80,7 @@ impl BodyRenderer if self.body_instance_buffer.is_some() && !self.needs_rebuild { return; } + self.needs_rebuild = false; match self.body_instance_buffer.as_mut() { Some(buffer) => { @@ -117,7 +104,6 @@ impl BodyRenderer ); self.last_time = None; - self.last_pos = None; self.body_instance_buffer = Some((bodies.len(), buffer)); } @@ -125,20 +111,16 @@ impl BodyRenderer &mut self, wgpuctx: &WgpuCtx, solar_system: &SolarSystem, - camera: &Camera, time: Second) -> Result<(), Box<dyn Error>> { //If the last updated time is the same, we don't need to update //the positions of all the bodies. if self.last_time.is_some_and(|last_time| { last_time == time }) { - if self.last_pos.is_some_and(|last_pos| { last_pos == camera.get_abs_position() }) { - return Ok(()) - } + return Ok(()); } self.last_time = Some(time); - self.last_pos = Some(camera.get_abs_position()); let (_, bodies_buffer) = match &self.body_instance_buffer { Some(tuple) => tuple, @@ -149,20 +131,18 @@ impl BodyRenderer let body_instances = bodies.iter().map(|body| { let position = solar_system.body_position(body); BodyInstance { - position: (position - self.last_pos.unwrap()), + position: position, radius: body.radius() }.raw() }).collect::<Vec<_>>(); wgpuctx.queue().write_buffer(bodies_buffer, 0, bytemuck::cast_slice(&body_instances)); - //Update the canvas texture. Ok(()) } pub fn render( &self, - wgpuctx: &WgpuCtx, pass: &mut RenderPass, camera: &Camera) { @@ -174,8 +154,7 @@ impl BodyRenderer pass.set_pipeline(&self.pipeline); pass.set_bind_group(0, camera.bindgroup(), &[]); - pass.set_vertex_buffer(0, self.body_vertex_buffer.slice(..)); - pass.set_vertex_buffer(1, bodies_buffer.slice(..)); + pass.set_vertex_buffer(0, bodies_buffer.slice(..)); pass.draw(0..6, 0..num_bodies.clone() as _); } @@ -205,12 +184,12 @@ impl BodyInstanceRaw attributes: &[ wgpu::VertexAttribute { offset: 0, - shader_location: 2, + shader_location: 0, format: wgpu::VertexFormat::Float32x3 }, wgpu::VertexAttribute { offset: mem::size_of::<[f32;3]>() as wgpu::BufferAddress, - shader_location: 3, + shader_location: 1, format: wgpu::VertexFormat::Float32 } ] @@ -246,7 +225,6 @@ impl GridRenderer pub fn render( &self, - wgpuctx: &WgpuCtx, pass: &mut RenderPass, camera: &Camera ) @@ -256,4 +234,234 @@ impl GridRenderer pass.draw(0..6, 0..1); } +} //impl GridRenderer + +pub struct OrbitRenderer +{ + needs_rebuild: bool, + last_time: Option<Second>, + + pipeline: wgpu::RenderPipeline, + + orbit_vertex_buffers: Option<Vec<(usize, Option<wgpu::Buffer>)>>, + origin_buffer: Option<wgpu::Buffer>, + origin_bind_group: Option<wgpu::BindGroup>, + origin_bind_group_layout: wgpu::BindGroupLayout +} + +impl OrbitRenderer +{ + pub fn new( + wgpuctx: &WgpuCtx) + -> Self { + let shader = wgpuctx.create_shader( + wgpu::include_wgsl!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/assets/shaders/tacmap/orbit.wgsl") + )); + + let origin_bind_group_layout = wgpuctx.device().create_bind_group_layout( + &wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStages::VERTEX, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Storage { read_only: true }, + has_dynamic_offset: false, + min_binding_size: None + }, + count: None + } + ] + } + ); + + let render_pipeline = RenderPipelineBuilder::new(&shader) + .add_bindgroup(&Camera::bindgroup_layout(wgpuctx)) + .add_bindgroup(&origin_bind_group_layout) + .add_vertex_layout(OrbitVertex::descr()) + .primitive_topology(wgpu::PrimitiveTopology::TriangleStrip) + .cull_mode(None) + .build(Some("Tactical map orbit render pipeline"), wgpuctx); + + Self { + needs_rebuild: true, + last_time: None, + pipeline: render_pipeline, + orbit_vertex_buffers: None, + origin_buffer: None, + origin_bind_group: None, + origin_bind_group_layout: origin_bind_group_layout + } + } + + pub fn mark_to_rebuild(&mut self) + { self.needs_rebuild = true; } + + pub fn rebuild( + &mut self, + wgpuctx: &WgpuCtx, + solar_system: &SolarSystem) + { + if self.orbit_vertex_buffers.is_some() && !self.needs_rebuild { + return; + } + self.needs_rebuild = false; + + match &self.orbit_vertex_buffers { + Some(buffers) => { + for buffer in buffers { + match &buffer.1 { + Some(v) => v.destroy(), + None => {} + } + } + self.orbit_vertex_buffers = None; + }, + None => {} + }; + + //From the solar system's bodies, calculate the orbits. + let bodies = solar_system.bodies(); + + match &self.origin_buffer { + Some(buffer) => { + buffer.destroy(); + } + None => {} + }; + let origin_buffer = wgpuctx.create_buffer( + &wgpu::BufferDescriptor { + label: None, + size: (std::mem::size_of::<[f32;3]>() * bodies.len()) as _, + usage: wgpu::BufferUsages::COPY_DST + | wgpu::BufferUsages::STORAGE, + mapped_at_creation: false + } + ); + + self.origin_bind_group = Some(wgpuctx.device().create_bind_group( + &wgpu::BindGroupDescriptor { + label: None, + layout: &self.origin_bind_group_layout, + entries: &[ + wgpu::BindGroupEntry { + binding: 0, + resource: origin_buffer.as_entire_binding() + } + ] + } + )); + self.origin_buffer = Some(origin_buffer); + + self.orbit_vertex_buffers = Some(bodies.iter().map(|body| { + if !body.does_orbit() { return (0, None); } + + let period = body.orbital_period(); + let period_interval = period as f64 / 360.0; + + let mut points = vec![ + OrbitVertex::default();361*2]; + for i in 0..361 { + let position = body.calculate_orbit_at( + (i as f64 * period_interval) as u64); + + points[i*2].origin_id = body.get_orbits().unwrap() as _; + points[i*2].position = [ + position.x as f32, + position.y as f32, + position.z as f32 + ]; + points[(i*2)+1] = points[i*2].clone(); + } + let buffer = wgpuctx.create_buffer_init( + &wgpu::util::BufferInitDescriptor { + label: None, + usage: wgpu::BufferUsages::VERTEX, + contents: bytemuck::cast_slice(&points) + } + ); + (361*2, Some(buffer)) + }).collect::<Vec<_>>()); + } + + pub fn update( + &mut self, + wgpuctx: &WgpuCtx, + solar_system: &SolarSystem, + time: Second) + { + if self.last_time.is_some_and(|t| { t == time }) { + return; + } + + self.last_time = Some(time); + let positions = solar_system.bodies().iter().map(|body| { + let pos = solar_system.body_position(body); + [ pos.x as f32, pos.y as f32, pos.z as f32 ] + }).collect::<Vec<_>>(); + + match &self.origin_buffer { + Some(buffer) => { + wgpuctx.queue().write_buffer(buffer, 0, bytemuck::cast_slice(&positions)); + }, + None => { return; } + }; + } + + pub fn render( + &self, + pass: &mut RenderPass, + camera: &Camera) + { + let buffers = match &self.orbit_vertex_buffers { + Some(v) => v, + None => return + }; + + pass.set_pipeline(&self.pipeline); + pass.set_bind_group(0, camera.bindgroup(), &[]); + + match &self.origin_bind_group { + Some(bind_group) => { pass.set_bind_group(1, bind_group, &[]); }, + None => { return; } + } + + for (num_points, buffer) in buffers { + match &buffer { + Some(buffer) => { + pass.set_vertex_buffer(0, buffer.slice(..)); + pass.draw(0..(*num_points as u32), 0..1); + }, + None => {} + } + } + } +} + +#[repr(C)] +#[derive(Copy, Clone, Default, Debug, bytemuck::Pod, bytemuck::Zeroable)] +pub struct OrbitVertex +{ + pub origin_id: u32, + pub position: [f32;3] +} + +impl OrbitVertex +{ + const ATTRIBS: [wgpu::VertexAttribute;2] = + wgpu::vertex_attr_array![0 => Uint32, 1 => Float32x3]; + + pub fn descr() + -> wgpu::VertexBufferLayout<'static> { + use std::mem; + + wgpu::VertexBufferLayout { + array_stride: mem::size_of::<Self>() as wgpu::BufferAddress, + step_mode: wgpu::VertexStepMode::Vertex, + attributes: &Self::ATTRIBS + } + } } @@ -65,15 +65,14 @@ impl State ); } }); - - let current_system = match state.current_system { - Some(id) => &solar_systems[id], - None => return - }; }); ui.horizontal(|ui| { - ui.label(format!("Time: {: <16}", TimeMan::format_duration(game_state.timeman().seconds()))); + let time_str = TimeMan::format_duration(game_state.timeman().seconds()); + ui.label( + egui::RichText::new(format!("Time: {: >16}", time_str)) + .font(egui::FontId::monospace(12.0)) + ); let button_seconds = [ 1, diff --git a/src/ui/camera_info.rs b/src/ui/camera_info.rs index 35cd54b..ccd06c5 100644 --- a/src/ui/camera_info.rs +++ b/src/ui/camera_info.rs @@ -28,7 +28,9 @@ impl CameraWindowState let current_system = &game_state.solar_systems()[ui_state.current_system.unwrap()]; - egui::Window::new("Camera Info").show(eguictx.context(), |ui| { + egui::Window::new("Debug Camera Info") + .title_bar(false) + .show(eguictx.context(), |ui| { ui.vertical(|ui| { let selected_body_label = match camera_state.target { Some(id) => current_system.bodies()[id].name(), @@ -50,14 +52,6 @@ impl CameraWindowState }); ui.label(format!("Scale: {}", camera_state.camera_scale)); - match camera_state.camera_pos { - Some(pos) => { ui.label(format!("Pos x:{:^10} y:{:^10} z:{:^10}", - pos.x, - pos.y, - pos.z - )); }, - None => {} - } match camera_state.camera_rot { Some(rot) => { ui.label(format!("pitch:{:^10} yaw:{:^10}", diff --git a/src/wgpuctx/pipeline.rs b/src/wgpuctx/pipeline.rs index 0811800..d698ac4 100644 --- a/src/wgpuctx/pipeline.rs +++ b/src/wgpuctx/pipeline.rs @@ -14,7 +14,8 @@ pub struct RenderPipelineBuilder<'a> vertex_buffer_layouts: Vec<wgpu::VertexBufferLayout<'a>>, - cull_mode: Option<wgpu::Face> + cull_mode: Option<wgpu::Face>, + primitive_topology: wgpu::PrimitiveTopology } impl<'a> RenderPipelineBuilder<'a> @@ -34,7 +35,8 @@ impl<'a> RenderPipelineBuilder<'a> vertex_buffer_layouts: Vec::new(), - cull_mode: Some(wgpu::Face::Back) + cull_mode: Some(wgpu::Face::Back), + primitive_topology: wgpu::PrimitiveTopology::TriangleList } } @@ -61,6 +63,13 @@ impl<'a> RenderPipelineBuilder<'a> self.cull_mode = mode; self } + pub fn primitive_topology( + mut self, + topology: wgpu::PrimitiveTopology + ) -> Self { + self.primitive_topology = topology; self + } + pub fn build( self, label: Option<&'static str>, @@ -109,8 +118,10 @@ impl<'a> RenderPipelineBuilder<'a> })], }), primitive: wgpu::PrimitiveState { - topology: wgpu::PrimitiveTopology::TriangleList, - strip_index_format: None, + topology: self.primitive_topology, + strip_index_format: if self.primitive_topology.is_strip() { + Some(wgpu::IndexFormat::Uint32) } else { + None }, front_face: wgpu::FrontFace::Ccw, cull_mode: self.cull_mode, polygon_mode: wgpu::PolygonMode::Fill, diff --git a/src/window.rs b/src/window.rs index 3b090ff..ce1b555 100644 --- a/src/window.rs +++ b/src/window.rs @@ -67,24 +67,27 @@ impl GameWindow game_state: &RefCell<GameState>, dt: Duration) { - { - let mut game_state = game_state.borrow_mut(); - if self.ui_state.do_auto_tick { - game_state.timeman.auto_tick = self.ui_state.auto_time; - }else{ - game_state.timeman.auto_tick = None; - } + let mut game_state = game_state.borrow_mut(); + if self.ui_state.do_auto_tick { + game_state.timeman.auto_tick = self.ui_state.auto_time; + }else{ + game_state.timeman.auto_tick = None; } - self.tactical_map.update(game_state, &mut self.ui_state, dt); + + let current_system = match self.ui_state.current_system { + Some(id) => &game_state.solar_systems()[id], + None => { return; } + }; + + self.tactical_map.update(current_system, &mut self.ui_state, dt); } pub fn keyboard_input( &mut self, - game_state: &RefCell<GameState>, key_code: KeyCode, key_state: ElementState) { - self.tactical_map.keyboard_input(game_state, key_code, key_state); + self.tactical_map.keyboard_input(key_code, key_state); } pub fn render( @@ -95,10 +98,15 @@ impl GameWindow return Ok(()); } - self.tactical_map.draw( - &self.wgpuctx, - game_state, - self.ui_state.current_system)?; + if self.ui_state.current_system.is_some() { + let game_state = game_state.borrow(); + let current_system = &game_state.solar_systems()[self.ui_state.current_system.unwrap()]; + + self.tactical_map.draw( + &self.wgpuctx, + current_system, + game_state.timeman())?; + } let view = self.wgpuctx.prepare_surface(&wgpu::TextureViewDescriptor::default())?; let mut scene = SceneCtx::from_view_default(&self.wgpuctx, &view, Some("Systemic window scene")); |
