summaryrefslogtreecommitdiffstats
path: root/src/tacmap
diff options
context:
space:
mode:
authorJon Santmyer <jon@jonsantmyer.com>2026-05-06 12:01:42 -0400
committerJon Santmyer <jon@jonsantmyer.com>2026-05-06 12:01:42 -0400
commit9788d9037ad7199701b1710c28559cb96bce5aec (patch)
treec490b40b1f0057c98c2b4bb3c2593f915313d14f /src/tacmap
parentd67fca88b17120566a93004c99dadeef0a61964b (diff)
downloadsystemic4x-9788d9037ad7199701b1710c28559cb96bce5aec.tar.gz
systemic4x-9788d9037ad7199701b1710c28559cb96bce5aec.tar.bz2
systemic4x-9788d9037ad7199701b1710c28559cb96bce5aec.zip
regenerate orbit lines based on system tick interval
Diffstat (limited to 'src/tacmap')
-rw-r--r--src/tacmap/body_render.rs24
-rw-r--r--src/tacmap/camera.rs6
-rw-r--r--src/tacmap/orbit_render.rs107
-rw-r--r--src/tacmap/render.rs4
4 files changed, 91 insertions, 50 deletions
diff --git a/src/tacmap/body_render.rs b/src/tacmap/body_render.rs
index 8b32532..92ac13f 100644
--- a/src/tacmap/body_render.rs
+++ b/src/tacmap/body_render.rs
@@ -1,7 +1,7 @@
use std::error::Error;
use crate::solar_system::Kilometers;
-use crate::timeman::Second;
+use crate::timeman::{SYSTEM_TICK_INTERVAL, Second};
use crate::wgpuctx::{WgpuCtx, pipeline::RenderPipelineBuilder};
use super::*;
@@ -92,6 +92,18 @@ impl BodyRenderer
return Ok(());
}
+ //Round to the nearest tick
+ 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 (_, bodies_buffer) = match &self.body_instance_buffer {
@@ -101,11 +113,11 @@ impl BodyRenderer
let bodies = solar_system.bodies();
let body_instances = bodies.iter().map(|body| {
- let position = body.position();
- let origin = match body.get_orbits() {
- Some(origin_id) => {
- let origin_body = &bodies[origin_id];
- origin_body.position()
+ let position = body.relative_position();
+ let origin = match body.get_orbit() {
+ Some(orbit) => {
+ let origin_body = &bodies[orbit.parent()];
+ origin_body.relative_position()
},
None => cgmath::Vector3::new(0.0, 0.0, 0.0)
};
diff --git a/src/tacmap/camera.rs b/src/tacmap/camera.rs
index 5efc24c..57856e2 100644
--- a/src/tacmap/camera.rs
+++ b/src/tacmap/camera.rs
@@ -4,7 +4,7 @@ use cgmath::{InnerSpace, Point3, Rad, Vector2, Vector3, perspective};
use winit::event::ElementState;
use winit::keyboard::KeyCode;
-use crate::solar_system::{self, BodyId, Kilometers, SolarSystem};
+use crate::solar_system::{self, Kilometers, SolarSystem};
use crate::ui;
use crate::wgpuctx::WgpuCtx;
@@ -16,7 +16,7 @@ pub struct Camera
yaw: Rad<f32>,
scale: f32,
- target: Option<solar_system::BodyId>,
+ target: Option<solar_system::body::BodyId>,
buffer: wgpu::Buffer,
staging_buffer: wgpu::Buffer,
@@ -166,7 +166,7 @@ impl Camera
pub fn set_target(
&mut self,
- target: Option<solar_system::BodyId>)
+ target: Option<solar_system::body::BodyId>)
{
if target == self.target { return; }
if !target.is_some() || !self.target.is_some() {
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(
diff --git a/src/tacmap/render.rs b/src/tacmap/render.rs
index fd93941..58efae0 100644
--- a/src/tacmap/render.rs
+++ b/src/tacmap/render.rs
@@ -3,10 +3,8 @@ use std::error::Error;
use wgpu::RenderPass;
-use crate::solar_system::Kilometers;
use crate::tacmap::camera::Camera;
-use crate::timeman::{DAY, SYSTEM_TICK_INTERVAL};
-use crate::{solar_system::{SolarSystem, SystemId}, timeman::Second, vertex::{self, Vertex}, wgpuctx::{WgpuCtx, pipeline::RenderPipelineBuilder}};
+use crate::wgpuctx::{WgpuCtx, pipeline::RenderPipelineBuilder};
#[derive(Debug, Clone)]
pub struct NeedsRebuildError;