Fix requiring viewport to be visible to render preview image
This commit is contained in:
3
TODO.md
3
TODO.md
@@ -91,6 +91,7 @@
|
||||
- [x] Cleanup self intersection resolution
|
||||
- [ ] Dont fail to load an stl without normals
|
||||
- [ ] GPU accalration for post processing effect?
|
||||
- [ ] Fix requiring viewport to be visible to render preview image
|
||||
- [x] Fix requiring viewport to be visible to render preview image
|
||||
- [x] Visulize mesh outside of bounging box
|
||||
- [ ] Save panel layout
|
||||
- [ ] Random triangle color render mode
|
||||
|
@@ -13,6 +13,7 @@ use egui::{Vec2, Visuals};
|
||||
use egui_dock::{DockState, NodeIndex};
|
||||
use egui_phosphor::regular::CARET_RIGHT;
|
||||
use egui_tracing::EventCollector;
|
||||
use egui_wgpu::RenderState;
|
||||
use nalgebra::Vector2;
|
||||
use parking_lot::RwLock;
|
||||
use tracing::{info, warn};
|
||||
@@ -23,7 +24,7 @@ use crate::{
|
||||
elephant_foot_fixer::{self},
|
||||
PluginManager,
|
||||
},
|
||||
render::{camera::Camera, rendered_mesh::RenderedMesh},
|
||||
render::{camera::Camera, preview, rendered_mesh::RenderedMesh},
|
||||
ui::{
|
||||
drag_and_drop,
|
||||
popup::{Popup, PopupIcon, PopupManager},
|
||||
@@ -43,6 +44,7 @@ use remote_print::RemotePrint;
|
||||
use slice_operation::{SliceOperation, SliceResult};
|
||||
|
||||
pub struct App {
|
||||
pub render_state: RenderState,
|
||||
// todo: dock state in ui_state?
|
||||
pub dock_state: DockState<Tab>,
|
||||
pub fps: FpsTracker,
|
||||
@@ -66,7 +68,12 @@ pub struct FpsTracker {
|
||||
}
|
||||
|
||||
impl App {
|
||||
pub fn new(config_dir: PathBuf, config: Config, event_collector: EventCollector) -> Self {
|
||||
pub fn new(
|
||||
render_state: RenderState,
|
||||
config_dir: PathBuf,
|
||||
config: Config,
|
||||
event_collector: EventCollector,
|
||||
) -> Self {
|
||||
let mut dock_state = DockState::new(vec![Tab::Viewport]);
|
||||
let surface = dock_state.main_surface_mut();
|
||||
let [_old_node, new_node] = surface.split_left(NodeIndex::root(), 0.20, vec![Tab::Models]);
|
||||
@@ -75,6 +82,7 @@ impl App {
|
||||
surface.split_below(new_node, 0.5, vec![Tab::Workspace, Tab::RemotePrint]);
|
||||
|
||||
Self {
|
||||
render_state,
|
||||
dock_state,
|
||||
popup: PopupManager::new(),
|
||||
state: UiState {
|
||||
@@ -218,8 +226,8 @@ impl eframe::App for App {
|
||||
// todo: probably dont do this
|
||||
let app = unsafe { &mut *(self as *mut _) };
|
||||
self.popup.render(app, ctx);
|
||||
// only update the visuals if the theme has changed
|
||||
|
||||
// only update the visuals if the theme has changed
|
||||
match self.config.theme {
|
||||
Theme::Dark => ctx.set_visuals(Visuals::dark()),
|
||||
Theme::Light => ctx.set_visuals(Visuals::light()),
|
||||
@@ -230,6 +238,7 @@ impl eframe::App for App {
|
||||
}
|
||||
|
||||
self.remote_print.tick(app);
|
||||
preview::process_previews(app);
|
||||
drag_and_drop::update(self, ctx);
|
||||
windows::ui(self, ctx);
|
||||
}
|
||||
|
@@ -68,13 +68,13 @@ fn main() -> Result<()> {
|
||||
..Default::default()
|
||||
},
|
||||
Box::new(|cc| {
|
||||
render::init_wgpu(cc);
|
||||
let render_state = render::init_wgpu(cc);
|
||||
|
||||
let mut fonts = FontDefinitions::default();
|
||||
egui_phosphor::add_to_fonts(&mut fonts, egui_phosphor::Variant::Regular);
|
||||
cc.egui_ctx.set_fonts(fonts);
|
||||
|
||||
Box::new(App::new(config_dir, config, collector))
|
||||
Box::new(App::new(render_state, config_dir, config, collector))
|
||||
}),
|
||||
)
|
||||
.unwrap();
|
||||
|
@@ -2,6 +2,7 @@ use std::mem;
|
||||
|
||||
use dispatch::solid_line::SolidLineDispatch;
|
||||
use eframe::CreationContext;
|
||||
use egui_wgpu::RenderState;
|
||||
use nalgebra::Vector4;
|
||||
use pipelines::{
|
||||
model::ModelPipeline, slice_preview::SlicePreviewPipeline, target_point::TargetPointPipeline,
|
||||
@@ -34,7 +35,7 @@ pub struct ModelVertex {
|
||||
pub position: [f32; 4],
|
||||
}
|
||||
|
||||
pub fn init_wgpu(cc: &CreationContext) {
|
||||
pub fn init_wgpu(cc: &CreationContext) -> RenderState {
|
||||
let render_state = cc.wgpu_render_state.as_ref().unwrap();
|
||||
let device = &render_state.device;
|
||||
|
||||
@@ -47,6 +48,8 @@ pub fn init_wgpu(cc: &CreationContext) {
|
||||
resources.insert(SlicePreviewRenderResources {
|
||||
slice_preview_pipeline: SlicePreviewPipeline::new(device),
|
||||
});
|
||||
|
||||
render_state.clone()
|
||||
}
|
||||
|
||||
impl ModelVertex {
|
||||
|
@@ -1,7 +1,7 @@
|
||||
use std::f32::consts::PI;
|
||||
|
||||
use image::{Rgba, RgbaImage};
|
||||
use nalgebra::{Vector2, Vector3};
|
||||
use nalgebra::{Matrix4, Vector2, Vector3};
|
||||
use tracing::info;
|
||||
use wgpu::{
|
||||
BufferAddress, BufferDescriptor, BufferUsages, Color, CommandEncoderDescriptor, Device,
|
||||
@@ -11,20 +11,33 @@ use wgpu::{
|
||||
TextureFormat, TextureUsages, TextureView, TextureViewDescriptor,
|
||||
};
|
||||
|
||||
use crate::TEXTURE_FORMAT;
|
||||
use crate::{app::App, TEXTURE_FORMAT};
|
||||
|
||||
use super::{camera::Camera, pipelines::model::ModelPipeline, workspace::WorkspaceRenderCallback};
|
||||
use super::{
|
||||
camera::Camera,
|
||||
pipelines::model::ModelPipeline,
|
||||
workspace::{WorkspaceRenderCallback, WorkspaceRenderResources},
|
||||
};
|
||||
|
||||
pub fn process_previews(app: &App) {
|
||||
match &app.slice_operation {
|
||||
Some(slice_operation) if slice_operation.needs_preview_image() => {
|
||||
let image = render_preview_image(app, (512, 512));
|
||||
slice_operation.add_preview_image(image);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Allow rendering multiple preview images at once
|
||||
pub fn render_preview_image(
|
||||
device: &Device,
|
||||
queue: &Queue,
|
||||
size: (u32, u32),
|
||||
model_pipeline: &mut ModelPipeline,
|
||||
workspace: &WorkspaceRenderCallback,
|
||||
) -> RgbaImage {
|
||||
fn render_preview_image(app: &App, size: (u32, u32)) -> RgbaImage {
|
||||
info!("Generating {}x{} preview image", size.0, size.1);
|
||||
|
||||
let mut resources = app.get_callback_resource_mut::<WorkspaceRenderResources>();
|
||||
let (device, queue) = (&app.render_state.device, &app.render_state.queue);
|
||||
|
||||
let mut workspace = app.get_workspace_render_callback(Matrix4::zeros(), false);
|
||||
|
||||
let (texture, resolved_texture, depth_texture) = init_textures(device, size);
|
||||
let texture_view = texture.create_view(&TextureViewDescriptor::default());
|
||||
let resolved_texture_view = resolved_texture.create_view(&TextureViewDescriptor::default());
|
||||
@@ -40,26 +53,22 @@ pub fn render_preview_image(
|
||||
let target = (min + max) / 2.0;
|
||||
let distance = (min - max).magnitude() / 2.0;
|
||||
|
||||
let mut old_workspace = workspace.clone();
|
||||
old_workspace.camera = Camera {
|
||||
workspace.camera = Camera {
|
||||
target,
|
||||
distance,
|
||||
angle: Vector2::new(0.0, PI / 10.0),
|
||||
..old_workspace.camera
|
||||
..workspace.camera
|
||||
};
|
||||
|
||||
let workspace = WorkspaceRenderCallback {
|
||||
transform: old_workspace
|
||||
.camera
|
||||
.view_projection_matrix(size.0 as f32 / size.1 as f32),
|
||||
..old_workspace
|
||||
};
|
||||
model_pipeline.prepare(device, &workspace);
|
||||
let aspect = size.0 as f32 / size.1 as f32;
|
||||
workspace.transform = workspace.camera.view_projection_matrix(aspect);
|
||||
|
||||
resources.model_pipeline.prepare(device, &workspace);
|
||||
|
||||
render_preview(
|
||||
device,
|
||||
queue,
|
||||
model_pipeline,
|
||||
&resources.model_pipeline,
|
||||
&workspace,
|
||||
&texture_view,
|
||||
&resolved_texture_view,
|
||||
|
@@ -6,13 +6,12 @@ use nalgebra::{Matrix4, Vector3};
|
||||
use parking_lot::RwLock;
|
||||
use wgpu::{CommandBuffer, CommandEncoder, Device, Queue, RenderPass};
|
||||
|
||||
use crate::app::{config::Config, slice_operation::SliceOperation};
|
||||
use crate::app::config::Config;
|
||||
|
||||
use super::{
|
||||
camera::Camera,
|
||||
dispatch::solid_line::SolidLineDispatch,
|
||||
pipelines::{model::ModelPipeline, target_point::TargetPointPipeline},
|
||||
preview::render_preview_image,
|
||||
rendered_mesh::RenderedMesh,
|
||||
};
|
||||
|
||||
@@ -27,6 +26,7 @@ pub struct WorkspaceRenderResources {
|
||||
pub struct WorkspaceRenderCallback {
|
||||
pub camera: Camera,
|
||||
pub transform: Matrix4<f32>,
|
||||
pub is_moving: bool,
|
||||
|
||||
pub bed_size: Vector3<f32>,
|
||||
pub grid_size: f32,
|
||||
@@ -34,8 +34,6 @@ pub struct WorkspaceRenderCallback {
|
||||
pub models: Arc<RwLock<Vec<RenderedMesh>>>,
|
||||
pub config: Config,
|
||||
|
||||
pub is_moving: bool,
|
||||
pub slice_operation: Option<SliceOperation>,
|
||||
pub line_support_debug: Vec<[Vector3<f32>; 2]>,
|
||||
}
|
||||
|
||||
@@ -50,15 +48,6 @@ impl CallbackTrait for WorkspaceRenderCallback {
|
||||
) -> Vec<CommandBuffer> {
|
||||
let resources = resources.get_mut::<WorkspaceRenderResources>().unwrap();
|
||||
|
||||
match &self.slice_operation {
|
||||
Some(slice_operation) if slice_operation.needs_preview_image() => {
|
||||
let pipeline = &mut resources.model_pipeline;
|
||||
let image = render_preview_image(device, queue, (512, 512), pipeline, self);
|
||||
slice_operation.add_preview_image(image);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
resources.solid_line.prepare(device, queue, self);
|
||||
resources.model_pipeline.prepare(device, self);
|
||||
resources.target_point_pipeline.prepare(queue, self);
|
||||
|
@@ -2,6 +2,8 @@ use eframe::Theme;
|
||||
use egui::{CentralPanel, Color32, Context, Frame, Id, Sense, Ui, WidgetText};
|
||||
use egui_dock::{DockArea, NodeIndex, SurfaceIndex, TabViewer};
|
||||
use egui_wgpu::Callback;
|
||||
use nalgebra::Matrix4;
|
||||
use parking_lot::MappedRwLockWriteGuard;
|
||||
|
||||
use crate::{app::App, render::workspace::WorkspaceRenderCallback};
|
||||
|
||||
@@ -135,24 +137,40 @@ fn viewport(app: &mut App, ui: &mut Ui, _ctx: &Context) {
|
||||
};
|
||||
ui.painter().rect_filled(rect, 0.0, color);
|
||||
|
||||
let aspect = rect.width() / rect.height();
|
||||
let view_projection = app.camera.view_projection_matrix(aspect);
|
||||
|
||||
let callback = Callback::new_paint_callback(
|
||||
rect,
|
||||
WorkspaceRenderCallback {
|
||||
camera: app.camera.clone(),
|
||||
transform: app
|
||||
.camera
|
||||
.view_projection_matrix(rect.width() / rect.height()),
|
||||
|
||||
bed_size: app.slice_config.platform_size,
|
||||
grid_size: app.config.grid_size,
|
||||
|
||||
is_moving: response.dragged(),
|
||||
slice_operation: app.slice_operation.clone(),
|
||||
|
||||
models: app.meshes.clone(),
|
||||
config: app.config.clone(),
|
||||
line_support_debug: app.state.line_support_debug.clone(),
|
||||
},
|
||||
app.get_workspace_render_callback(view_projection, response.dragged()),
|
||||
);
|
||||
|
||||
ui.painter().add(callback);
|
||||
}
|
||||
|
||||
impl App {
|
||||
pub fn get_workspace_render_callback(
|
||||
&self,
|
||||
view_projection: Matrix4<f32>,
|
||||
is_moving: bool,
|
||||
) -> WorkspaceRenderCallback {
|
||||
WorkspaceRenderCallback {
|
||||
camera: self.camera.clone(),
|
||||
transform: view_projection,
|
||||
|
||||
bed_size: self.slice_config.platform_size,
|
||||
grid_size: self.config.grid_size,
|
||||
|
||||
is_moving,
|
||||
models: self.meshes.clone(),
|
||||
config: self.config.clone(),
|
||||
line_support_debug: self.state.line_support_debug.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_callback_resource_mut<T: 'static>(&self) -> MappedRwLockWriteGuard<T> {
|
||||
MappedRwLockWriteGuard::map(self.render_state.renderer.write(), |x| {
|
||||
x.callback_resources.get_mut::<T>().unwrap()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user