diff options
Diffstat (limited to 'src/tacmap/orbit_render.rs')
| -rw-r--r-- | src/tacmap/orbit_render.rs | 107 |
1 files changed, 69 insertions, 38 deletions
diff --git a/src/tacmap/orbit_render.rs b/src/tacmap/orbit_render.rs index a6a90d1..c003366 100644 --- a/src/tacmap/orbit_render.rs +++ b/src/tacmap/orbit_render.rs @@ -1,6 +1,8 @@ +use std::error::Error; + use super::*; -use crate::solar_system::BodyId; +use crate::solar_system::body::{BodyId, OrbitalBody}; use crate::timeman::{SYSTEM_TICK_INTERVAL, Second}; use crate::wgpuctx::{WgpuCtx, pipeline::RenderPipelineBuilder}; @@ -68,6 +70,52 @@ impl OrbitRenderer pub fn mark_to_rebuild(&mut self) { self.needs_rebuild = true; } + fn create_orbit_buffer_for_body( + &self, + wgpuctx: &WgpuCtx, + body: &OrbitalBody, + time: Second) + -> (usize, Option<wgpu::Buffer>) + { + let orbit = match body.get_orbit() { + Some(orbit) => orbit, + None => return (0, None) + }; + + let period = body.orbital_period(); + + let num_points = ((period / (SYSTEM_TICK_INTERVAL)) as usize).clamp(90, 360); + let period_interval = period as f64 / num_points as f64; + + let mut points = vec![ + OrbitVertex::default();(num_points+1)*2]; + + for i in 0..num_points { + let position = body.calculate_orbit_at( + time + (i as f64 * period_interval) as Second); + + points[i*2].origin_id = orbit.parent() as _; + points[i*2].position = [ + position.x as f32, + position.y as f32, + position.z as f32 + ]; + + points[(i*2)+1] = points[i*2]; + } + points[num_points*2] = points[0]; + points[num_points*2+1] = points[1]; + + let buffer = wgpuctx.create_buffer_init( + &wgpu::util::BufferInitDescriptor { + label: None, + usage: wgpu::BufferUsages::VERTEX, + contents: bytemuck::cast_slice(&points) + } + ); + ((num_points+1)*2, Some(buffer)) + } + pub fn rebuild( &mut self, wgpuctx: &WgpuCtx, @@ -123,41 +171,6 @@ impl OrbitRenderer } )); 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 num_points = ((period / (SYSTEM_TICK_INTERVAL)) as usize).clamp(180, 360*4); - let period_interval = period as f64 / num_points as f64; - - let mut points = vec![ - OrbitVertex::default();(num_points+1)*2]; - for i in 0..num_points { - let position = body.calculate_orbit_at( - (i as f64 * period_interval) as Second); - - 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(); - } - points[num_points*2] = points[0].clone(); - points[num_points*2+1] = points[1].clone(); - - let buffer = wgpuctx.create_buffer_init( - &wgpu::util::BufferInitDescriptor { - label: None, - usage: wgpu::BufferUsages::VERTEX, - contents: bytemuck::cast_slice(&points) - } - ); - ((num_points+1)*2, Some(buffer)) - }).collect::<Vec<_>>()); } pub fn update( @@ -165,11 +178,23 @@ impl OrbitRenderer wgpuctx: &WgpuCtx, solar_system: &SolarSystem, time: Second) + -> Result<(), Box<dyn Error>> { if self.last_time.is_some_and(|t| { t == time }) { - return; + return Ok(()); } + let tick_time = match self.last_time { + Some(last_time) => { + let this_tick = time / SYSTEM_TICK_INTERVAL; + let last_tick = last_time / SYSTEM_TICK_INTERVAL; + + if this_tick == last_tick { return Ok(()) } + this_tick * SYSTEM_TICK_INTERVAL + } + None => 0 + }; + self.last_time = Some(time); let positions = solar_system.bodies().iter().map(|body| { let pos = solar_system.body_position(body); @@ -180,8 +205,14 @@ impl OrbitRenderer Some(buffer) => { wgpuctx.queue().write_buffer(buffer, 0, bytemuck::cast_slice(&positions)); }, - None => { return; } + None => { return Err(Box::new(NeedsRebuildError)); } }; + + let bodies = solar_system.bodies(); + self.orbit_vertex_buffers = Some(bodies.iter().map(|body| { + self.create_orbit_buffer_for_body(wgpuctx, body, tick_time) + }).collect::<Vec<_>>()); + Ok(()) } pub fn render( |
