UI Camera movement

This commit is contained in:
Connor Slade
2024-06-20 18:16:56 -04:00
parent 89cdae4299
commit 7b697fef9f
4 changed files with 149 additions and 15 deletions

41
Cargo.lock generated
View File

@@ -939,6 +939,12 @@ dependencies = [
"crossbeam-utils",
]
[[package]]
name = "const_panic"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6051f239ecec86fde3410901ab7860d458d160371533842974fc61f96d15879b"
[[package]]
name = "core-foundation"
version = "0.9.4"
@@ -1051,7 +1057,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e3d747f100290a1ca24b752186f61f6637e1deffe3bf6320de6fcb29510a307"
dependencies = [
"bitflags 2.5.0",
"libloading 0.7.4",
"libloading 0.8.3",
"winapi",
]
@@ -1230,6 +1236,37 @@ dependencies = [
"bytemuck",
]
[[package]]
name = "encase"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a9299a95fa5671ddf29ecc22b00e121843a65cb9ff24911e394b4ae556baf36"
dependencies = [
"const_panic",
"encase_derive",
"thiserror",
]
[[package]]
name = "encase_derive"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07e09decb3beb1fe2db6940f598957b2e1f7df6206a804d438ff6cb2a9cddc10"
dependencies = [
"encase_derive_impl",
]
[[package]]
name = "encase_derive_impl"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd31dbbd9743684d339f907a87fe212cb7b51d75b9e8e74181fe363199ee9b47"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.66",
]
[[package]]
name = "enumflags2"
version = "0.7.10"
@@ -3611,6 +3648,8 @@ dependencies = [
"eframe",
"egui",
"egui-wgpu",
"encase",
"nalgebra",
"slicer",
"wgpu",
]

View File

@@ -12,3 +12,5 @@ egui-wgpu = "0.27.2"
wgpu = "0.19.4"
slicer = { path = "../slicer" }
encase = "0.8.0"
nalgebra = "0.32.6"

View File

@@ -2,20 +2,38 @@ use std::{fs::File, mem};
use anyhow::Result;
use eframe::NativeOptions;
use egui::{CentralPanel, Frame, Sense, TopBottomPanel, Vec2, Window};
use egui::{CentralPanel, Frame, Sense, Slider, Stroke, TopBottomPanel, Vec2, Window};
use egui_wgpu::{Callback, CallbackTrait};
use slicer::mesh::Mesh;
use nalgebra::{Matrix4, Point3, Vector3};
use slicer::{mesh::Mesh, Pos};
use wgpu::{
BindGroup, BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingType, Buffer, BufferAddress, BufferBindingType, BufferDescriptor, BufferSize, BufferUsages, ColorTargetState, ColorWrites, Face, FragmentState, IndexFormat, MultisampleState, PipelineLayoutDescriptor, PrimitiveState, RenderPipeline, RenderPipelineDescriptor, ShaderModuleDescriptor, ShaderStages, TextureFormat, VertexAttribute, VertexBufferLayout, VertexFormat, VertexState, VertexStepMode
BindGroup, BindGroupEntry, BindGroupLayoutDescriptor, Buffer, BufferAddress, BufferBinding,
BufferDescriptor, BufferUsages, ColorTargetState, ColorWrites, FragmentState, IndexFormat,
MultisampleState, PipelineLayoutDescriptor, PrimitiveState, RenderPipeline,
RenderPipelineDescriptor, ShaderModuleDescriptor, TextureFormat, VertexAttribute,
VertexBufferLayout, VertexFormat, VertexState, VertexStepMode,
};
const TEXTURE_FORMAT: TextureFormat = TextureFormat::Bgra8Unorm;
struct App {}
struct App {
camera: Camera,
}
struct Camera {
eye: Point3<f32>,
target: Point3<f32>,
up: Vector3<f32>,
fovy: f32,
znear: f32,
zfar: f32,
}
struct WorkspaceRenderResources {
vertex_buffer: Buffer,
index_buffer: Buffer,
uniform_buffer: Buffer,
render_pipeline: RenderPipeline,
bind_group: BindGroup,
@@ -51,9 +69,25 @@ fn main() -> Result<()> {
source: wgpu::ShaderSource::Wgsl(include_str!("shader/workspace.wgsl").into()),
});
let uniform_buffer = device.create_buffer(&BufferDescriptor {
label: None,
size: mem::size_of::<WorkspaceRenderCallback>() as u64,
usage: BufferUsages::UNIFORM | BufferUsages::COPY_DST,
mapped_at_creation: false,
});
let bind_group_layout = device.create_bind_group_layout(&BindGroupLayoutDescriptor {
label: None,
entries: &[],
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
min_binding_size: None,
},
count: None,
}],
});
let vertex_buffers = [VertexBufferLayout {
@@ -107,7 +141,14 @@ fn main() -> Result<()> {
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
label: None,
layout: &bind_group_layout,
entries: &[],
entries: &[BindGroupEntry {
binding: 0,
resource: wgpu::BindingResource::Buffer(BufferBinding {
buffer: &uniform_buffer,
offset: 0,
size: None,
}),
}],
});
render_state
@@ -117,12 +158,24 @@ fn main() -> Result<()> {
.insert(WorkspaceRenderResources {
vertex_buffer,
index_buffer,
uniform_buffer,
render_pipeline,
bind_group,
modal: test_modal,
});
Box::new(App {})
Box::new(App {
camera: Camera {
eye: Point3::new(0.0, -50.0, 5.0),
target: Point3::new(0.0, 50.0, 0.0),
up: Vector3::new(0.0, 1.0, 0.0),
fovy: 25.0,
znear: 0.1,
zfar: 100.0,
},
})
}),
)
.unwrap();
@@ -142,18 +195,43 @@ impl eframe::App for App {
});
});
CentralPanel::default().show(ctx, |ui| {
Frame::canvas(ui.style()).show(ui, |ui| {
let (rect, response) = ui.allocate_exact_size(Vec2::splat(300.0), Sense::drag());
Window::new("Controls").show(ctx, |ui| {});
let callback = Callback::new_paint_callback(rect, WorkspaceRenderCallback);
CentralPanel::default()
.frame(Frame::none())
.show(ctx, |ui| {
let (rect, _response) = ui.allocate_exact_size(ui.available_size(), Sense::drag());
let callback = Callback::new_paint_callback(
rect,
WorkspaceRenderCallback {
transform: self
.camera
.build_view_projection_matrix(rect.width() / rect.height()),
},
);
ui.painter().add(callback);
});
});
}
}
struct WorkspaceRenderCallback;
impl Camera {
fn build_view_projection_matrix(&self, aspect: f32) -> Matrix4<f32> {
const OPENGL_TO_WGPU_MATRIX: Matrix4<f32> = Matrix4::new(
1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 1.0,
);
let fov = self.fovy * std::f32::consts::PI / 180.0;
let view = Matrix4::look_at_rh(&self.eye, &self.target, &self.up);
let proj = Matrix4::new_perspective(aspect, fov, self.znear, self.zfar);
OPENGL_TO_WGPU_MATRIX * proj * view
}
}
struct WorkspaceRenderCallback {
transform: Matrix4<f32>,
}
impl CallbackTrait for WorkspaceRenderCallback {
fn prepare(
@@ -186,6 +264,8 @@ impl CallbackTrait for WorkspaceRenderCallback {
bytemuck::cast_slice(&resources.modal.faces),
);
queue.write_buffer(&resources.uniform_buffer, 0, &self.to_wgsl());
Vec::new()
}
@@ -207,6 +287,13 @@ impl CallbackTrait for WorkspaceRenderCallback {
}
}
impl WorkspaceRenderCallback {
fn to_wgsl(&self) -> Vec<u8> {
let mut out = Vec::new();
out.extend_from_slice(bytemuck::cast_slice(&self.transform.as_slice()));
out
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
pub struct ModelVertex {

View File

@@ -1,3 +1,9 @@
@group(0) @binding(0) var<uniform> context: Context;
struct Context {
transform: mat4x4<f32>,
}
struct VertexOutput {
@builtin(position)
position: vec4<f32>,
@@ -11,7 +17,7 @@ fn vert(
@location(1) tex_coord: vec2<f32>,
) -> VertexOutput {
var out: VertexOutput;
out.position = position;
out.position = context.transform * position;
out.tex_coord = tex_coord;
return out;
}