diff options
| author | Jon Santmyer <jon@jonsantmyer.com> | 2026-05-10 13:29:56 -0400 |
|---|---|---|
| committer | Jon Santmyer <jon@jonsantmyer.com> | 2026-05-10 13:29:56 -0400 |
| commit | 7f63ec5c10eb7e8dd4edaabd1a6a437328911d39 (patch) | |
| tree | 36bd3d75ebc0c25256413c21a7cb28c9296953f5 /src/tacmap/fleet_render.rs | |
| parent | c9041e2e6fe59d6127bb1085b874e8e3cda8000e (diff) | |
| download | systemic4x-7f63ec5c10eb7e8dd4edaabd1a6a437328911d39.tar.gz systemic4x-7f63ec5c10eb7e8dd4edaabd1a6a437328911d39.tar.bz2 systemic4x-7f63ec5c10eb7e8dd4edaabd1a6a437328911d39.zip | |
fleets
Diffstat (limited to 'src/tacmap/fleet_render.rs')
| -rw-r--r-- | src/tacmap/fleet_render.rs | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/src/tacmap/fleet_render.rs b/src/tacmap/fleet_render.rs new file mode 100644 index 0000000..ba21318 --- /dev/null +++ b/src/tacmap/fleet_render.rs @@ -0,0 +1,177 @@ +use std::error::Error; + +use crate::fleet::FleetsManager; +use crate::solar_system::orbit::StaticOrbiter; +use crate::solar_system::{Kilometers}; +use crate::timeman::{Second}; +use crate::wgpuctx::{WgpuCtx, pipeline::RenderPipelineBuilder}; + +use super::*; + +pub struct FleetRenderer +{ + last_time: Option<Second>, + + pipeline: wgpu::RenderPipeline, + + fleet_instance_buffer: Option<(usize, wgpu::Buffer)> +} + +struct FleetInstance +{ + offset: cgmath::Vector3<Kilometers>, + origin: cgmath::Vector3<Kilometers>, + heading: cgmath::Vector2<cgmath::Rad<f32>> +} + +#[repr(C)] +#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] +struct FleetInstanceRaw +{ + rotmat: [[f32;3];3], + origin: [f32;3], + offset: [f32;3], +} + +impl FleetRenderer +{ + pub fn new( + wgpuctx: &WgpuCtx) + -> Self { + let shader = wgpuctx.create_shader( + wgpu::include_wgsl!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/assets/shaders/tacmap/fleet.wgsl") + )); + + let render_pipeline = RenderPipelineBuilder::new(&shader) + .add_bindgroup(&Camera::bindgroup_layout(wgpuctx)) + .add_vertex_layout(FleetInstanceRaw::descr()) + .cull_mode(None) + .build(Some("Tactical map fleet render pipeline"), wgpuctx); + + Self { + last_time: None, + pipeline: render_pipeline, + fleet_instance_buffer: None + } + } + + pub fn update( + &mut self, + wgpuctx: &WgpuCtx, + fleets_manager: &FleetsManager, + solar_system: &SolarSystem, + 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 }) { + return Ok(()); + } + + self.last_time = Some(time); + + if let Some((_, buffer)) = &self.fleet_instance_buffer { + buffer.destroy(); + self.fleet_instance_buffer = None; + } + + let fleets = solar_system.fleets(fleets_manager); + let fleets_instances = fleets.iter().filter_map(|id| { + let fleet = match fleets_manager.entry(*id) { + Some(fleet) => fleet, + None => { return None; } + }; + let heading = fleet.heading(); + let offset = fleet.offset_position(); + let origin = match fleet.orbit() { + Some(orbit) => { + let origin_body = solar_system.body(orbit.parent()); + origin_body.absolute_position(solar_system, time) + }, + None => cgmath::vec3(0.0, 0.0, 0.0) + }; + Some( + FleetInstance { + heading: *heading, + offset: *offset, + origin: origin + }.raw() + ) + }).collect::<Vec<_>>(); + let fleets_buffer = wgpuctx.create_buffer_init( + &wgpu::util::BufferInitDescriptor { + label: None, + contents: bytemuck::cast_slice(fleets_instances.as_slice()), + usage: wgpu::BufferUsages::VERTEX + }); + + self.fleet_instance_buffer = Some((fleets.len(), fleets_buffer)); + + Ok(()) + } + + pub fn render( + &self, + pass: &mut wgpu::RenderPass, + camera: &Camera) + { + let (num_fleets, fleets_buffer) = match &self.fleet_instance_buffer { + Some(tuple) => tuple, + None => return + }; + if *num_fleets == 0 { return; } + + pass.set_pipeline(&self.pipeline); + pass.set_bind_group(0, camera.bindgroup(), &[]); + + pass.set_vertex_buffer(0, fleets_buffer.slice(..)); + + pass.draw(0..6, 0..*num_fleets as _); + } +} // impl RenderState + +impl FleetInstance +{ + fn raw(&self) -> FleetInstanceRaw + { + FleetInstanceRaw { + rotmat: (cgmath::Matrix3::from_angle_x(self.heading.x) * + cgmath::Matrix3::from_angle_y(self.heading.y)) + .into(), + origin: [ + self.origin.x as f32, + self.origin.y as f32, + self.origin.z as f32 + ], + offset: [ + self.offset.x as f32, + self.offset.y as f32, + self.offset.z as f32 + ] + } + } +} // impl BodyInstance + +impl FleetInstanceRaw +{ + const ATTRIBS: [wgpu::VertexAttribute;5] = + wgpu::vertex_attr_array![ + 0 => Float32x3, 1 => Float32x3, 2 => Float32x3, + 3 => Float32x3, + 4 => 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::Instance, + attributes: &Self::ATTRIBS + } + } +} |
