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"
cyborg = { path = "../", features = ["legion"] }
egui = "0.18"
egui-winit = "0.18.0"
egui-gizmo = "0.7"
egui-winit = "0.18"
egui_wgpu_backend = "0.18.0"
glam = { version = "0.20", features = ["serde"] }
gltf = { version = "1.0", features = ["utils"] }

View File

@ -211,7 +211,7 @@ impl UserInterface {
});
egui::CentralPanel::default().show(ctx, |ui| {
ui.add(viewport);
viewport.show(ui);
ui.heading("Viewport");
});
}
@ -260,6 +260,7 @@ pub struct ViewportWidget {
pub flycam: Flycam,
pub width: u32,
pub height: u32,
pub dragging: bool,
}
impl ViewportWidget {
@ -269,21 +270,39 @@ impl ViewportWidget {
flycam: Flycam::new(0.002, 10.0, 0.25),
width: 640,
height: 480,
dragging: false,
}
}
}
impl egui::Widget for &mut ViewportWidget {
fn ui(self, ui: &mut egui::Ui) -> egui::Response {
fn should_drag(
&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);
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.height = rect.height().round() as u32;
self.flycam.resize(self.width, self.height);
self.flycam.update();
use egui::{pos2, Color32, Mesh, Rect, Shape};
let mut mesh = Mesh::with_texture(self.texture);
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);
ui.painter().add(Shape::mesh(mesh));
if response.dragged() {
let delta = response.drag_delta();
let gizmo = egui_gizmo::Gizmo::new("My gizmo")
.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);
for event in ui.input().events.iter() {
for event in input.events.iter() {
match event {
egui::Event::Key { key, pressed, .. } => {
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.resize(self.width, self.height);
self.flycam.update();
response
}
}

View File

@ -233,16 +233,21 @@ impl Flycam {
pub fn get_eye(&self) -> [f32; 4] {
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)
let rotation = Mat4::from_quat(self.get_orientation().inverse());
let translation = Mat4::from_translation(-self.position);
let view = rotation * translation;
// perspective projection
let proj = Mat4::perspective_rh_gl(self.fovy, self.aspect, self.znear, self.zfar);
rotation * translation
}
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;
vp.to_cols_array_2d()
}