diff --git a/simulator/src/main.rs b/simulator/src/main.rs index eefe249..daaec28 100644 --- a/simulator/src/main.rs +++ b/simulator/src/main.rs @@ -1,5 +1,7 @@ use std::cmp::max; -use std::sync::Arc; +use std::sync::{Arc, RwLock}; +use std::thread; +use std::time::Duration; use cgmath::num_traits::ToPrimitive; use cgmath::Rotation3; use pollster::FutureExt; @@ -10,6 +12,7 @@ use winit::dpi::PhysicalSize; use winit::event::WindowEvent; use winit::event_loop::{ActiveEventLoop, EventLoop}; use winit::window::{Window, WindowId}; +use solar_engine::{Body, Simulator}; pub async fn run() { let event_loop = EventLoop::new().unwrap(); @@ -154,6 +157,8 @@ struct State<'a> { num_vertices: u32, num_indices: u32, + + simulator: Arc>, } impl<'a> State<'a> { @@ -175,21 +180,50 @@ impl<'a> State<'a> { let num_vertices = VERTICES.len() as u32; let num_indices = INDICES.len() as u32; - let instances = vec![ - RenderInstance { - position: cgmath::Vector3::new(0.0, 0.0, 0.0), + let mut sim = Simulator::new(60.0 * 60.0 * 24.0); + sim.add_body(Body { + name: "Sun".to_string(), + position: [0.0, 0.0], + velocity: [0.0, 0.0], + mass: 1.989e30, + }); + sim.add_body(Body { + name: "Earth".to_string(), + position: [1.496e11, 0.0], + velocity: [0.0, 29780.0], + mass: 5.972e24, + }); + + let simulator = Arc::new(RwLock::new(sim)); + + let sim_clone = simulator.clone(); + thread::spawn(move || { + loop { + { + let mut sim = sim_clone.write().unwrap(); + sim.step(); + } + thread::sleep(Duration::from_millis(16)); + } + }); + + let instances = { + let sim = simulator.read().unwrap(); + sim.bodies.iter().map(|b| RenderInstance { + position: cgmath::Vector3::new( + (b.position[0] / 1.496e11) as f32, + (b.position[1] / 1.496e11) as f32, + 0.0, + ), rotation: cgmath::Quaternion::from_angle_z(cgmath::Deg(0.0)), - }, - RenderInstance { - position: cgmath::Vector3::new(1.0, 1.0, 0.0), - rotation: cgmath::Quaternion::from_angle_z(cgmath::Deg(45.0)), - }, - ]; + }).collect::>() + }; + let instance_data: Vec = instances.iter().map(RenderInstance::to_raw).collect(); let instance_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { label: Some("Instance Buffer"), contents: bytemuck::cast_slice(&instance_data), - usage: wgpu::BufferUsages::VERTEX, + usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST, }); Self { @@ -209,6 +243,8 @@ impl<'a> State<'a> { num_vertices, num_indices, + + simulator, } } @@ -217,7 +253,17 @@ impl<'a> State<'a> { } fn update(&mut self) { - // TODO: Update logic here + let updated_instances: Vec = { + let sim = self.simulator.read().unwrap(); + sim.bodies.iter().map(|b| RenderInstance { + position: cgmath::Vector3::new((b.position[0] / 1.496e11) as f32, (b.position[1] / 1.496e11) as f32, 0.0), + rotation: cgmath::Quaternion::from_angle_z(cgmath::Deg(0.0)), + }).collect() + }; + + let instance_data: Vec = updated_instances.iter().map(RenderInstance::to_raw).collect(); + self.queue.write_buffer(&self.instance_buffer, 0, bytemuck::cast_slice(&instance_data)); + self.instances = updated_instances; } fn create_index_buffer(device: &Device) -> wgpu::Buffer { @@ -380,12 +426,14 @@ impl<'a> State<'a> { occlusion_query_set: None, timestamp_writes: None, }); - + render_pass.set_pipeline(&self.render_pipeline); render_pass.set_vertex_buffer(0, self.vertex_buffer.slice(..)); - render_pass.set_vertex_buffer(1, self.instance_buffer.slice(..)); render_pass.set_index_buffer(self.index_buffer.slice(..), wgpu::IndexFormat::Uint16); - render_pass.draw_indexed(0..self.num_indices, 0, 0..self.instances.len() as u32); + if !self.instances.is_empty() { + render_pass.set_vertex_buffer(1, self.instance_buffer.slice(..)); + render_pass.draw_indexed(0..self.num_indices, 0, 0..self.instances.len() as u32); + } } self.queue.submit(std::iter::once(encoder.finish()));