From 97621f28bfda0f120cecf44d554db5c5eaaabca8 Mon Sep 17 00:00:00 2001 From: Sean Isom Date: Mon, 10 Mar 2025 18:25:56 -0400 Subject: [PATCH] Modify GUI to use GLB model instead of STEP --- examples/axis.glb | Bin 0 -> 6952 bytes gui/Cargo.toml | 1 + gui/src/app.rs | 13 +++---- gui/src/camera.rs | 10 +++--- gui/src/main.rs | 16 ++++----- gui/src/model.rs | 89 ++++++++++++++++++++++++++++++---------------- 6 files changed, 77 insertions(+), 52 deletions(-) create mode 100644 examples/axis.glb diff --git a/examples/axis.glb b/examples/axis.glb new file mode 100644 index 0000000000000000000000000000000000000000..295326fbf458fda139bcf94b0f1a4bcdbef85a60 GIT binary patch literal 6952 zcmds6OLH4V5MCU@BfJBImjSWikp$V%)3yZoAz?>O94pvPcm(6f(pp}SR${esl5)99 z=j89?KrW=phJpi}C<=~H#fg8AOU&0Zy}Prr6kAESSXH08r{|mQp6(u1$|+YCrusBZ zJNBBUB@SxZ>G}NZx?X5B3`b9|>uZMHFl&~c)?}VEF+)xqok)V>SuCuOVxs7*k+;9 zSZdUbVzW}P5hJ*n>DzEbg#@PItMxDgJf7=17) zMv))G&xQ;G?$?gUvHOXf@QR~ErVPC3R52H1Z@+ka58;!3Z&D*(Z|1WTGZS-u0@0Ko zba4Z^9048&^nb>%%FZgfolM32eHsyUWIBxtO^Dk+$>0DRf*-KTfsq9-nwTRspXp?HN(y`m%l2a0-=*S)8ji z%c~Zi8vQ0z**H}wiXQ^BdLyitYR%<}F>jXWbvt&`P~SWq3qEV_y<^AKU5A*NjSZ2Z z(O5NPqw2OO% zxw8{9c=cgDo1e+gEk*Qn3;`*m1;;XC6~RF#W21zozwH|NW*m-rv@X+}06!H}R(Yn&h&IJ)_u_J_ddIeD!RA z6PO2|ALMv;)We_o{z?2`$PeuF4zMTQf~u1ZYtbvO4ua41muLA+1%3LlRR23Tihnm& zkVEmw7tOpsGe~{Be^T^-?c$z6JxhFP56puyC+bY@^r_CO^b_DH{-vL89O09R2MQ^p) zQG0oB*gNUOXS;XbmQvGhy2xkXc4;hr`=9S=(M=b`&OK@=aX@R0oxEM5H`_W1pLfwk zznRlfrEVh(s6!t``Y0I;vjBk9jQ=0{MlV6Ka{uhdslr7oEyyVsLTD*EzS+x zc3rM1Id`vJmx=G1cT2q|`Z-Fyq_f?0)OD0LgT1{#0^G=VkX GGVmXDzH>hS literal 0 HcmV?d00001 diff --git a/gui/Cargo.toml b/gui/Cargo.toml index 49c030e..0477f7c 100644 --- a/gui/Cargo.toml +++ b/gui/Cargo.toml @@ -19,3 +19,4 @@ nalgebra-glm = "0.13.0" pollster = "0.2.4" wgpu = "0.8.1" winit = "0.24.0" +gltf = "1.4.1" diff --git a/gui/src/app.rs b/gui/src/app.rs index 5f22100..9ff3cf0 100644 --- a/gui/src/app.rs +++ b/gui/src/app.rs @@ -1,11 +1,12 @@ use nalgebra_glm as glm; use glm::Vec2; +use gltf; use winit::{ dpi::{PhysicalSize}, event::{ElementState, ModifiersState, WindowEvent, DeviceEvent, VirtualKeyCode, MouseScrollDelta}, }; -use triangulate::mesh::Mesh; +//use triangulate::mesh::Mesh; use crate::{backdrop::Backdrop, camera::Camera, model::Model}; pub struct App { @@ -16,7 +17,7 @@ pub struct App { swapchain_format: wgpu::TextureFormat, swapchain: wgpu::SwapChain, - loader: Option>, + loader: Option>, model: Option, backdrop: Backdrop, camera: Camera, @@ -38,7 +39,7 @@ pub enum Reply { impl App { pub fn new(start_time: std::time::SystemTime, size: PhysicalSize, adapter: wgpu::Adapter, surface: wgpu::Surface, - device: wgpu::Device, loader: std::thread::JoinHandle) + device: wgpu::Device, loader: std::thread::JoinHandle) -> Self { let swapchain_format = adapter.get_swap_chain_preferred_format(&surface) @@ -200,10 +201,10 @@ impl App { .unwrap() .join() .expect("Failed to load mesh"); - let model = Model::new(&self.device, self.swapchain_format, - &mesh.verts, &mesh.triangles); + let (model, vertices) = Model::new( + &self.device, self.swapchain_format,&mesh); self.model = Some(model); - self.camera.fit_verts(&mesh.verts); + self.camera.fit_verts(&vertices); self.first_frame = true; } else { self.first_frame = false; diff --git a/gui/src/camera.rs b/gui/src/camera.rs index b83cb4d..5b4a22e 100644 --- a/gui/src/camera.rs +++ b/gui/src/camera.rs @@ -3,7 +3,7 @@ use nalgebra_glm as glm; use glm::{Vec2, Vec3, Vec4, Mat4}; use winit::event::MouseButton; -use triangulate::mesh::Vertex; +use crate::model::GPUVertex; #[derive(Copy, Clone, Debug)] enum MouseState { @@ -116,10 +116,10 @@ impl Camera { } } - pub fn fit_verts(&mut self, verts: &[Vertex]) { - let xb = verts.iter().map(|v| v.pos.x).minmax().into_option().unwrap(); - let yb = verts.iter().map(|v| v.pos.y).minmax().into_option().unwrap(); - let zb = verts.iter().map(|v| v.pos.z).minmax().into_option().unwrap(); + pub fn fit_verts(&mut self, verts: &[GPUVertex]) { + let xb = verts.iter().map(|v| v.pos[0]).minmax().into_option().unwrap(); + let yb = verts.iter().map(|v| v.pos[1]).minmax().into_option().unwrap(); + let zb = verts.iter().map(|v| v.pos[2]).minmax().into_option().unwrap(); let dx = xb.1 - xb.0; let dy = yb.1 - yb.0; let dz = zb.1 - zb.0; diff --git a/gui/src/main.rs b/gui/src/main.rs index 18c0a29..45d35a4 100644 --- a/gui/src/main.rs +++ b/gui/src/main.rs @@ -1,3 +1,4 @@ +use gltf::Gltf; use std::time::SystemTime; use winit::{ event::{Event}, @@ -11,10 +12,9 @@ pub(crate) mod camera; pub(crate) mod model; use crate::app::App; -use triangulate::mesh::Mesh; async fn run(start: SystemTime, event_loop: EventLoop<()>, window: Window, - loader: std::thread::JoinHandle) + loader: std::thread::JoinHandle) { let size = window.inner_size(); let (surface, adapter) = { @@ -85,14 +85,10 @@ fn main() { // and triangulated in the background while we wait for a GPU context let loader = std::thread::spawn(|| { println!("Loading mesh!"); - use step::step_file::StepFile; - use triangulate::triangulate::triangulate; - - let data = std::fs::read(input).expect("Could not open file"); - let flat = StepFile::strip_flatten(&data); - let step = StepFile::parse(&flat); - let (mesh, _stats) = triangulate(&step); - mesh + use std::{fs, io}; + let file = fs::File::open(input).unwrap(); + let reader = io::BufReader::new(file); + gltf::Gltf::from_reader(reader).unwrap() }); let event_loop = EventLoop::new(); diff --git a/gui/src/model.rs b/gui/src/model.rs index 5c2d2da..7873dd2 100644 --- a/gui/src/model.rs +++ b/gui/src/model.rs @@ -3,28 +3,19 @@ use std::borrow::Cow; use bytemuck::{Pod, Zeroable}; use nalgebra_glm as glm; use glm::{Vec4, Mat4}; +use gltf::Gltf; use wgpu::util::DeviceExt; -use triangulate::mesh::{Vertex, Triangle}; use crate::camera::Camera; + #[repr(C)] #[derive(Clone, Copy, Debug, Pod, Zeroable)] -struct GPUVertex { - pos: [f32; 4], - norm: [f32; 4], - color: [f32; 4], -} - -impl GPUVertex { - fn from_vertex(v: &Vertex) -> Self { - Self { - pos: [v.pos.x as f32, v.pos.y as f32, v.pos.z as f32, 1.0], - norm: [v.norm.x as f32, v.norm.y as f32, v.norm.z as f32, 1.0], - color: [v.color.x as f32, v.color.y as f32, v.color.z as f32, 1.0], - } - } +pub struct GPUVertex { + pub pos: [f32; 4], + pub norm: [f32; 4], + pub color: [f32; 4], } pub struct Model { @@ -37,26 +28,62 @@ pub struct Model { } impl Model { - pub fn new(device: &wgpu::Device, swapchain_format: wgpu::TextureFormat, - verts: &[Vertex], tris: &[Triangle]) -> Self { + pub fn new(device: &wgpu::Device, swapchain_format: wgpu::TextureFormat, gltf: &Gltf + ) -> (Self, Vec) { + + // Load buffers + let mut buffer_data = Vec::new(); + for buffer in gltf.buffers() { + let bin = match buffer.source() { + gltf::buffer::Source::Bin => { + if let Some(blob) = gltf.blob.clone() { + blob + } else { + panic!("Missing Blob"); + } + } + _ => panic!("Only GLB/embedded buffers supported") + }; + + buffer_data.push(bin); + } - let vertex_data: Vec = verts.into_iter() - .map(GPUVertex::from_vertex) - .collect(); - let index_data: Vec = tris.into_iter() - .flat_map(|t| t.verts.iter()) - .copied() - .collect(); + let mesh = gltf.meshes().next().unwrap(); + let primitive = mesh.primitives().next().unwrap(); + + let reader = primitive.reader(|buffer| Some(&buffer_data[buffer.index()])); + + let (positions, normals, colors) = ( + reader.read_positions().unwrap(), + reader.read_normals().unwrap(), + reader.read_colors(0).unwrap().into_rgba_f32(), + ); + + let indices = reader.read_indices().map(|indices| indices.into_u32()); + let indices = match indices { + Some(indices) => indices.collect::>(), + None => (0..positions.len() as u32).collect(), + }; + + let vertices = positions + .zip(normals) + .zip(colors) + .map(|((pos, norm), color)| GPUVertex { + pos: [pos[0], pos[1], pos[2], 1.0], + norm: [norm[0], norm[1], norm[2], 1.0], + color, + }) + .collect::>(); let vertex_buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some("Vertex buffer"), - contents: bytemuck::cast_slice(&vertex_data), + label: Some("Vertex Buffer"), + contents: bytemuck::cast_slice(&vertices), usage: wgpu::BufferUsage::VERTEX, }); let index_buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some("Index buffer"), - contents: bytemuck::cast_slice(&index_data), + label: Some("Index Buffer"), + contents: bytemuck::cast_slice(&indices), usage: wgpu::BufferUsage::INDEX, }); @@ -170,14 +197,14 @@ impl Model { multisample: wgpu::MultisampleState::default(), }); - Model { + (Model { render_pipeline, index_buf, vertex_buf, uniform_buf, bind_group, - index_count: tris.len() as u32 * 3, - } + index_count: indices.len() as u32 // index_count: tris.len() as u32 * 3, + }, vertices) } pub fn draw(&self, camera: &Camera,