use crate::resources::*;
impl DeviceResources {
pub fn update_gizmo_mesh(
&mut self,
device: &wgpu::Device,
queue: &wgpu::Queue,
mode: crate::interaction::manipulation::gizmo::GizmoMode,
hovered: crate::interaction::manipulation::gizmo::GizmoAxis,
space_orientation: glam::Quat,
) {
let (verts, indices) = crate::interaction::manipulation::gizmo::build_gizmo_mesh(
mode,
hovered,
space_orientation,
);
let vert_bytes: &[u8] = bytemuck::cast_slice(&verts);
let idx_bytes: &[u8] = bytemuck::cast_slice(&indices);
if vert_bytes.len() as u64 > self.gizmo_vertex_buffer.size() {
self.gizmo_vertex_buffer = device.create_buffer(&wgpu::BufferDescriptor {
label: Some("gizmo_vertex_buf"),
size: vert_bytes.len() as u64,
usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: false,
});
}
if idx_bytes.len() as u64 > self.gizmo_index_buffer.size() {
self.gizmo_index_buffer = device.create_buffer(&wgpu::BufferDescriptor {
label: Some("gizmo_index_buf"),
size: idx_bytes.len() as u64,
usage: wgpu::BufferUsages::INDEX | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: false,
});
}
queue.write_buffer(&self.gizmo_vertex_buffer, 0, vert_bytes);
queue.write_buffer(&self.gizmo_index_buffer, 0, idx_bytes);
self.gizmo_index_count = indices.len() as u32;
}
pub fn update_gizmo_uniform(&self, queue: &wgpu::Queue, model: glam::Mat4) {
let uniform = crate::interaction::manipulation::gizmo::GizmoUniform {
model: model.to_cols_array_2d(),
};
queue.write_buffer(&self.gizmo_uniform_buf, 0, bytemuck::cast_slice(&[uniform]));
}
pub fn create_constraint_overlay(
&self,
device: &wgpu::Device,
overlay: &crate::interaction::query::snap::ConstraintOverlay,
) -> (
wgpu::Buffer,
wgpu::Buffer,
u32,
wgpu::Buffer,
wgpu::BindGroup,
) {
use bytemuck::cast_slice;
let (vertices, colour): (Vec<OverlayVertex>, [f32; 4]) = match overlay {
crate::interaction::query::snap::ConstraintOverlay::AxisLine {
origin,
direction,
colour,
} => (
vec![
OverlayVertex {
position: (*origin - *direction).to_array(),
},
OverlayVertex {
position: (*origin + *direction).to_array(),
},
],
*colour,
),
crate::interaction::query::snap::ConstraintOverlay::Plane {
origin,
axis_a,
axis_b,
colour,
} => (
vec![
OverlayVertex {
position: (*origin - *axis_a).to_array(),
},
OverlayVertex {
position: (*origin + *axis_a).to_array(),
},
OverlayVertex {
position: (*origin - *axis_b).to_array(),
},
OverlayVertex {
position: (*origin + *axis_b).to_array(),
},
],
*colour,
),
};
let indices: Vec<u32> = (0..vertices.len() as u32).collect();
let vertex_buffer = device.create_buffer(&wgpu::BufferDescriptor {
label: Some("constraint_overlay_vbuf"),
size: (std::mem::size_of::<OverlayVertex>() * vertices.len()) as u64,
usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: true,
});
vertex_buffer
.slice(..)
.get_mapped_range_mut()
.copy_from_slice(cast_slice(&vertices));
vertex_buffer.unmap();
let index_buffer = device.create_buffer(&wgpu::BufferDescriptor {
label: Some("constraint_overlay_ibuf"),
size: (std::mem::size_of::<u32>() * indices.len()) as u64,
usage: wgpu::BufferUsages::INDEX | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: true,
});
index_buffer
.slice(..)
.get_mapped_range_mut()
.copy_from_slice(cast_slice(&indices));
index_buffer.unmap();
let uniform_data = OverlayUniform {
model: glam::Mat4::IDENTITY.to_cols_array_2d(),
colour,
};
let uniform_buffer = device.create_buffer(&wgpu::BufferDescriptor {
label: Some("constraint_overlay_ubuf"),
size: std::mem::size_of::<OverlayUniform>() as u64,
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: true,
});
uniform_buffer
.slice(..)
.get_mapped_range_mut()
.copy_from_slice(cast_slice(&[uniform_data]));
uniform_buffer.unmap();
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
label: Some("constraint_overlay_bg"),
layout: &self.overlay_bind_group_layout,
entries: &[wgpu::BindGroupEntry {
binding: 0,
resource: uniform_buffer.as_entire_binding(),
}],
});
(
vertex_buffer,
index_buffer,
indices.len() as u32,
uniform_buffer,
bind_group,
)
}
pub(crate) fn create_clip_plane_fill_overlay(
&self,
device: &wgpu::Device,
overlay: &crate::interaction::manipulation::clip_plane::ClipPlaneOverlay,
) -> (
wgpu::Buffer,
wgpu::Buffer,
u32,
wgpu::Buffer,
wgpu::BindGroup,
) {
use crate::interaction::manipulation::clip_plane::plane_tangents;
use bytemuck::cast_slice;
let (t1, t2) = plane_tangents(overlay.normal);
let e = overlay.extent;
let c = overlay.center;
let corners = [
c + e * t1 + e * t2,
c - e * t1 + e * t2,
c - e * t1 - e * t2,
c + e * t1 - e * t2,
];
let vertices: Vec<OverlayVertex> = corners
.iter()
.map(|p| OverlayVertex {
position: p.to_array(),
})
.collect();
let indices: Vec<u32> = vec![0, 1, 2, 0, 2, 3];
let vertex_buffer = device.create_buffer(&wgpu::BufferDescriptor {
label: Some("clip_plane_fill_vbuf"),
size: (std::mem::size_of::<OverlayVertex>() * vertices.len()) as u64,
usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: true,
});
vertex_buffer
.slice(..)
.get_mapped_range_mut()
.copy_from_slice(cast_slice(&vertices));
vertex_buffer.unmap();
let index_buffer = device.create_buffer(&wgpu::BufferDescriptor {
label: Some("clip_plane_fill_ibuf"),
size: (std::mem::size_of::<u32>() * indices.len()) as u64,
usage: wgpu::BufferUsages::INDEX | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: true,
});
index_buffer
.slice(..)
.get_mapped_range_mut()
.copy_from_slice(cast_slice(&indices));
index_buffer.unmap();
let uniform_data = OverlayUniform {
model: glam::Mat4::IDENTITY.to_cols_array_2d(),
colour: overlay.fill_colour,
};
let uniform_buffer = device.create_buffer(&wgpu::BufferDescriptor {
label: Some("clip_plane_fill_ubuf"),
size: std::mem::size_of::<OverlayUniform>() as u64,
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: true,
});
uniform_buffer
.slice(..)
.get_mapped_range_mut()
.copy_from_slice(cast_slice(&[uniform_data]));
uniform_buffer.unmap();
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
label: Some("clip_plane_fill_bg"),
layout: &self.overlay_bind_group_layout,
entries: &[wgpu::BindGroupEntry {
binding: 0,
resource: uniform_buffer.as_entire_binding(),
}],
});
(
vertex_buffer,
index_buffer,
indices.len() as u32,
uniform_buffer,
bind_group,
)
}
pub(crate) fn create_clip_plane_line_overlay(
&self,
device: &wgpu::Device,
overlay: &crate::interaction::manipulation::clip_plane::ClipPlaneOverlay,
) -> (
wgpu::Buffer,
wgpu::Buffer,
u32,
wgpu::Buffer,
wgpu::BindGroup,
) {
use crate::interaction::manipulation::clip_plane::plane_tangents;
use bytemuck::cast_slice;
let (t1, t2) = plane_tangents(overlay.normal);
let e = overlay.extent;
let c = overlay.center;
let c0 = c + e * t1 + e * t2;
let c1 = c - e * t1 + e * t2;
let c2 = c - e * t1 - e * t2;
let c3 = c + e * t1 - e * t2;
let n_tip = c + overlay.normal * (e * 0.5);
let vertices: Vec<OverlayVertex> = vec![
OverlayVertex {
position: c0.to_array(),
},
OverlayVertex {
position: c1.to_array(),
},
OverlayVertex {
position: c1.to_array(),
},
OverlayVertex {
position: c2.to_array(),
},
OverlayVertex {
position: c2.to_array(),
},
OverlayVertex {
position: c3.to_array(),
},
OverlayVertex {
position: c3.to_array(),
},
OverlayVertex {
position: c0.to_array(),
},
OverlayVertex {
position: c.to_array(),
},
OverlayVertex {
position: n_tip.to_array(),
},
];
let indices: Vec<u32> = (0..vertices.len() as u32).collect();
let vertex_buffer = device.create_buffer(&wgpu::BufferDescriptor {
label: Some("clip_plane_line_vbuf"),
size: (std::mem::size_of::<OverlayVertex>() * vertices.len()) as u64,
usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: true,
});
vertex_buffer
.slice(..)
.get_mapped_range_mut()
.copy_from_slice(cast_slice(&vertices));
vertex_buffer.unmap();
let index_buffer = device.create_buffer(&wgpu::BufferDescriptor {
label: Some("clip_plane_line_ibuf"),
size: (std::mem::size_of::<u32>() * indices.len()) as u64,
usage: wgpu::BufferUsages::INDEX | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: true,
});
index_buffer
.slice(..)
.get_mapped_range_mut()
.copy_from_slice(cast_slice(&indices));
index_buffer.unmap();
let uniform_data = OverlayUniform {
model: glam::Mat4::IDENTITY.to_cols_array_2d(),
colour: overlay.border_colour,
};
let uniform_buffer = device.create_buffer(&wgpu::BufferDescriptor {
label: Some("clip_plane_line_ubuf"),
size: std::mem::size_of::<OverlayUniform>() as u64,
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: true,
});
uniform_buffer
.slice(..)
.get_mapped_range_mut()
.copy_from_slice(cast_slice(&[uniform_data]));
uniform_buffer.unmap();
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
label: Some("clip_plane_line_bg"),
layout: &self.overlay_bind_group_layout,
entries: &[wgpu::BindGroupEntry {
binding: 0,
resource: uniform_buffer.as_entire_binding(),
}],
});
(
vertex_buffer,
index_buffer,
indices.len() as u32,
uniform_buffer,
bind_group,
)
}
pub(crate) fn upload_cap_geometry(
&self,
device: &wgpu::Device,
cap: &crate::geometry::cap_geometry::CapMesh,
colour: [f32; 4],
) -> (
wgpu::Buffer,
wgpu::Buffer,
u32,
wgpu::Buffer,
wgpu::BindGroup,
) {
use bytemuck::cast_slice;
let vertices: Vec<OverlayVertex> = cap
.positions
.iter()
.map(|p| OverlayVertex { position: *p })
.collect();
let vertex_buffer = device.create_buffer(&wgpu::BufferDescriptor {
label: Some("cap_vbuf"),
size: (std::mem::size_of::<OverlayVertex>() * vertices.len()) as u64,
usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: true,
});
vertex_buffer
.slice(..)
.get_mapped_range_mut()
.copy_from_slice(cast_slice(&vertices));
vertex_buffer.unmap();
let index_buffer = device.create_buffer(&wgpu::BufferDescriptor {
label: Some("cap_ibuf"),
size: (std::mem::size_of::<u32>() * cap.indices.len()) as u64,
usage: wgpu::BufferUsages::INDEX | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: true,
});
index_buffer
.slice(..)
.get_mapped_range_mut()
.copy_from_slice(cast_slice(&cap.indices));
index_buffer.unmap();
let uniform_data = OverlayUniform {
model: glam::Mat4::IDENTITY.to_cols_array_2d(),
colour,
};
let uniform_buffer = device.create_buffer(&wgpu::BufferDescriptor {
label: Some("cap_ubuf"),
size: std::mem::size_of::<OverlayUniform>() as u64,
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: true,
});
uniform_buffer
.slice(..)
.get_mapped_range_mut()
.copy_from_slice(cast_slice(&[uniform_data]));
uniform_buffer.unmap();
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
label: Some("cap_bg"),
layout: &self.overlay_bind_group_layout,
entries: &[wgpu::BindGroupEntry {
binding: 0,
resource: uniform_buffer.as_entire_binding(),
}],
});
let idx_count = cap.indices.len() as u32;
(
vertex_buffer,
index_buffer,
idx_count,
uniform_buffer,
bind_group,
)
}
}
#[repr(C)]
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
pub struct OverlayVertex {
pub position: [f32; 3],
}
impl OverlayVertex {
pub fn buffer_layout() -> wgpu::VertexBufferLayout<'static> {
wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<OverlayVertex>() as wgpu::BufferAddress,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &[wgpu::VertexAttribute {
offset: 0,
shader_location: 0,
format: wgpu::VertexFormat::Float32x3,
}],
}
}
}
#[repr(C)]
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
pub(crate) struct OverlayUniform {
pub(crate) model: [[f32; 4]; 4],
pub(crate) colour: [f32; 4], }
pub(crate) struct BackdropBlurState {
#[allow(dead_code)]
pub intermediate_texture: wgpu::Texture,
pub intermediate_view: wgpu::TextureView,
#[allow(dead_code)]
pub blur_a_texture: wgpu::Texture,
pub blur_a_view: wgpu::TextureView,
#[allow(dead_code)]
pub blur_b_texture: wgpu::Texture,
pub blur_b_view: wgpu::TextureView,
pub size: [u32; 2],
pub format: wgpu::TextureFormat,
}
#[repr(C)]
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
pub(crate) struct GroundPlaneUniform {
pub view_proj: [[f32; 4]; 4], pub cam_right: [f32; 4], pub cam_up: [f32; 4], pub cam_back: [f32; 4], pub eye_pos: [f32; 3], pub height: f32, pub colour: [f32; 4], pub shadow_colour: [f32; 4], pub light_vp: [[f32; 4]; 4], pub tan_half_fov: f32, pub aspect: f32, pub tile_size: f32, pub shadow_bias: f32, pub mode: u32, pub shadow_opacity: f32, pub _pad: [f32; 2], pub colour2: [f32; 4], }
#[repr(C)]
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
pub(crate) struct GridUniform {
pub view_proj: [[f32; 4]; 4], pub cam_to_world: [[f32; 4]; 3], pub tan_half_fov: f32, pub aspect: f32, pub _pad_ivp: [f32; 2], pub eye_pos: [f32; 3], pub grid_z: f32, pub spacing_minor: f32, pub spacing_major: f32, pub snap_origin: [f32; 2], pub colour_minor: [f32; 4], pub colour_major: [f32; 4], }