diff --git a/examples/camera.rs b/examples/camera.rs index b4cfcf5..9e9802a 100644 --- a/examples/camera.rs +++ b/examples/camera.rs @@ -26,7 +26,7 @@ async fn run() { window, ) .await; - test_xyz::add_xyz_line(&mut mini_gpu); + test_xyz::add_xyz_line(&mut mini_gpu, None); let mut camera_controller = MapController::default(); mini_gpu .renderer diff --git a/examples/objloader.rs b/examples/objloader.rs index ebba5d7..7bc234b 100644 --- a/examples/objloader.rs +++ b/examples/objloader.rs @@ -31,8 +31,8 @@ async fn run() { .await; make_test_mesh(&mut mini_gpu).await; let mut camera_controller = MapController::default(); - camera_controller.config.width = size.width as f32; - camera_controller.config.height = size.height as f32; + camera_controller.config.width = mini_gpu.renderer.viewport.width; + camera_controller.config.height = mini_gpu.renderer.viewport.height; mini_gpu .renderer diff --git a/examples/orthographic_camera.rs b/examples/orthographic_camera.rs index 2354078..5eb88b0 100644 --- a/examples/orthographic_camera.rs +++ b/examples/orthographic_camera.rs @@ -3,6 +3,7 @@ use ::mini_gpu::{ controller::map::MapController, material::MaterialTrait, materials::image::{Image, ImageConfig}, + orthographic_camera::OrthographicCamera, }, entity::Entity, mini_gpu::{self, MiniGPU}, @@ -33,11 +34,12 @@ async fn run() { window, ) .await; - make_test_mesh(&mut mini_gpu); utils::camera::default_orthographic_camera(&mut mini_gpu); - test_xyz::add_xyz_line(&mut mini_gpu); + make_test_mesh(&mut mini_gpu).await; + test_xyz::add_xyz_line(&mut mini_gpu, Some(10.)); let mut camera_controller = MapController::default(); - camera_controller.config.pan_speed = 0.01; + camera_controller.config.width = mini_gpu.renderer.viewport.width; + camera_controller.config.height = mini_gpu.renderer.viewport.height; mini_gpu .renderer @@ -68,6 +70,8 @@ async fn run() { physical_size.width as f32 / physical_size.height as f32, &mini_gpu.renderer, ); + camera_controller.config.width = mini_gpu.renderer.viewport.width; + camera_controller.config.height = mini_gpu.renderer.viewport.height; mini_gpu.renderer.window.request_redraw(); } WindowEvent::CloseRequested => target.exit(), @@ -84,32 +88,25 @@ async fn run() { .unwrap(); } -fn make_test_mesh(mini_gpu: &mut MiniGPU) { - let bytes = include_bytes!("./case.jpg"); - let image = image::load_from_memory(bytes).unwrap(); - let texture = Texture::from_image( - &mini_gpu.renderer.device, - &mini_gpu.renderer.queue, - &image, - Some("texture"), - ) - .unwrap(); - - let material = Image::new( - ImageConfig { - texture: Some(texture), - ..Default::default() - }, - &mini_gpu.renderer, - ); - println!("width: {}", image.width()); - println!("height: {}", image.height()); - let scale = image.width() as f32 / image.height() as f32; - let mesh = material.make_image_mesh(scale * 1., 1., vec![1.0, 0.0, 0.0], &mini_gpu.renderer); +async fn make_test_mesh(mini_gpu: &mut MiniGPU) { + let path = std::path::Path::new("examples/models/cube/cube.obj"); + let obj = utils::obj::load_obj(path, mini_gpu).await; + match obj { + Ok(size) => { + println!("Loaded obj with {} vertices", size); + } + Err(e) => { + println!("Failed to load obj ({:?})", e,); + } + } - let entity_id = mini_gpu.scene.add_entity(Entity::new()); - mini_gpu.scene.set_entity_component(entity_id, mesh, "mesh"); - mini_gpu - .scene - .set_entity_component::>(entity_id, Box::new(material), "material"); + let camera = mini_gpu.scene.get_default_camera().unwrap(); + let orthographic_camera = camera + .as_any() + .downcast_mut::() + .unwrap(); + orthographic_camera.config.width = 10.0; + orthographic_camera.config.aspect = mini_gpu.renderer.viewport.aspect; + orthographic_camera.config.position.z = 10.0; + camera.update_bind_group(&mini_gpu.renderer); } diff --git a/src/components/controller/map.rs b/src/components/controller/map.rs index 538e6e9..26cce0f 100644 --- a/src/components/controller/map.rs +++ b/src/components/controller/map.rs @@ -24,8 +24,8 @@ pub struct MapController { pub struct MapControllerConfig { pub rotate_speed: f32, pub pan_speed: f32, - pub width: f32, - pub height: f32, + pub width: f32, // window width + pub height: f32, //// window height } impl Default for MapControllerConfig { @@ -121,11 +121,20 @@ impl MapController { let dis = self.mouse_now_pos - self.before_pos; let camera_look_at = (camera.config.target - camera.config.position).normalize(); let camera_right = camera_look_at.cross(-camera.config.up).normalize(); - let camera_forward = camera_look_at.cross(camera_right).normalize(); - let camera_move = camera_right * dis.x * self.config.pan_speed - + camera_forward * dis.y * self.config.pan_speed; + let camera_up = camera.config.up.normalize(); + // 计算每个像素对应的世界坐标系中的距离 + let view_width = camera.config.width; + let view_height = camera.config.width / camera.config.aspect; + let pan_speed_x = view_width / self.config.width; + let pan_speed_y = view_height / self.config.height; + + let camera_move = (camera_right * dis.x * pan_speed_x + + camera_up * dis.y * pan_speed_y) + * self.config.pan_speed; + camera.config.position += camera_move; camera.config.target += camera_move; + self.before_pos = self.mouse_now_pos; } else if self.mouse_left_pressed { let dis = self.mouse_now_pos - self.before_pos; diff --git a/src/components/orthographic_camera.rs b/src/components/orthographic_camera.rs index a2e233d..1f9c077 100644 --- a/src/components/orthographic_camera.rs +++ b/src/components/orthographic_camera.rs @@ -21,10 +21,10 @@ pub struct OrthographicCameraConfig { impl Default for OrthographicCameraConfig { fn default() -> Self { Self { - width: 10.0, + width: 10.0, // ndc width aspect: 1.0, near: 0.1, - far: 100.0, + far: 1000.0, position: Vec3::new(0.0, 0.0, 10.0), target: Vec3::new(0.0, 0.0, 0.0), up: Vec3::new(0.0, 1.0, 0.0), diff --git a/src/components/viewport.rs b/src/components/viewport.rs index 8fb85a6..9b693ba 100644 --- a/src/components/viewport.rs +++ b/src/components/viewport.rs @@ -1,20 +1,18 @@ -use glam::Vec2; - pub struct Viewport { pub width: f32, pub height: f32, pub aspect: f32, - // per pixel representation of the screen - pub pixel_size: Vec2, } impl Viewport { - pub fn new(width: f32, height: f32) -> Viewport { + // todo: pass camera props to calculate pixel size + pub fn new(width: u32, height: u32) -> Viewport { + let width_f32 = width as f32; + let height_f32 = height as f32; Viewport { - width, - height, - aspect: width / height, - pixel_size: Vec2::new(1.0 / width, 1.0 / height), + width: width_f32, + height: height_f32, + aspect: width_f32 / height_f32, } } } diff --git a/src/renderer.rs b/src/renderer.rs index 7966236..36d8d13 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -2,7 +2,9 @@ use std::{collections::HashMap, sync::Arc}; use winit::window::Window; -use crate::{scene::Scene, system::system::System, utils::depth_texture}; +use crate::{ + components::viewport::Viewport, scene::Scene, system::system::System, utils::depth_texture, +}; pub struct Renderer { pub config: RendererConfig, @@ -15,6 +17,7 @@ pub struct Renderer { pub window: Arc, pub systems_map: HashMap>, pub depth_texture: depth_texture::DepthTexture, + pub viewport: Viewport, } pub struct RendererConfig { @@ -25,7 +28,7 @@ pub struct RendererConfig { impl Renderer { pub async fn new(config: RendererConfig, window: Arc) -> Renderer { let instance = wgpu::Instance::default(); - let surface = instance.create_surface(window.clone()).unwrap() ; + let surface = instance.create_surface(window.clone()).unwrap(); let adapter = instance .request_adapter(&wgpu::RequestAdapterOptions { power_preference: wgpu::PowerPreference::default(), @@ -66,6 +69,7 @@ impl Renderer { depth_texture::DepthTexture::new(&device, &surface_config, "depth_texture"); Renderer { window, + viewport: Viewport::new(config.width, config.height), config, surface_config, swapchain_format, @@ -79,6 +83,8 @@ impl Renderer { } pub fn resize(&mut self, width: u32, height: u32) { + self.viewport.width = width as f32; + self.viewport.height = height as f32; self.surface_config.width = width; self.surface_config.height = height; self.surface.configure(&self.device, &self.surface_config); diff --git a/src/utils/camera.rs b/src/utils/camera.rs index fa979da..10f7450 100644 --- a/src/utils/camera.rs +++ b/src/utils/camera.rs @@ -11,6 +11,8 @@ use crate::{ pub fn default_orthographic_camera(mini_gpu: &mut MiniGPU) { let mut camera = OrthographicCamera::new( OrthographicCameraConfig { + width: mini_gpu.config.width as f32, + aspect: mini_gpu.config.width as f32 / mini_gpu.config.height as f32, ..Default::default() }, &mini_gpu.renderer, diff --git a/src/utils/test_xyz.rs b/src/utils/test_xyz.rs index cbd4778..1672baf 100644 --- a/src/utils/test_xyz.rs +++ b/src/utils/test_xyz.rs @@ -1,6 +1,8 @@ use crate::{ components::{ - material::{Material, MaterialConfig, MaterialTrait}, materials::shader::ShaderParser, mesh::Mesh + material::{Material, MaterialConfig, MaterialTrait}, + materials::shader::ShaderParser, + mesh::Mesh, }, entity, mini_gpu::MiniGPU, @@ -28,19 +30,23 @@ fn fs_main(out:VertexOutput) -> @location(0) vec4f { } "#; -pub fn add_xyz_line(mini_gpu: &mut MiniGPU) { +pub fn add_xyz_line(mini_gpu: &mut MiniGPU, user_size: Option) { + let size = user_size.unwrap_or(0.5); let mesh = Mesh::new( - vec![0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.5], + vec![ + 0.0, 0.0, 0.0, size, 0.0, 0.0, 0.0, size, 0.0, 0.0, 0.0, size, + ], vec![0, 1, 0, 2, 0, 3], &mini_gpu.renderer, ); let mut shader_parser = ShaderParser::new(); - + let material_line = Material::new( MaterialConfig { shader: shader_parser - .parse_shader(TEST_XYZLINE_SHADER) - .to_string().to_string(), + .parse_shader(TEST_XYZLINE_SHADER) + .to_string() + .to_string(), topology: wgpu::PrimitiveTopology::LineList, uniforms: vec![0.], },