1use crate::{
15 device_viewer::DeviceViewer, imgui_renderer::ImGuiRenderer, model::Model, renderer::Renderer,
16 settings::Settings, Quaternion, Vector3, GL_SCALE,
17};
18
19use autd3_driver::geometry::{Device, Transducer};
20
21use vulkano::{
22 command_buffer::{
23 AutoCommandBufferBuilder, CommandBufferUsage, RenderPassBeginInfo, SubpassContents,
24 },
25 sync::GpuFuture,
26};
27use winit::{
28 event::{Event, WindowEvent},
29 event_loop::{EventLoop, EventLoopBuilder},
30 platform::run_return::EventLoopExtRunReturn,
31};
32
33#[cfg(target_os = "windows")]
34use winit::platform::windows::WindowExtWindows;
35
36#[derive(Default)]
38pub struct GeometryViewer {
39 window_height: u32,
40 window_width: u32,
41 vsync: bool,
42 settings: Settings,
43}
44
45impl GeometryViewer {
46 pub fn new() -> Self {
47 Self {
48 window_width: 800,
49 window_height: 600,
50 vsync: true,
51 settings: Settings::new(0),
52 }
53 }
54
55 pub fn with_window_size(self, width: u32, height: u32) -> Self {
57 Self {
58 window_width: width,
59 window_height: height,
60 ..self
61 }
62 }
63
64 pub fn with_vsync(self, vsync: bool) -> Self {
66 Self { vsync, ..self }
67 }
68
69 pub fn with_settings(self, settings: Settings) -> Self {
71 Self { settings, ..self }
72 }
73
74 pub fn run<T: Transducer>(&mut self, devices: &[Device<T>]) -> anyhow::Result<i32> {
88 let mut event_loop = EventLoopBuilder::<()>::with_user_event().build();
89 self.run_with_event_loop(devices, &mut event_loop)
90 }
91
92 pub fn create_event_loop() -> EventLoop<()> {
96 EventLoopBuilder::<()>::with_user_event().build()
97 }
98
99 #[allow(clippy::let_and_return)]
112 pub fn run_with_event_loop<T: Transducer>(
113 &mut self,
114 devices: &[Device<T>],
115 event_loop: &mut EventLoop<()>,
116 ) -> anyhow::Result<i32> {
117 let mut render = Renderer::new(
118 event_loop,
119 "AUTD GeometryViewer",
120 self.window_width as _,
121 self.window_height as _,
122 self.vsync,
123 );
124 render.window().focus_window();
125
126 let model = Model::new()?;
127 let mut device_viewer = DeviceViewer::new(&render, &model);
128
129 let num_dev = devices.len();
130
131 let geo: Vec<_> = devices
132 .iter()
133 .map(|dev| {
134 let tr = &dev[0];
135 let pos = tr.position();
136 let rot = tr.rotation();
137 (
138 Vector3::new(pos.x as _, pos.y as _, pos.z as _) * GL_SCALE,
139 Quaternion::new(rot.w as _, rot.i as _, rot.j as _, rot.k as _),
140 )
141 })
142 .collect();
143
144 let mut settings = self.settings.clone();
145 if settings.shows.len() < num_dev {
146 settings.shows.resize(num_dev, true);
147 }
148
149 render.move_camera(settings.camera_pos(), settings.camera_rot());
150
151 let mut imgui = ImGuiRenderer::new(&render);
152
153 #[cfg(target_os = "windows")]
154 let hwnd = render.window().hwnd();
155
156 let mut is_running = true;
157 let r = event_loop.run_return(move |event, _, control_flow| {
158 match event {
159 Event::WindowEvent {
160 event: WindowEvent::CloseRequested,
161 ..
162 } => {
163 is_running = false;
164 control_flow.set_exit();
165 }
166 Event::WindowEvent {
167 event: WindowEvent::Resized(..),
168 window_id,
169 } if window_id == render.window().id() => {
170 render.resize();
171 imgui.resized(render.window(), &event);
172 }
173 Event::WindowEvent {
174 event:
175 WindowEvent::ScaleFactorChanged {
176 scale_factor,
177 new_inner_size,
178 },
179 window_id,
180 } if window_id == render.window().id() => {
181 *new_inner_size = render
182 .window()
183 .inner_size()
184 .to_logical::<u32>(render.window().scale_factor())
185 .to_physical(scale_factor);
186 render.resize();
187 let event_imgui: Event<'_, ()> = Event::WindowEvent {
188 window_id,
189 event: WindowEvent::ScaleFactorChanged {
190 scale_factor,
191 new_inner_size,
192 },
193 };
194 imgui.resized(render.window(), &event_imgui);
195 }
196 Event::MainEventsCleared => {
197 imgui.prepare_frame(render.window());
198 render.window().request_redraw();
199 }
200 Event::NewEvents(_) => {
201 imgui.update_delta_time();
202 render.window().request_redraw();
203 }
204 Event::RedrawRequested(_) => {
205 let before_pipeline_future = match render.start_frame() {
206 Err(e) => {
207 eprintln!("{}", e);
208 return;
209 }
210 Ok(future) => future,
211 };
212 let after_future = {
213 let framebuffer = render.frame_buffer();
214
215 let mut builder = AutoCommandBufferBuilder::primary(
216 render.command_buffer_allocator(),
217 render.queue().queue_family_index(),
218 CommandBufferUsage::OneTimeSubmit,
219 )
220 .unwrap();
221
222 let clear_values =
223 vec![Some(settings.background.into()), Some(1f32.into()), None];
224 builder
225 .begin_render_pass(
226 RenderPassBeginInfo {
227 clear_values,
228 ..RenderPassBeginInfo::framebuffer(framebuffer)
229 },
230 SubpassContents::Inline,
231 )
232 .unwrap()
233 .set_viewport(0, [render.viewport()]);
234
235 render.move_camera(settings.camera_pos(), settings.camera_rot());
236 let view = render.get_view();
237 let proj = render.get_projection(
238 settings.camera_fov,
239 settings.camera_near_clip,
240 settings.camera_far_clip,
241 );
242
243 device_viewer.render(&model, &geo, (view, proj), &settings, &mut builder);
244
245 builder.end_render_pass().unwrap();
246
247 imgui.render(&render, &geo, &mut settings, &mut builder);
248
249 let command_buffer = builder.build().unwrap();
250
251 let future = before_pipeline_future
252 .then_execute(render.queue(), command_buffer)
253 .unwrap();
254
255 future.boxed()
256 };
257
258 render.finish_frame(after_future);
259 }
260 event => {
261 imgui.handle_event(render.window(), &event);
262 }
263 }
264 if !is_running {
265 control_flow.set_exit();
266 }
267 });
268
269 #[cfg(target_os = "windows")]
270 unsafe {
271 let _ = windows::Win32::UI::WindowsAndMessaging::DestroyWindow(
272 windows::Win32::Foundation::HWND(hwnd),
273 );
274 }
275
276 Ok(r)
277 }
278}