STL loading and file dialogs

This commit is contained in:
mars 2022-05-15 23:29:34 -06:00
parent a2fc6590b4
commit 3606cabb53
4 changed files with 148 additions and 10 deletions

View File

@ -4,6 +4,8 @@ version = "0.1.0"
edition = "2021"
[dependencies]
bytemuck = "^1.0"
crossbeam-channel = "^0.5"
cyborg = { path = "../", features = ["legion"] }
egui = "0.17.0"
egui-winit = "0.17.0"
@ -13,3 +15,5 @@ legion = "^0.4"
pollster = "0.2"
puffin = "^0.13"
puffin_egui = "0.14.0"
rfd = "^0.8"
stl = "0.2.1"

View File

@ -25,6 +25,7 @@ struct Application {
ui: ui::UserInterface,
viewport: ui::ViewportWidget,
render_state: render::RenderState,
file_receiver: crossbeam_channel::Receiver<ui::FileEvent>,
}
impl Application {
@ -66,8 +67,16 @@ impl Application {
let egui_state = egui_winit::State::new(4096, &window);
let egui_ctx = egui::Context::default();
let mut egui_rp = egui_wgpu_backend::RenderPass::new(&device, config.format, 1);
let render_state = render::RenderState::new(device.clone(), queue.clone(), config.format, &mut egui_rp);
let viewport_texture = render_state.resources.get::<render::ViewportStore>().unwrap().viewport.egui_texture;
let render_state =
render::RenderState::new(device.clone(), queue.clone(), config.format, &mut egui_rp);
let viewport_texture = render_state
.resources
.get::<render::ViewportStore>()
.unwrap()
.viewport
.egui_texture;
let (file_sender, file_receiver) = crossbeam_channel::unbounded();
Self {
window,
@ -79,14 +88,98 @@ impl Application {
egui_state,
egui_ctx,
egui_rp,
ui: ui::UserInterface::new(),
ui: ui::UserInterface::new(file_sender),
viewport: ui::ViewportWidget::new(viewport_texture),
render_state,
file_receiver,
}
}
pub fn update(&mut self) {
self.window.request_redraw();
loop {
match self.file_receiver.try_recv() {
Ok(ui::FileEvent::Save) => println!("Saving!"),
Ok(ui::FileEvent::SaveAs(path)) => println!("Saving as: {:?}", path),
Ok(ui::FileEvent::Import(kind, path)) => match kind {
ui::ImportKind::Stl => {
self.load_stl(path);
}
},
Err(crossbeam_channel::TryRecvError::Empty) => break,
Err(crossbeam_channel::TryRecvError::Disconnected) => {
panic!("File event sender hung up!");
}
}
}
}
pub fn load_stl(&mut self, path: std::path::PathBuf) {
use cyborg::pass::{
mesh::{Index, MeshPass, Vertex},
RenderPassBox,
};
use cyborg::storage::mesh::{AttrBuffer, MeshBuffer};
eprintln!("loading {:?}", path);
let mut file = std::fs::File::open(path).unwrap();
let stl = stl::read_stl(&mut file).unwrap();
let mut vertices = Vec::new();
let mut indices = Vec::new();
for tri in stl.triangles.iter() {
let tan_frame = 0; // TODO make from normal
indices.push(vertices.len() as Index);
vertices.push(Vertex {
position: tri.v1,
tan_frame,
});
indices.push(vertices.len() as Index);
vertices.push(Vertex {
position: tri.v2,
tan_frame,
});
indices.push(vertices.len() as Index);
vertices.push(Vertex {
position: tri.v3,
tan_frame,
});
}
let mesh_pass = self
.render_state
.resources
.get::<RenderPassBox<MeshPass>>()
.unwrap();
let attributes = mesh_pass.get_attributes();
let vertices = AttrBuffer {
id: attributes.vertex,
count: vertices.len(),
data: bytemuck::cast_slice(&vertices).to_vec(),
};
let indices = AttrBuffer {
id: attributes.index,
count: indices.len(),
data: bytemuck::cast_slice(&indices).to_vec(),
};
let mut mesh = MeshBuffer::default();
mesh.attributes.push(vertices);
mesh.attributes.push(indices);
self.render_state.world.push((
cyborg::scene::Mesh {
mesh: mesh_pass.get_mesh_pool().load(mesh).unwrap(),
},
cyborg::scene::Transform {
transform: glam::Mat4::from_translation(glam::Vec3::new(0.0, -10.0, 0.0)),
},
));
}
pub fn on_resize(&mut self, new_size: PhysicalSize<u32>) {
@ -108,12 +201,14 @@ impl Application {
let output = {
puffin::profile_scope!("Draw egui");
let raw_input = self.egui_state.take_egui_input(&self.window);
self.egui_ctx.run(raw_input, |ctx| self.ui.run(ctx, &mut self.viewport))
self.egui_ctx
.run(raw_input, |ctx| self.ui.run(ctx, &mut self.viewport))
};
{
puffin::profile_scope!("Main render");
self.render_state.update_viewport(&mut self.egui_rp, &mut self.viewport);
self.render_state
.update_viewport(&mut self.egui_rp, &mut self.viewport);
self.render_state.render();
}
@ -164,7 +259,6 @@ fn main() {
event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Wait;
// println!("{:?}", event);
match event {
Event::RedrawRequested(window_id) if window_id == app.window.id() => {

View File

@ -1,7 +1,22 @@
use crate::winit;
use crossbeam_channel::Sender;
use cyborg::camera::Flycam;
use std::path::PathBuf;
#[derive(Clone, Debug)]
pub enum FileEvent {
Save,
SaveAs(PathBuf),
Import(ImportKind, PathBuf),
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum ImportKind {
Stl,
}
pub struct UserInterface {
file_sender: Sender<FileEvent>,
developer_mode: bool,
show_profiler: bool,
quit: bool,
@ -10,8 +25,9 @@ pub struct UserInterface {
}
impl UserInterface {
pub fn new() -> Self {
pub fn new(file_sender: Sender<FileEvent>) -> Self {
Self {
file_sender,
developer_mode: true,
show_profiler: false,
quit: false,
@ -35,15 +51,39 @@ impl UserInterface {
}
if ui.button("Save").clicked() {
println!("Saving!");
ui.close_menu();
self.file_sender.send(FileEvent::Save).unwrap();
}
if ui.button("Save as...").clicked() {
println!("Saving as!");
ui.close_menu();
let file_sender = self.file_sender.to_owned();
std::thread::spawn(move || {
if let Some(path) = rfd::FileDialog::new().save_file() {
file_sender.send(FileEvent::SaveAs(path)).unwrap();
}
});
}
ui.menu_button("Import...", |ui| {
if ui.button("STL").clicked() {
ui.close_menu();
let import_kind = ImportKind::Stl;
let file_sender = self.file_sender.to_owned();
std::thread::spawn(move || {
let dialog = rfd::FileDialog::new().add_filter("STL", &["stl"]);
if let Some(paths) = dialog.pick_files() {
for path in paths.iter() {
let event = FileEvent::Import(import_kind, path.into());
file_sender.send(event).unwrap();
}
}
});
}
});
if ui.button("Open...").clicked() {
println!("Opening!");
ui.close_menu();

View File

@ -14,7 +14,7 @@ pub struct ShaderInfo {
}
#[repr(C)]
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
pub struct Vertex {
pub position: [f32; 3],
pub tan_frame: u32,