Add stub 3D gizmo

This commit is contained in:
mars 2022-09-17 11:28:10 -06:00
parent 17635f056e
commit 4bfd6977c3
3 changed files with 54 additions and 23 deletions

View File

@ -8,7 +8,8 @@ bytemuck = "^1.0"
crossbeam-channel = "^0.5" crossbeam-channel = "^0.5"
cyborg = { path = "../", features = ["legion"] } cyborg = { path = "../", features = ["legion"] }
egui = "0.18" egui = "0.18"
egui-winit = "0.18.0" egui-gizmo = "0.7"
egui-winit = "0.18"
egui_wgpu_backend = "0.18.0" egui_wgpu_backend = "0.18.0"
glam = { version = "0.20", features = ["serde"] } glam = { version = "0.20", features = ["serde"] }
gltf = { version = "1.0", features = ["utils"] } gltf = { version = "1.0", features = ["utils"] }

View File

@ -211,7 +211,7 @@ impl UserInterface {
}); });
egui::CentralPanel::default().show(ctx, |ui| { egui::CentralPanel::default().show(ctx, |ui| {
ui.add(viewport); viewport.show(ui);
ui.heading("Viewport"); ui.heading("Viewport");
}); });
} }
@ -260,6 +260,7 @@ pub struct ViewportWidget {
pub flycam: Flycam, pub flycam: Flycam,
pub width: u32, pub width: u32,
pub height: u32, pub height: u32,
pub dragging: bool,
} }
impl ViewportWidget { impl ViewportWidget {
@ -269,21 +270,39 @@ impl ViewportWidget {
flycam: Flycam::new(0.002, 10.0, 0.25), flycam: Flycam::new(0.002, 10.0, 0.25),
width: 640, width: 640,
height: 480, height: 480,
dragging: false,
} }
} }
}
impl egui::Widget for &mut ViewportWidget { fn should_drag(
fn ui(self, ui: &mut egui::Ui) -> egui::Response { &self,
viewport: egui::Rect,
gizmo_active: bool,
pointer: &egui::PointerState,
) -> bool {
if gizmo_active {
false
} else if !pointer.primary_down() {
false
} else if self.dragging {
true
} else if let Some(pos) = pointer.interact_pos() {
viewport.contains(pos)
} else {
false
}
}
fn show(&mut self, ui: &mut egui::Ui) {
ui.style_mut().spacing.window_margin = egui::style::Margin::same(0.0); ui.style_mut().spacing.window_margin = egui::style::Margin::same(0.0);
let rect = ui.max_rect(); let rect = ui.max_rect();
let id = egui::Id::new("viewport_widget");
let sense = egui::Sense::click_and_drag();
let response = ui.interact(rect, id, sense);
self.width = rect.width().round() as u32; self.width = rect.width().round() as u32;
self.height = rect.height().round() as u32; self.height = rect.height().round() as u32;
self.flycam.resize(self.width, self.height);
self.flycam.update();
use egui::{pos2, Color32, Mesh, Rect, Shape}; use egui::{pos2, Color32, Mesh, Rect, Shape};
let mut mesh = Mesh::with_texture(self.texture); let mut mesh = Mesh::with_texture(self.texture);
let uv = Rect::from_min_max(pos2(0.0, 0.0), pos2(1.0, 1.0)); let uv = Rect::from_min_max(pos2(0.0, 0.0), pos2(1.0, 1.0));
@ -291,11 +310,22 @@ impl egui::Widget for &mut ViewportWidget {
mesh.add_rect_with_uv(rect, uv, tint); mesh.add_rect_with_uv(rect, uv, tint);
ui.painter().add(Shape::mesh(mesh)); ui.painter().add(Shape::mesh(mesh));
if response.dragged() { let gizmo = egui_gizmo::Gizmo::new("My gizmo")
let delta = response.drag_delta(); .viewport(rect)
.view_matrix(self.flycam.get_view().to_cols_array_2d())
.projection_matrix(self.flycam.get_projection().to_cols_array_2d());
let gizmo = gizmo.interact(ui);
let input = ui.input();
self.dragging = self.should_drag(rect, gizmo.is_some(), &input.pointer);
if self.dragging {
let delta = input.pointer.delta();
self.flycam.process_mouse(delta.x as f64, delta.y as f64); self.flycam.process_mouse(delta.x as f64, delta.y as f64);
for event in ui.input().events.iter() { for event in input.events.iter() {
match event { match event {
egui::Event::Key { key, pressed, .. } => { egui::Event::Key { key, pressed, .. } => {
use winit::event::{ElementState, VirtualKeyCode}; use winit::event::{ElementState, VirtualKeyCode};
@ -324,14 +354,9 @@ impl egui::Widget for &mut ViewportWidget {
_ => {} _ => {}
} }
} }
} else if response.drag_released() { } else {
self.flycam.defocus(); self.flycam.defocus();
} }
self.flycam.resize(self.width, self.height);
self.flycam.update();
response
} }
} }

View File

@ -233,16 +233,21 @@ impl Flycam {
pub fn get_eye(&self) -> [f32; 4] { pub fn get_eye(&self) -> [f32; 4] {
self.position.extend(0.0).to_array() self.position.extend(0.0).to_array()
} }
pub fn get_vp(&self) -> [[f32; 4]; 4] { pub fn get_view(&self) -> glam::Mat4 {
// view matrix is inverted camera pose (world space to camera space) // view matrix is inverted camera pose (world space to camera space)
let rotation = Mat4::from_quat(self.get_orientation().inverse()); let rotation = Mat4::from_quat(self.get_orientation().inverse());
let translation = Mat4::from_translation(-self.position); let translation = Mat4::from_translation(-self.position);
let view = rotation * translation; rotation * translation
}
// perspective projection
let proj = Mat4::perspective_rh_gl(self.fovy, self.aspect, self.znear, self.zfar); pub fn get_projection(&self) -> glam::Mat4 {
Mat4::perspective_rh_gl(self.fovy, self.aspect, self.znear, self.zfar)
}
pub fn get_vp(&self) -> [[f32; 4]; 4] {
let view = self.get_view();
let proj = self.get_projection();
let vp = proj * view; let vp = proj * view;
vp.to_cols_array_2d() vp.to_cols_array_2d()
} }