Added circles and geometries

This commit is contained in:
Verox001 2025-05-04 13:21:36 +02:00
parent 7eacf0d0a5
commit e709e2dd3f

View File

@ -1,4 +1,5 @@
use std::cmp::max; use std::cmp::max;
use std::collections::HashMap;
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
use std::thread; use std::thread;
use std::time::Duration; use std::time::Duration;
@ -21,11 +22,24 @@ pub async fn run() {
let _ = event_loop.run_app(&mut window_state); let _ = event_loop.run_app(&mut window_state);
} }
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
enum Shape {
Polygon,
Circle,
}
struct Geometry {
vertex_buffer: wgpu::Buffer,
index_buffer: wgpu::Buffer,
index_count: u32,
}
struct RenderInstance { struct RenderInstance {
position: cgmath::Vector3<f32>, position: cgmath::Vector3<f32>,
rotation: cgmath::Quaternion<f32>, rotation: cgmath::Quaternion<f32>,
color: [f32; 3], color: [f32; 3],
scale: f32 scale: f32,
shape: Shape,
} }
impl RenderInstance { impl RenderInstance {
@ -83,20 +97,6 @@ impl Vertex {
} }
} }
const VERTICES: &[Vertex] = &[
Vertex { position: [-0.0868241, 0.49240386, 0.0], color: [0.5, 0.0, 0.5] },
Vertex { position: [-0.49513406, 0.06958647, 0.0], color: [0.5, 0.0, 0.5] },
Vertex { position: [-0.21918549, -0.44939706, 0.0], color: [0.5, 0.0, 0.5] },
Vertex { position: [0.35966998, -0.3473291, 0.0], color: [0.5, 0.0, 0.5] },
Vertex { position: [0.44147372, 0.2347359, 0.0], color: [0.5, 0.0, 0.5] },
];
const INDICES: &[u16] = &[
0, 1, 4,
1, 2, 4,
2, 3, 4,
];
struct StateApplication<'a> { struct StateApplication<'a> {
state: Option<State<'a>>, state: Option<State<'a>>,
} }
@ -148,6 +148,26 @@ impl<'a> ApplicationHandler for StateApplication<'a>{
} }
} }
fn create_circle_vertices(segment_count: usize, radius: f32, color: [f32; 3]) -> (Vec<Vertex>, Vec<u16>) {
let mut vertices = vec![Vertex { position: [0.0, 0.0, 0.0], color }];
let mut indices = vec![];
for i in 0..=segment_count {
let theta = (i as f32) / (segment_count as f32) * std::f32::consts::TAU;
let x = radius * theta.cos();
let y = radius * theta.sin();
vertices.push(Vertex { position: [x, y, 0.0], color });
}
for i in 1..=segment_count {
indices.push(0);
indices.push(i as u16);
indices.push((i % segment_count + 1) as u16);
}
(vertices, indices)
}
struct State<'a> { struct State<'a> {
surface: Surface<'a>, surface: Surface<'a>,
device: Device, device: Device,
@ -156,16 +176,13 @@ struct State<'a> {
size: PhysicalSize<u32>, size: PhysicalSize<u32>,
window: Arc<Window>, window: Arc<Window>,
render_pipeline: wgpu::RenderPipeline, render_pipeline: wgpu::RenderPipeline,
vertex_buffer: wgpu::Buffer,
index_buffer: wgpu::Buffer,
instances: Vec<RenderInstance>, instances: Vec<RenderInstance>,
instance_buffer: wgpu::Buffer, instance_buffer: wgpu::Buffer,
num_vertices: u32, geometries: HashMap<Shape, Geometry>,
num_indices: u32,
simulator: Arc<RwLock<Simulator>>, simulator: Arc<RwLock<Simulator>>,
} }
@ -183,11 +200,51 @@ impl<'a> State<'a> {
surface.configure(&device, &config); surface.configure(&device, &config);
let render_pipeline = Self::create_render_pipeline(&device, &config); let render_pipeline = Self::create_render_pipeline(&device, &config);
let vertex_buffer = Self::create_vertex_buffer(&device);
let index_buffer = Self::create_index_buffer(&device);
let num_vertices = VERTICES.len() as u32; let mut geometries = HashMap::new();
let num_indices = INDICES.len() as u32; let polygon_vertices = vec![
Vertex { position: [-0.0868241, 0.49240386, 0.0], color: [0.5, 0.0, 0.5] },
Vertex { position: [-0.49513406, 0.06958647, 0.0], color: [0.5, 0.0, 0.5] },
Vertex { position: [-0.21918549, -0.44939706, 0.0], color: [0.5, 0.0, 0.5] },
Vertex { position: [0.35966998, -0.3473291, 0.0], color: [0.5, 0.0, 0.5] },
Vertex { position: [0.44147372, 0.2347359, 0.0], color: [0.5, 0.0, 0.5] },
];
let polygon_indices = vec![0, 1, 4, 1, 2, 4, 2, 3, 4];
let polygon_vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Polygon Vertex Buffer"),
contents: bytemuck::cast_slice(&polygon_vertices),
usage: wgpu::BufferUsages::VERTEX,
});
let polygon_index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Polygon Index Buffer"),
contents: bytemuck::cast_slice(&polygon_indices),
usage: wgpu::BufferUsages::INDEX,
});
geometries.insert(Shape::Polygon, Geometry {
vertex_buffer: polygon_vertex_buffer,
index_buffer: polygon_index_buffer,
index_count: polygon_indices.len() as u32,
});
let (circle_vertices, circle_indices) = create_circle_vertices(32, 0.5, [0.5, 0.5, 0.5]);
let circle_vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Circle Vertex Buffer"),
contents: bytemuck::cast_slice(&circle_vertices),
usage: wgpu::BufferUsages::VERTEX,
});
let circle_index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Circle Index Buffer"),
contents: bytemuck::cast_slice(&circle_indices),
usage: wgpu::BufferUsages::INDEX,
});
geometries.insert(Shape::Circle, Geometry {
vertex_buffer: circle_vertex_buffer,
index_buffer: circle_index_buffer,
index_count: circle_indices.len() as u32,
});
let mut sim = Simulator::new(60.0 * 60.0 * 24.0); let mut sim = Simulator::new(60.0 * 60.0 * 24.0);
sim.add_body(Body { sim.add_body(Body {
@ -231,6 +288,7 @@ impl<'a> State<'a> {
_ => [0.5, 0.5, 0.5], _ => [0.5, 0.5, 0.5],
}, },
scale: 0.1, scale: 0.1,
shape: Shape::Circle
}).collect::<Vec<_>>() }).collect::<Vec<_>>()
}; };
@ -248,16 +306,12 @@ impl<'a> State<'a> {
config, config,
size, size,
window: window_arc, window: window_arc,
render_pipeline, render_pipeline,
vertex_buffer, geometries,
index_buffer,
instances, instances,
instance_buffer, instance_buffer,
num_vertices,
num_indices,
simulator, simulator,
} }
@ -279,6 +333,7 @@ impl<'a> State<'a> {
_ => [0.5, 0.5, 0.5], _ => [0.5, 0.5, 0.5],
}, },
scale: 0.5, scale: 0.5,
shape: Shape::Circle
}).collect() }).collect()
}; };
@ -287,26 +342,6 @@ impl<'a> State<'a> {
self.instances = updated_instances; self.instances = updated_instances;
} }
fn create_index_buffer(device: &Device) -> wgpu::Buffer {
device.create_buffer_init(
&wgpu::util::BufferInitDescriptor {
label: Some("Index Buffer"),
contents: bytemuck::cast_slice(INDICES),
usage: wgpu::BufferUsages::INDEX,
}
)
}
fn create_vertex_buffer(device: &Device) -> wgpu::Buffer {
device.create_buffer_init(
&wgpu::util::BufferInitDescriptor {
label: Some("Vertex Buffer"),
contents: bytemuck::cast_slice(VERTICES),
usage: wgpu::BufferUsages::VERTEX,
}
)
}
fn create_render_pipeline(device: &Device, config: &wgpu::SurfaceConfiguration) -> wgpu::RenderPipeline { fn create_render_pipeline(device: &Device, config: &wgpu::SurfaceConfiguration) -> wgpu::RenderPipeline {
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor { let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: Some("Shader"), label: Some("Shader"),
@ -449,11 +484,25 @@ impl<'a> State<'a> {
}); });
render_pass.set_pipeline(&self.render_pipeline); render_pass.set_pipeline(&self.render_pipeline);
render_pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
render_pass.set_index_buffer(self.index_buffer.slice(..), wgpu::IndexFormat::Uint16); for shape in [Shape::Polygon, Shape::Circle] {
if !self.instances.is_empty() { let geometry = &self.geometries[&shape];
let relevant_instances: Vec<_> = self.instances
.iter()
.enumerate()
.filter(|(_, inst)| inst.shape == shape)
.map(|(i, _)| i as u32)
.collect();
if relevant_instances.is_empty() {
continue;
}
render_pass.set_vertex_buffer(0, geometry.vertex_buffer.slice(..));
render_pass.set_vertex_buffer(1, self.instance_buffer.slice(..)); 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); render_pass.set_index_buffer(geometry.index_buffer.slice(..), wgpu::IndexFormat::Uint16);
render_pass.draw_indexed(0..geometry.index_count, 0, 0..relevant_instances.len() as u32);
} }
} }