143 lines
4.0 KiB
Rust
143 lines
4.0 KiB
Rust
use std::collections::HashMap;
|
|
use wgpu::{Device, Buffer};
|
|
use wgpu::util::DeviceExt;
|
|
use crate::renderer::Vertex;
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
|
pub enum Shape {
|
|
Circle,
|
|
Sphere,
|
|
}
|
|
|
|
pub struct Geometry {
|
|
pub(crate) vertex_buffer: Buffer,
|
|
pub(crate) index_buffer: Buffer,
|
|
pub(crate) index_count: u32,
|
|
}
|
|
|
|
pub struct GeometryManager {
|
|
pub geometries: HashMap<Shape, Geometry>,
|
|
}
|
|
|
|
impl GeometryManager {
|
|
pub fn new(device: &Device) -> Self {
|
|
let mut geometries = HashMap::new();
|
|
|
|
// Circle
|
|
let (circle_vertices, circle_indices) = create_circle_vertices(512, 0.5, [0.5, 0.5, 0.5]);
|
|
geometries.insert(
|
|
Shape::Circle,
|
|
Self::create_geometry(device, &circle_vertices, &circle_indices),
|
|
);
|
|
|
|
// Sphere
|
|
let (sphere_vertices, sphere_indices) = create_sphere_vertices(32, 32, 0.5, [0.5, 0.5, 0.5]);
|
|
geometries.insert(
|
|
Shape::Sphere,
|
|
Self::create_geometry(device, &sphere_vertices, &sphere_indices),
|
|
);
|
|
|
|
// Füge hier beliebige weitere Shapes hinzu
|
|
|
|
Self { geometries }
|
|
}
|
|
|
|
pub fn get(&self, shape: &Shape) -> Option<&Geometry> {
|
|
self.geometries.get(shape)
|
|
}
|
|
|
|
pub fn shapes(&self) -> impl Iterator<Item = Shape> + '_ {
|
|
self.geometries.keys().copied()
|
|
}
|
|
|
|
fn create_geometry(device: &Device, vertices: &[Vertex], indices: &[u16]) -> Geometry {
|
|
let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
|
label: Some("Vertex Buffer"),
|
|
contents: bytemuck::cast_slice(vertices),
|
|
usage: wgpu::BufferUsages::VERTEX,
|
|
});
|
|
|
|
let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
|
label: Some("Index Buffer"),
|
|
contents: bytemuck::cast_slice(indices),
|
|
usage: wgpu::BufferUsages::INDEX,
|
|
});
|
|
|
|
Geometry {
|
|
vertex_buffer,
|
|
index_buffer,
|
|
index_count: indices.len() as u32,
|
|
}
|
|
}
|
|
}
|
|
|
|
pub 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,
|
|
normal: [0.0, 0.0, 1.0],
|
|
}];
|
|
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,
|
|
normal: [0.0, 0.0, 1.0],
|
|
});
|
|
}
|
|
|
|
for i in 1..=segment_count {
|
|
indices.push(0);
|
|
indices.push(i as u16);
|
|
indices.push((i % segment_count + 1) as u16);
|
|
}
|
|
|
|
(vertices, indices)
|
|
}
|
|
|
|
pub fn create_sphere_vertices(stacks: usize, slices: usize, radius: f32, color: [f32; 3]) -> (Vec<Vertex>, Vec<u16>) {
|
|
let mut vertices = Vec::new();
|
|
let mut indices = Vec::new();
|
|
|
|
for i in 0..=stacks {
|
|
let phi = std::f32::consts::PI * (i as f32) / (stacks as f32);
|
|
let y = phi.cos();
|
|
let r = phi.sin();
|
|
|
|
for j in 0..=slices {
|
|
let theta = 2.0 * std::f32::consts::PI * (j as f32) / (slices as f32);
|
|
let x = r * theta.cos();
|
|
let z = r * theta.sin();
|
|
|
|
let normal = [x, y, z];
|
|
|
|
vertices.push(Vertex {
|
|
position: [x * radius, y * radius, z * radius],
|
|
color,
|
|
normal,
|
|
});
|
|
}
|
|
}
|
|
|
|
for i in 0..stacks {
|
|
for j in 0..slices {
|
|
let first = i * (slices + 1) + j;
|
|
let second = first + slices + 1;
|
|
|
|
indices.push(first as u16);
|
|
indices.push(second as u16);
|
|
indices.push((first + 1) as u16);
|
|
|
|
indices.push(second as u16);
|
|
indices.push((second + 1) as u16);
|
|
indices.push((first + 1) as u16);
|
|
}
|
|
}
|
|
|
|
(vertices, indices)
|
|
}
|