2025-05-05 15:33:22 +02:00
|
|
|
#[repr(C)]
|
|
|
|
|
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
|
|
|
pub struct Globals {
|
2025-05-05 20:07:20 +02:00
|
|
|
pub view_proj: [[f32; 4]; 4],
|
2025-05-05 15:33:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
|
|
|
|
pub enum Shape {
|
|
|
|
|
Polygon,
|
|
|
|
|
Circle,
|
2025-05-05 21:52:42 +02:00
|
|
|
Sphere,
|
2025-05-05 15:33:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct Geometry {
|
|
|
|
|
pub(crate) vertex_buffer: wgpu::Buffer,
|
|
|
|
|
pub(crate) index_buffer: wgpu::Buffer,
|
|
|
|
|
pub(crate) index_count: u32,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct RenderInstance {
|
|
|
|
|
pub position: cgmath::Vector3<f32>,
|
|
|
|
|
pub rotation: cgmath::Quaternion<f32>,
|
|
|
|
|
pub color: [f32; 3],
|
|
|
|
|
pub scale: f32,
|
|
|
|
|
pub shape: Shape,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl RenderInstance {
|
|
|
|
|
pub fn to_raw(&self) -> InstanceRaw {
|
|
|
|
|
let model = cgmath::Matrix4::from_translation(self.position)
|
|
|
|
|
* cgmath::Matrix4::from(self.rotation)
|
|
|
|
|
* cgmath::Matrix4::from_scale(self.scale);
|
|
|
|
|
InstanceRaw {
|
|
|
|
|
model: model.into(),
|
|
|
|
|
color: self.color,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[repr(C)]
|
|
|
|
|
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
|
|
|
pub struct InstanceRaw {
|
|
|
|
|
model: [[f32; 4]; 4],
|
|
|
|
|
color: [f32; 3],
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl InstanceRaw {
|
|
|
|
|
pub(crate) fn desc() -> wgpu::VertexBufferLayout<'static> {
|
|
|
|
|
wgpu::VertexBufferLayout {
|
|
|
|
|
array_stride: size_of::<InstanceRaw>() as wgpu::BufferAddress,
|
|
|
|
|
step_mode: wgpu::VertexStepMode::Instance,
|
|
|
|
|
attributes: &[
|
|
|
|
|
wgpu::VertexAttribute { offset: 0, shader_location: 5, format: wgpu::VertexFormat::Float32x4 },
|
|
|
|
|
wgpu::VertexAttribute { offset: 16, shader_location: 6, format: wgpu::VertexFormat::Float32x4 },
|
|
|
|
|
wgpu::VertexAttribute { offset: 32, shader_location: 7, format: wgpu::VertexFormat::Float32x4 },
|
|
|
|
|
wgpu::VertexAttribute { offset: 48, shader_location: 8, format: wgpu::VertexFormat::Float32x4 },
|
|
|
|
|
wgpu::VertexAttribute { offset: 64, shader_location: 9, format: wgpu::VertexFormat::Float32x3 },
|
|
|
|
|
],
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub struct SampleCount(pub u32);
|
|
|
|
|
|
|
|
|
|
impl SampleCount {
|
|
|
|
|
pub fn get(&self) -> u32 {
|
|
|
|
|
self.0
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[repr(C)]
|
|
|
|
|
#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
|
|
|
|
|
pub struct Vertex {
|
|
|
|
|
pub(crate) position: [f32; 3],
|
|
|
|
|
pub(crate) color: [f32; 3],
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Vertex {
|
|
|
|
|
const ATTRIBS: [wgpu::VertexAttribute; 2] =
|
|
|
|
|
wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x3];
|
|
|
|
|
|
|
|
|
|
pub(crate) fn desc() -> wgpu::VertexBufferLayout<'static> {
|
|
|
|
|
wgpu::VertexBufferLayout {
|
|
|
|
|
array_stride: size_of::<Self>() as wgpu::BufferAddress,
|
|
|
|
|
step_mode: wgpu::VertexStepMode::Vertex,
|
|
|
|
|
attributes: &Self::ATTRIBS,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 }];
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-05 21:52:42 +02:00
|
|
|
(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();
|
|
|
|
|
|
|
|
|
|
vertices.push(Vertex {
|
|
|
|
|
position: [x * radius, y * radius, z * radius],
|
|
|
|
|
color,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-05 15:33:22 +02:00
|
|
|
(vertices, indices)
|
|
|
|
|
}
|