From 7b22551bee769f46b5d1a0f4c9b90344185bf893 Mon Sep 17 00:00:00 2001 From: numzero Date: Sat, 15 Nov 2025 19:13:07 +0300 Subject: [PATCH] add some real UI --- src/lib.rs | 39 +++++-- src/main.rs | 19 +++- ui/src/api.cxx | 6 +- ui/src/api.hxx | 20 +++- ui/src/lib.rs | 6 +- ui/src/main_window.cxx | 22 ++++ ui/src/main_window.hxx | 3 + ui/src/main_window.ui | 225 ++++++++++++++++++++++++++++++++++++++++- ui/src/viewport.cxx | 7 +- ui/src/viewport.hxx | 3 + 10 files changed, 322 insertions(+), 28 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index bbf3c90..df375e9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,6 +17,23 @@ mod trace; const OUTPUT_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Bgra8UnormSrgb; +#[derive(Debug, Clone, Copy, PartialEq)] +#[repr(C)] +pub struct SphericalPosition { + pub yaw: f32, + pub pitch: f32, + pub distance: f32, +} + +#[derive(Debug, Clone, Copy)] +#[repr(C)] +pub struct RedrawArgs { + pub camera_position: SphericalPosition, + pub light_position: SphericalPosition, + pub light_radius: f32, + pub light_spread: f32, +} + pub struct Gpu { device: wgpu::Device, queue: wgpu::Queue, @@ -88,11 +105,11 @@ impl Core { } } - fn render(&self, output: &wgpu::Texture) { + fn render(&self, output: &wgpu::Texture, args: &RedrawArgs) { let camera = OrbitalCamera { - position_yaw: PI / 4., - position_pitch: 0.5f32.sqrt().atan(), - distance: 3.0, + position_yaw: args.camera_position.yaw, + position_pitch: args.camera_position.pitch, + distance: args.camera_position.distance, }; let aspect = { let size = output.size(); @@ -134,11 +151,11 @@ impl Core { self.pipeline.render(&mut pass, [&self.tripod]); let source = Source { - position_yaw: 0.0, - position_pitch: PI / 3., - distance: 1.0, - radius: 0.125, - spread: 0.125, + position_yaw: args.light_position.yaw, + position_pitch: args.light_position.pitch, + distance: args.light_position.distance, + radius: args.light_radius, + spread: args.light_spread, }; let contour: Vec = loop_list(source.contour(17)) @@ -227,9 +244,9 @@ impl Core { /// Redraws the entire surface. /// /// [`Self::configure`] must be called at least once before this. - pub fn redraw(&mut self) { + pub fn redraw(&mut self, args: &RedrawArgs) { let output = self.surface.get_current_texture().unwrap(); - self.render(&output.texture); + self.render(&output.texture, args); output.present(); } } diff --git a/src/main.rs b/src/main.rs index db10706..615a203 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,7 @@ -use std::sync::Arc; +use std::{f32::consts::PI, sync::Arc}; use glam::uvec2; -use photon_light::{Core, init_gpu_inner}; +use photon_light::{Core, RedrawArgs, SphericalPosition, init_gpu_inner}; use winit::{ application::ApplicationHandler, event::WindowEvent, @@ -37,7 +37,20 @@ impl MainWindow { WindowEvent::Resized(physical_size) => self .core .configure(uvec2(physical_size.width, physical_size.height)), - WindowEvent::RedrawRequested => self.core.redraw(), + WindowEvent::RedrawRequested => self.core.redraw(&RedrawArgs { + camera_position: SphericalPosition { + yaw: PI / 4., + pitch: 0.5f32.sqrt().atan(), + distance: 3.0, + }, + light_position: SphericalPosition { + yaw: 0.0, + pitch: PI / 3., + distance: 1.0, + }, + light_radius: 0.125, + light_spread: 0.125, + }), _ => {} } } diff --git a/ui/src/api.cxx b/ui/src/api.cxx index 2acbb55..d65a690 100644 --- a/ui/src/api.cxx +++ b/ui/src/api.cxx @@ -7,7 +7,7 @@ namespace ffi { extern "C" Core* rt4_viewport_create(xcb_connection_t* connection, std::uint32_t window); extern "C" void rt4_viewport_destroy(Core* viewport); extern "C" void rt4_viewport_configure(Core* viewport, std::uint32_t width, std::uint32_t height); -extern "C" void rt4_viewport_redraw(Core* viewport); +extern "C" void rt4_viewport_redraw(Core* viewport, const RedrawArgs* args); } // namespace ffi BoxCore::BoxCore(BoxCore&& b) @@ -52,6 +52,6 @@ void MutCore::configure(std::uint32_t width, std::uint32_t height) const { rt4_viewport_configure(use(), width, height); } -void MutCore::redraw() const { - rt4_viewport_redraw(use()); +void MutCore::redraw(const RedrawArgs& args) const { + rt4_viewport_redraw(use(), &args); } diff --git a/ui/src/api.hxx b/ui/src/api.hxx index 02b8e70..50b9e67 100644 --- a/ui/src/api.hxx +++ b/ui/src/api.hxx @@ -6,7 +6,23 @@ struct xcb_connection_t; namespace ffi { struct Core; -} + +struct SphericalPosition { + float yaw; + float pitch; + float distance; +}; + +struct RedrawArgs { + SphericalPosition camera_position; + SphericalPosition light_position; + float light_radius; + float light_spread; +}; +} // namespace ffi + +using ffi::RedrawArgs; +using ffi::SphericalPosition; class MutCore { friend class BoxCore; @@ -15,7 +31,7 @@ public: explicit operator bool() const { return ptr; } void configure(std::uint32_t width, std::uint32_t height) const; - void redraw() const; + void redraw(const RedrawArgs& args) const; private: ffi::Core* ptr = nullptr; diff --git a/ui/src/lib.rs b/ui/src/lib.rs index daf90a7..9ee96ef 100644 --- a/ui/src/lib.rs +++ b/ui/src/lib.rs @@ -1,7 +1,7 @@ use std::{ffi::c_void, num::NonZero, ptr::NonNull}; use glam::uvec2; -use photon_light::{Core, init_gpu_inner}; +use photon_light::{Core, RedrawArgs, init_gpu_inner}; use raw_window_handle::{RawDisplayHandle, RawWindowHandle, XcbDisplayHandle, XcbWindowHandle}; unsafe fn create_viewport( @@ -40,6 +40,6 @@ unsafe extern "C" fn rt4_viewport_configure(viewport: &mut Core, width: u32, hei } #[unsafe(no_mangle)] -unsafe extern "C" fn rt4_viewport_redraw(viewport: &mut Core) { - viewport.redraw(); +unsafe extern "C" fn rt4_viewport_redraw(viewport: &mut Core, args: &RedrawArgs) { + viewport.redraw(args); } diff --git a/ui/src/main_window.cxx b/ui/src/main_window.cxx index abdb991..caa80e9 100644 --- a/ui/src/main_window.cxx +++ b/ui/src/main_window.cxx @@ -6,8 +6,30 @@ PhotonLight::PhotonLight(QWidget* parent) : QMainWindow(parent), m_ui(new Ui::MainWindow) { m_ui->setupUi(this); + emit updateView(); } PhotonLight::~PhotonLight() = default; +float deg_to_rad(float val) { + return val * float(M_PI / 180); +} + +void PhotonLight::updateView() { + m_ui->viewport->setView(RedrawArgs{ + .camera_position = SphericalPosition{ + .yaw = deg_to_rad(m_ui->cameraYaw->value()), + .pitch = deg_to_rad(m_ui->cameraPitch->value()), + .distance = 3.0, + }, + .light_position = SphericalPosition{ + .yaw = deg_to_rad(m_ui->lightYaw->value()), + .pitch = deg_to_rad(m_ui->lightPitch->value()), + .distance = 1.0, + }, + .light_radius = 0.125, + .light_spread = 0.125, + }); +} + #include "moc_main_window.cpp" diff --git a/ui/src/main_window.hxx b/ui/src/main_window.hxx index 94005de..1ca73cc 100644 --- a/ui/src/main_window.hxx +++ b/ui/src/main_window.hxx @@ -14,6 +14,9 @@ public: explicit PhotonLight(QWidget* parent = nullptr); ~PhotonLight() override; +public slots: + void updateView(); + private: const std::unique_ptr m_ui; }; diff --git a/ui/src/main_window.ui b/ui/src/main_window.ui index a6b18ec..3974303 100644 --- a/ui/src/main_window.ui +++ b/ui/src/main_window.ui @@ -6,8 +6,8 @@ 0 0 - 1220 - 823 + 800 + 600 @@ -16,7 +16,7 @@ - + @@ -25,12 +25,159 @@ 0 0 - 1220 + 800 38 + + + QDockWidget::DockWidgetFloatable|QDockWidget::DockWidgetMovable + + + 2 + + + + + + + Camera + + + + + + Yaw + + + + + + + -180 + + + 180 + + + 15 + + + 45 + + + Qt::Horizontal + + + + + + + Pitch + + + + + + + -90 + + + 90 + + + 15 + + + 35 + + + Qt::Horizontal + + + + + + + + + + Light + + + + + + Yaw + + + + + + + -180 + + + 180 + + + 15 + + + Qt::Horizontal + + + + + + + Pitch + + + + + + + -90 + + + 90 + + + 15 + + + 60 + + + Qt::Horizontal + + + false + + + + + + + + + + Qt::Vertical + + + + 20 + 385 + + + + + + + @@ -41,5 +188,73 @@ - + + + cameraYaw + valueChanged(int) + MainWindow + updateView() + + + 688 + 159 + + + 403 + 362 + + + + + cameraPitch + valueChanged(int) + MainWindow + updateView() + + + 688 + 215 + + + 403 + 362 + + + + + lightYaw + valueChanged(int) + MainWindow + updateView() + + + 688 + 319 + + + 403 + 362 + + + + + lightPitch + valueChanged(int) + MainWindow + updateView() + + + 688 + 375 + + + 403 + 362 + + + + + + updateView() + diff --git a/ui/src/viewport.cxx b/ui/src/viewport.cxx index bf53b59..483ba07 100644 --- a/ui/src/viewport.cxx +++ b/ui/src/viewport.cxx @@ -14,6 +14,11 @@ Viewport::Viewport(QWidget* parent, Qt::WindowFlags f) Viewport::~Viewport() = default; +void Viewport::setView(RedrawArgs new_args) { + args = new_args; + update(); +} + QPaintEngine* Viewport::paintEngine() const { return nullptr; } @@ -32,7 +37,7 @@ bool Viewport::event(QEvent* event) { void Viewport::paintEvent(QPaintEvent* event) { if (!core) recreate(); - core->redraw(); + core->redraw(args); } void Viewport::resizeEvent(QResizeEvent* event) { diff --git a/ui/src/viewport.hxx b/ui/src/viewport.hxx index 67eb446..95839b9 100644 --- a/ui/src/viewport.hxx +++ b/ui/src/viewport.hxx @@ -12,6 +12,8 @@ public: ~Viewport() override; QPaintEngine* paintEngine() const override; + void setView(RedrawArgs new_args); + protected: bool event(QEvent* event) override; void paintEvent(QPaintEvent* event) override; @@ -19,6 +21,7 @@ protected: private: BoxCore core; + RedrawArgs args = {}; void recreate(); void updateSize();