From 35e22924461d2ff7a3f139969c3e40b71fc4053b Mon Sep 17 00:00:00 2001 From: thatcomputerguy0101 Date: Thu, 24 Oct 2024 14:16:44 -0400 Subject: [PATCH 01/11] Add camera view example (mostly for debugging) --- Cargo.toml | 6 +- examples/camera_view/Cargo.toml | 18 ++ examples/camera_view/src/lib.rs | 19 ++ examples/camera_view/src/main.rs | 414 +++++++++++++++++++++++++++++++ 4 files changed, 456 insertions(+), 1 deletion(-) create mode 100644 examples/camera_view/Cargo.toml create mode 100644 examples/camera_view/src/lib.rs create mode 100644 examples/camera_view/src/main.rs diff --git a/Cargo.toml b/Cargo.toml index 20d7f9e90..fbaf31dba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -202,4 +202,8 @@ required-features = ["headless"] [[example]] name = "logo" -path = "examples/logo/src/main.rs" \ No newline at end of file +path = "examples/logo/src/main.rs" + +[[example]] +name = "camera_view" +path = "examples/camera_view/src/main.rs" diff --git a/examples/camera_view/Cargo.toml b/examples/camera_view/Cargo.toml new file mode 100644 index 000000000..e85fbf70a --- /dev/null +++ b/examples/camera_view/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "camera_view" +version = "0.1.0" +authors = ["Asger Nyman Christiansen ", "Alan Everett "] +edition = "2021" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +three-d = { path = "../../", features=["egui-gui"] } + +[target.'cfg(target_arch = "wasm32")'.dependencies] +log = "0.4" +wasm-bindgen = "0.2" +wasm-bindgen-futures = "0.4" +console_error_panic_hook = "0.1" +console_log = "1" diff --git a/examples/camera_view/src/lib.rs b/examples/camera_view/src/lib.rs new file mode 100644 index 000000000..ca78be894 --- /dev/null +++ b/examples/camera_view/src/lib.rs @@ -0,0 +1,19 @@ +#![allow(special_module_name)] +mod main; + +// Entry point for wasm +#[cfg(target_arch = "wasm32")] +use wasm_bindgen::prelude::*; + +#[cfg(target_arch = "wasm32")] +#[wasm_bindgen(start)] +pub fn start() -> Result<(), JsValue> { + console_log::init_with_level(log::Level::Debug).unwrap(); + + use log::info; + info!("Logging works!"); + + std::panic::set_hook(Box::new(console_error_panic_hook::hook)); + main::main(); + Ok(()) +} diff --git a/examples/camera_view/src/main.rs b/examples/camera_view/src/main.rs new file mode 100644 index 000000000..19b2e19fd --- /dev/null +++ b/examples/camera_view/src/main.rs @@ -0,0 +1,414 @@ +use cgmath::point3; +use three_d::*; +use three_d_asset::ProjectionType; + +pub fn main() { + let window = Window::new(WindowSettings { + title: "Camera View!".to_string(), + max_size: Some((1280, 720)), + ..Default::default() + }) + .unwrap(); + let context = window.gl(); + + let mut camera = Camera::new_perspective( + window.viewport(), + vec3(5.0, 2.0, 2.5), + vec3(0.0, 0.0, 0.0), + vec3(0.0, 1.0, 0.0), + degrees(45.0), + 0.1, + 100.0, + ); + let mut control = OrbitControl::new(vec3(0.0, 0.0, 0.0), 1.0, 1000.0); + + let mut debug_camera = Camera::new_orthographic( + window.viewport(), + vec3(10.0, 4.0, 5.0), + vec3(0.0, 0.0, 0.0), + vec3(0.0, 1.0, 0.0), + 24.0, + -1000.0, + 1000.0, + ); + + let mut sphere = Gm::new( + Mesh::new(&context, &CpuMesh::sphere(16)), + PhysicalMaterial::new_transparent( + &context, + &CpuMaterial { + albedo: Srgba { + r: 255, + g: 0, + b: 0, + a: 200, + }, + ..Default::default() + }, + ), + ); + sphere.set_transformation(Mat4::from_translation(vec3(0.0, 1.3, 0.0)) * Mat4::from_scale(0.2)); + let mut cylinder = Gm::new( + Mesh::new(&context, &CpuMesh::cylinder(16)), + PhysicalMaterial::new_transparent( + &context, + &CpuMaterial { + albedo: Srgba { + r: 0, + g: 255, + b: 0, + a: 200, + }, + ..Default::default() + }, + ), + ); + cylinder + .set_transformation(Mat4::from_translation(vec3(1.3, 0.0, 0.0)) * Mat4::from_scale(0.2)); + let mut cube = Gm::new( + Mesh::new(&context, &CpuMesh::cube()), + PhysicalMaterial::new_transparent( + &context, + &CpuMaterial { + albedo: Srgba { + r: 0, + g: 0, + b: 255, + a: 100, + }, + ..Default::default() + }, + ), + ); + cube.set_transformation(Mat4::from_translation(vec3(0.0, 0.0, 1.3)) * Mat4::from_scale(0.2)); + let axes = Axes::new(&context, 0.1, 2.0); + let bounding_box_sphere = Gm::new( + BoundingBox::new(&context, sphere.aabb()), + ColorMaterial { + color: Srgba::BLACK, + ..Default::default() + }, + ); + let bounding_box_cube = Gm::new( + BoundingBox::new(&context, cube.aabb()), + ColorMaterial { + color: Srgba::BLACK, + ..Default::default() + }, + ); + let bounding_box_cylinder = Gm::new( + BoundingBox::new(&context, cylinder.aabb()), + ColorMaterial { + color: Srgba::BLACK, + ..Default::default() + }, + ); + + let light0 = DirectionalLight::new(&context, 1.0, Srgba::WHITE, &vec3(0.0, -0.5, -0.5)); + let light1 = DirectionalLight::new(&context, 1.0, Srgba::WHITE, &vec3(0.0, 0.5, 0.5)); + + // Shapes to represent the main camera view through the debug camera + let mut marker_sphere = CpuMesh::sphere(16); + marker_sphere.transform(&Mat4::from_scale(0.15)).unwrap(); + let mut marker_arrow = CpuMesh::arrow(0.8, 0.6, 16); + marker_arrow + .transform(&Mat4::from_nonuniform_scale(1.0, 0.15, 0.15)) + .unwrap(); + + let mut position_marker = Gm::new( + Mesh::new(&context, &marker_sphere), + PhysicalMaterial::new_opaque( + &context, + &CpuMaterial { + albedo: Srgba::new_opaque(255, 255, 0), + ..Default::default() + }, + ), + ); + let mut target_marker = Gm::new( + Mesh::new(&context, &marker_sphere), + PhysicalMaterial::new_opaque( + &context, + &CpuMaterial { + albedo: Srgba::new_opaque(0, 255, 255), + ..Default::default() + }, + ), + ); + let mut up_marker = Gm::new( + Mesh::new(&context, &marker_arrow), + PhysicalMaterial::new_opaque( + &context, + &CpuMaterial { + albedo: Srgba::GREEN, + ..Default::default() + }, + ), + ); + + let mut marker_vertex = CpuMesh::sphere(16); + marker_vertex.transform(&Mat4::from_scale(0.05)).unwrap(); + let mut marker_edge = CpuMesh::cylinder(16); + marker_edge + .transform(&Mat4::from_nonuniform_scale(1.0, 0.05, 0.05)) + .unwrap(); + + let cube_points = [ + point3(-1.0, -1.0, -1.0), + point3(-1.0, -1.0, 1.0), + point3(-1.0, 1.0, 1.0), + point3(-1.0, 1.0, -1.0), + point3(1.0, 1.0, -1.0), + point3(1.0, 1.0, 1.0), + point3(1.0, -1.0, 1.0), + point3(1.0, -1.0, -1.0), + ]; + let xy_edges = [0, 3, 1, 2, 4, 7, 5, 6, 0, 7, 1, 6, 2, 5, 3, 4]; + let mut frustum_vertex_marker = Gm::new( + InstancedMesh::new(&context, &Instances::default(), &marker_vertex), + PhysicalMaterial::new_opaque( + &context, + &CpuMaterial { + albedo: Srgba::new_opaque(255, 0, 255), + ..Default::default() + }, + ), + ); + let mut frustum_edge_marker = Gm::new( + InstancedMesh::new(&context, &Instances::default(), &marker_edge), + PhysicalMaterial::new_opaque( + &context, + &CpuMaterial { + albedo: Srgba::new_opaque(255, 0, 255), + ..Default::default() + }, + ), + ); + + // Initial properties of the example + let mut camera_ratio = 0.5; + let mut height = 2.0; + let mut fov = if let ProjectionType::Perspective { field_of_view_y } = camera.projection_type() + { + (*field_of_view_y).into() + } else { + degrees(45.0f32) + }; + let mut near_plane = camera.z_near(); + let mut far_plane = camera.z_far(); + + let mut gui = three_d::GUI::new(&context); + window.render_loop(move |mut frame_input| { + // Gui panel to control the number of cubes and whether or not instancing is turned on. + let mut panel_width = 0.0; + let mut camera_changed = false; + gui.update( + &mut frame_input.events, + frame_input.accumulated_time, + frame_input.viewport, + frame_input.device_pixel_ratio, + |gui_context| { + use three_d::egui::*; + SidePanel::left("side_panel").show(gui_context, |ui| { + use three_d::egui::*; + ui.heading("Debug Panel"); + ComboBox::from_label("Camera mode") + .selected_text(match camera.projection_type() { + ProjectionType::Perspective { .. } => "Perspective", + ProjectionType::Orthographic { .. } => "Orthographic", + }) + .show_ui(ui, |ui| { + if ui + .selectable_label( + matches!( + camera.projection_type(), + ProjectionType::Orthographic { .. } + ), + "Orthographic", + ) + .clicked() + { + camera.set_orthographic_projection(height, near_plane, far_plane); + }; + if ui + .selectable_label( + matches!( + camera.projection_type(), + ProjectionType::Perspective { .. } + ), + "Perspective", + ) + .clicked() + { + camera.set_perspective_projection(fov, near_plane, far_plane) + } + }); + camera_changed |= ui + .add(match camera.projection_type() { + ProjectionType::Orthographic { .. } => { + Slider::new(&mut height, 0.0..=120.0).text("Height") + } + _ => Slider::new(&mut fov.0, -120.0..=120.0) + .text("FOV") + .suffix("°"), + }) + .changed(); + camera_changed |= ui + .add(Slider::new(&mut near_plane, -100.0..=100.0).text("Near plane")) + .changed(); + if near_plane >= far_plane { + near_plane = far_plane - 0.1; + } + camera_changed |= ui + .add(Slider::new(&mut far_plane, -100.0..=100.0).text("Far plane")) + .changed(); + if near_plane >= far_plane { + far_plane = near_plane + 0.1; + } + + if camera_changed { + match camera.projection_type() { + ProjectionType::Orthographic { .. } => { + camera.set_orthographic_projection(height, near_plane, far_plane) + } + ProjectionType::Perspective { .. } => { + if near_plane < 0.0 { + near_plane = 0.1; + if far_plane < near_plane { + far_plane = near_plane + 0.1; + } + } + if fov <= degrees(0.0) { + fov = degrees(1.0); + } + camera.set_perspective_projection(fov, near_plane, far_plane) + } + } + } + + ui.add(Label::new( + "Left camera can be changed by the above inputs; right \ + camera shows a debug visual for the left camera. In the \ + debug visual, the yellow sphere is the camera position, \ + the cyan sphere is the camera target, the green arrow \ + is the camera up direction, and the magenta lines \ + outline the camera's view frustum.", + )); + + ui.add( + Slider::new(&mut camera_ratio, 0.01..=0.99) + .text("Main camera to debug camera screen ratio"), + ); + }); + panel_width = gui_context.used_rect().width(); + }, + ); + + let viewport = Viewport { + x: (panel_width * frame_input.device_pixel_ratio) as i32, + y: 0, + width: ((frame_input.viewport.width + - (panel_width * frame_input.device_pixel_ratio) as u32) as f32 + * camera_ratio) as u32, + height: frame_input.viewport.height, + }; + camera.set_viewport(viewport); + + let meta_viewport = Viewport { + x: (panel_width * frame_input.device_pixel_ratio) as i32 + + ((frame_input.viewport.width + - (panel_width * frame_input.device_pixel_ratio) as u32) + as f32 + * camera_ratio) as i32, + y: 0, + width: ((frame_input.viewport.width + - (panel_width * frame_input.device_pixel_ratio) as u32) as f32 + * (1.0 - camera_ratio)) as u32, + height: frame_input.viewport.height, + }; + debug_camera.set_viewport(meta_viewport); + + // Camera control must be after the gui update. + control.handle_events(&mut camera, &mut frame_input.events); + + // Update camera debug shapes + position_marker.set_transformation(Mat4::from_translation(*camera.position())); + target_marker.set_transformation(Mat4::from_translation(*camera.target())); + up_marker.set_transformation( + Mat4::from_translation(*camera.position()) + * Mat4::from_axis_angle( + Vec3::unit_x().cross(*camera.up()), + Vec3::unit_x().angle(*camera.up()), + ), + ); + + let frustum_vertices = cube_points.map(|point| { + (camera.projection() * camera.view()) + .inverse_transform() + .unwrap() + .transform_point(point) + }); + frustum_vertex_marker.set_instances(&Instances { + transformations: frustum_vertices + .into_iter() + .map(|vertex| Mat4::from_translation(vertex.to_vec())) + .collect(), + ..Default::default() + }); + + let frustum_edge_vertices: Vec<_> = frustum_vertices + .iter() + .chain(xy_edges.map(|index| &frustum_vertices[index])) + .collect(); + let frustum_edges = frustum_edge_vertices.chunks_exact(2); + frustum_edge_marker.set_instances(&Instances { + transformations: frustum_edges + .map(|points| { + Mat4::from_translation(points[0].to_vec()) + * Mat4::from_axis_angle( + Vec3::unit_x().cross(points[1] - points[0]).normalize(), + Vec3::unit_x().angle(points[1] - points[0]), + ) + * Mat4::from_nonuniform_scale(points[1].distance(*points[0]), 1.0, 1.0) + }) + .collect(), + ..Default::default() + }); + + let screen = frame_input.screen(); + screen.clear(ClearState::color_and_depth(0.8, 0.8, 0.8, 1.0, 1.0)); + screen.render( + &camera, + sphere + .into_iter() + .chain(&cylinder) + .chain(&cube) + .chain(&axes) + .chain(&bounding_box_sphere) + .chain(&bounding_box_cube) + .chain(&bounding_box_cylinder), + &[&light0, &light1], + ); + screen.render( + &debug_camera, + sphere + .into_iter() + .chain(&cylinder) + .chain(&cube) + .chain(&axes) + .chain(&bounding_box_sphere) + .chain(&bounding_box_cube) + .chain(&bounding_box_cylinder) + .chain(&position_marker) + .chain(&target_marker) + .chain(&up_marker) + .chain(&frustum_vertex_marker) + .chain(&frustum_edge_marker), + &[&light0, &light1], + ); + + screen.write(|| gui.render()).unwrap(); + + FrameOutput::default() + }); +} From 4a25562b86dc1696560012ec773e8500ebb6d7e6 Mon Sep 17 00:00:00 2001 From: thatcomputerguy0101 Date: Thu, 24 Oct 2024 15:09:51 -0400 Subject: [PATCH 02/11] Add missing example dependencies --- examples/camera_view/Cargo.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/camera_view/Cargo.toml b/examples/camera_view/Cargo.toml index e85fbf70a..4892f379c 100644 --- a/examples/camera_view/Cargo.toml +++ b/examples/camera_view/Cargo.toml @@ -9,6 +9,8 @@ crate-type = ["cdylib"] [dependencies] three-d = { path = "../../", features=["egui-gui"] } +three-d-asset = {version = "0.7"} +cgmath = "0.18" [target.'cfg(target_arch = "wasm32")'.dependencies] log = "0.4" From 67782f6705c204eab660181ed72873ddc81604a9 Mon Sep 17 00:00:00 2001 From: thatcomputerguy0101 Date: Sat, 26 Oct 2024 00:29:34 -0400 Subject: [PATCH 03/11] Add camera position/view_direction to camera_view example --- examples/camera_view/src/main.rs | 73 +++++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/examples/camera_view/src/main.rs b/examples/camera_view/src/main.rs index 19b2e19fd..b56a5892a 100644 --- a/examples/camera_view/src/main.rs +++ b/examples/camera_view/src/main.rs @@ -146,6 +146,27 @@ pub fn main() { ), ); + let mut view_position_marker = Gm::new( + Mesh::new(&context, &marker_sphere), + PhysicalMaterial::new_opaque( + &context, + &CpuMaterial { + albedo: Srgba::new_opaque(255, 127, 0), + ..Default::default() + }, + ), + ); + let mut view_direction_marker = Gm::new( + Mesh::new(&context, &marker_arrow), + PhysicalMaterial::new_opaque( + &context, + &CpuMaterial { + albedo: Srgba::BLUE, + ..Default::default() + }, + ), + ); + let mut marker_vertex = CpuMesh::sphere(16); marker_vertex.transform(&Mat4::from_scale(0.05)).unwrap(); let mut marker_edge = CpuMesh::cylinder(16); @@ -196,6 +217,7 @@ pub fn main() { }; let mut near_plane = camera.z_near(); let mut far_plane = camera.z_far(); + let mut show_click_info = false; let mut gui = three_d::GUI::new(&context); window.render_loop(move |mut frame_input| { @@ -295,6 +317,17 @@ pub fn main() { outline the camera's view frustum.", )); + ui.add(Checkbox::new( + &mut show_click_info, + "Enable position/view_direction debug visuals", + )); + + ui.add(Label::new( + "When enabled, clicking shows the camera base position \ + as an orange sphere and the view direction as a blue \ + arrow.", + )); + ui.add( Slider::new(&mut camera_ratio, 0.01..=0.99) .text("Main camera to debug camera screen ratio"), @@ -375,6 +408,32 @@ pub fn main() { ..Default::default() }); + if show_click_info { + for event in &frame_input.events { + if let Event::MousePress { + button: MouseButton::Left, + handled: false, + position, + .. + } = event + { + view_position_marker.set_transformation(Mat4::from_translation( + camera.position_at_pixel(*position), + )); + let view_direction = camera.view_direction_at_pixel(*position); + view_direction_marker.set_transformation( + Mat4::from_translation(camera.position_at_pixel(*position)) + * Mat4::from_axis_angle( + Vec3::unit_x().cross(view_direction), + Vec3::unit_x().angle(view_direction), + ), + ); + + break; + } + } + } + let screen = frame_input.screen(); screen.clear(ClearState::color_and_depth(0.8, 0.8, 0.8, 1.0, 1.0)); screen.render( @@ -403,7 +462,19 @@ pub fn main() { .chain(&target_marker) .chain(&up_marker) .chain(&frustum_vertex_marker) - .chain(&frustum_edge_marker), + .chain(&frustum_edge_marker) + .chain( + show_click_info + .then_some(&view_position_marker) + .into_iter() + .flatten(), + ) + .chain( + show_click_info + .then_some(&view_direction_marker) + .into_iter() + .flatten(), + ), &[&light0, &light1], ); From b53e5ebd4cd0183deb7db16b1ae7c78854c3f8a6 Mon Sep 17 00:00:00 2001 From: thatcomputerguy0101 Date: Sat, 26 Oct 2024 14:45:27 -0400 Subject: [PATCH 04/11] Simplify reorienting camera markers --- examples/camera_view/src/main.rs | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/examples/camera_view/src/main.rs b/examples/camera_view/src/main.rs index b56a5892a..35e961475 100644 --- a/examples/camera_view/src/main.rs +++ b/examples/camera_view/src/main.rs @@ -369,10 +369,7 @@ pub fn main() { target_marker.set_transformation(Mat4::from_translation(*camera.target())); up_marker.set_transformation( Mat4::from_translation(*camera.position()) - * Mat4::from_axis_angle( - Vec3::unit_x().cross(*camera.up()), - Vec3::unit_x().angle(*camera.up()), - ), + * rotation_matrix_from_dir_to_dir(Vec3::unit_x(), *camera.up()), ); let frustum_vertices = cube_points.map(|point| { @@ -398,10 +395,7 @@ pub fn main() { transformations: frustum_edges .map(|points| { Mat4::from_translation(points[0].to_vec()) - * Mat4::from_axis_angle( - Vec3::unit_x().cross(points[1] - points[0]).normalize(), - Vec3::unit_x().angle(points[1] - points[0]), - ) + * rotation_matrix_from_dir_to_dir(Vec3::unit_x(), points[1] - points[0]) * Mat4::from_nonuniform_scale(points[1].distance(*points[0]), 1.0, 1.0) }) .collect(), @@ -420,12 +414,11 @@ pub fn main() { view_position_marker.set_transformation(Mat4::from_translation( camera.position_at_pixel(*position), )); - let view_direction = camera.view_direction_at_pixel(*position); view_direction_marker.set_transformation( Mat4::from_translation(camera.position_at_pixel(*position)) - * Mat4::from_axis_angle( - Vec3::unit_x().cross(view_direction), - Vec3::unit_x().angle(view_direction), + * rotation_matrix_from_dir_to_dir( + Vec3::unit_x(), + camera.view_direction_at_pixel(*position), ), ); From 7dcd95db466f0bab668d53be47f686c962d52997 Mon Sep 17 00:00:00 2001 From: thatcomputerguy0101 Date: Mon, 28 Oct 2024 13:08:16 -0400 Subject: [PATCH 05/11] Shorten splitscreen slider message --- examples/camera_view/src/main.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/examples/camera_view/src/main.rs b/examples/camera_view/src/main.rs index 35e961475..eff9818c2 100644 --- a/examples/camera_view/src/main.rs +++ b/examples/camera_view/src/main.rs @@ -328,10 +328,7 @@ pub fn main() { arrow.", )); - ui.add( - Slider::new(&mut camera_ratio, 0.01..=0.99) - .text("Main camera to debug camera screen ratio"), - ); + ui.add(Slider::new(&mut camera_ratio, 0.01..=0.99).text("Splitscreen ratio")); }); panel_width = gui_context.used_rect().width(); }, From 2f5ff15827fce6009027121349f1a097778bd13e Mon Sep 17 00:00:00 2001 From: thatcomputerguy0101 Date: Thu, 21 Nov 2024 12:57:47 -0500 Subject: [PATCH 06/11] Fix reference typing for vectors and matrices in view example --- examples/camera_view/src/main.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/camera_view/src/main.rs b/examples/camera_view/src/main.rs index eff9818c2..69bdaba69 100644 --- a/examples/camera_view/src/main.rs +++ b/examples/camera_view/src/main.rs @@ -104,15 +104,15 @@ pub fn main() { }, ); - let light0 = DirectionalLight::new(&context, 1.0, Srgba::WHITE, &vec3(0.0, -0.5, -0.5)); - let light1 = DirectionalLight::new(&context, 1.0, Srgba::WHITE, &vec3(0.0, 0.5, 0.5)); + let light0 = DirectionalLight::new(&context, 1.0, Srgba::WHITE, vec3(0.0, -0.5, -0.5)); + let light1 = DirectionalLight::new(&context, 1.0, Srgba::WHITE, vec3(0.0, 0.5, 0.5)); // Shapes to represent the main camera view through the debug camera let mut marker_sphere = CpuMesh::sphere(16); - marker_sphere.transform(&Mat4::from_scale(0.15)).unwrap(); + marker_sphere.transform(Mat4::from_scale(0.15)).unwrap(); let mut marker_arrow = CpuMesh::arrow(0.8, 0.6, 16); marker_arrow - .transform(&Mat4::from_nonuniform_scale(1.0, 0.15, 0.15)) + .transform(Mat4::from_nonuniform_scale(1.0, 0.15, 0.15)) .unwrap(); let mut position_marker = Gm::new( @@ -168,10 +168,10 @@ pub fn main() { ); let mut marker_vertex = CpuMesh::sphere(16); - marker_vertex.transform(&Mat4::from_scale(0.05)).unwrap(); + marker_vertex.transform(Mat4::from_scale(0.05)).unwrap(); let mut marker_edge = CpuMesh::cylinder(16); marker_edge - .transform(&Mat4::from_nonuniform_scale(1.0, 0.05, 0.05)) + .transform(Mat4::from_nonuniform_scale(1.0, 0.05, 0.05)) .unwrap(); let cube_points = [ @@ -362,11 +362,11 @@ pub fn main() { control.handle_events(&mut camera, &mut frame_input.events); // Update camera debug shapes - position_marker.set_transformation(Mat4::from_translation(*camera.position())); - target_marker.set_transformation(Mat4::from_translation(*camera.target())); + position_marker.set_transformation(Mat4::from_translation(camera.position())); + target_marker.set_transformation(Mat4::from_translation(camera.target())); up_marker.set_transformation( - Mat4::from_translation(*camera.position()) - * rotation_matrix_from_dir_to_dir(Vec3::unit_x(), *camera.up()), + Mat4::from_translation(camera.position()) + * rotation_matrix_from_dir_to_dir(Vec3::unit_x(), camera.up()), ); let frustum_vertices = cube_points.map(|point| { From e2049f2b37b75952e1059d9c326539a8031c5d10 Mon Sep 17 00:00:00 2001 From: thatcomputerguy0101 Date: Mon, 28 Oct 2024 13:11:47 -0400 Subject: [PATCH 07/11] Add planar camera to camera_view example --- examples/camera_view/src/main.rs | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/examples/camera_view/src/main.rs b/examples/camera_view/src/main.rs index 69bdaba69..e107def06 100644 --- a/examples/camera_view/src/main.rs +++ b/examples/camera_view/src/main.rs @@ -20,14 +20,14 @@ pub fn main() { 0.1, 100.0, ); - let mut control = OrbitControl::new(vec3(0.0, 0.0, 0.0), 1.0, 1000.0); + let mut control = OrbitControl::new(vec3(0.0, 0.0, 0.0), 0.2, 1000.0); let mut debug_camera = Camera::new_orthographic( window.viewport(), vec3(10.0, 4.0, 5.0), vec3(0.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), - 24.0, + 2.0, -1000.0, 1000.0, ); @@ -238,6 +238,7 @@ pub fn main() { .selected_text(match camera.projection_type() { ProjectionType::Perspective { .. } => "Perspective", ProjectionType::Orthographic { .. } => "Orthographic", + ProjectionType::Planar { .. } => "Planar", }) .show_ui(ui, |ui| { if ui @@ -264,6 +265,18 @@ pub fn main() { { camera.set_perspective_projection(fov, near_plane, far_plane) } + if ui + .selectable_label( + matches!( + camera.projection_type(), + ProjectionType::Planar { .. } + ), + "Planar", + ) + .clicked() + { + camera.set_planar_projection(fov, near_plane, far_plane) + } }); camera_changed |= ui .add(match camera.projection_type() { @@ -305,6 +318,21 @@ pub fn main() { } camera.set_perspective_projection(fov, near_plane, far_plane) } + ProjectionType::Planar { .. } => { + let focal_point = -Angle::cot(fov / 2.0); + if focal_point < 0.0 && near_plane <= focal_point { + near_plane = focal_point + 0.001; + if near_plane > far_plane { + far_plane = near_plane + 0.1; + } + } else if focal_point > 0.0 && far_plane >= focal_point { + far_plane = focal_point - 0.001; + if near_plane > far_plane { + near_plane = far_plane - 0.1; + } + } + camera.set_planar_projection(fov, near_plane, far_plane) + } } } From 4af671ec92a900ef17212b5856b1cb99ca169b76 Mon Sep 17 00:00:00 2001 From: thatcomputerguy0101 Date: Thu, 21 Nov 2024 13:00:06 -0500 Subject: [PATCH 08/11] Remove extra shapes from camera view example --- examples/camera_view/src/main.rs | 92 +------------------------------- 1 file changed, 2 insertions(+), 90 deletions(-) diff --git a/examples/camera_view/src/main.rs b/examples/camera_view/src/main.rs index e107def06..d88e8cc94 100644 --- a/examples/camera_view/src/main.rs +++ b/examples/camera_view/src/main.rs @@ -32,77 +32,7 @@ pub fn main() { 1000.0, ); - let mut sphere = Gm::new( - Mesh::new(&context, &CpuMesh::sphere(16)), - PhysicalMaterial::new_transparent( - &context, - &CpuMaterial { - albedo: Srgba { - r: 255, - g: 0, - b: 0, - a: 200, - }, - ..Default::default() - }, - ), - ); - sphere.set_transformation(Mat4::from_translation(vec3(0.0, 1.3, 0.0)) * Mat4::from_scale(0.2)); - let mut cylinder = Gm::new( - Mesh::new(&context, &CpuMesh::cylinder(16)), - PhysicalMaterial::new_transparent( - &context, - &CpuMaterial { - albedo: Srgba { - r: 0, - g: 255, - b: 0, - a: 200, - }, - ..Default::default() - }, - ), - ); - cylinder - .set_transformation(Mat4::from_translation(vec3(1.3, 0.0, 0.0)) * Mat4::from_scale(0.2)); - let mut cube = Gm::new( - Mesh::new(&context, &CpuMesh::cube()), - PhysicalMaterial::new_transparent( - &context, - &CpuMaterial { - albedo: Srgba { - r: 0, - g: 0, - b: 255, - a: 100, - }, - ..Default::default() - }, - ), - ); - cube.set_transformation(Mat4::from_translation(vec3(0.0, 0.0, 1.3)) * Mat4::from_scale(0.2)); let axes = Axes::new(&context, 0.1, 2.0); - let bounding_box_sphere = Gm::new( - BoundingBox::new(&context, sphere.aabb()), - ColorMaterial { - color: Srgba::BLACK, - ..Default::default() - }, - ); - let bounding_box_cube = Gm::new( - BoundingBox::new(&context, cube.aabb()), - ColorMaterial { - color: Srgba::BLACK, - ..Default::default() - }, - ); - let bounding_box_cylinder = Gm::new( - BoundingBox::new(&context, cylinder.aabb()), - ColorMaterial { - color: Srgba::BLACK, - ..Default::default() - }, - ); let light0 = DirectionalLight::new(&context, 1.0, Srgba::WHITE, vec3(0.0, -0.5, -0.5)); let light1 = DirectionalLight::new(&context, 1.0, Srgba::WHITE, vec3(0.0, 0.5, 0.5)); @@ -454,28 +384,10 @@ pub fn main() { let screen = frame_input.screen(); screen.clear(ClearState::color_and_depth(0.8, 0.8, 0.8, 1.0, 1.0)); - screen.render( - &camera, - sphere - .into_iter() - .chain(&cylinder) - .chain(&cube) - .chain(&axes) - .chain(&bounding_box_sphere) - .chain(&bounding_box_cube) - .chain(&bounding_box_cylinder), - &[&light0, &light1], - ); + screen.render(&camera, axes.into_iter(), &[&light0, &light1]); screen.render( &debug_camera, - sphere - .into_iter() - .chain(&cylinder) - .chain(&cube) - .chain(&axes) - .chain(&bounding_box_sphere) - .chain(&bounding_box_cube) - .chain(&bounding_box_cylinder) + axes.into_iter() .chain(&position_marker) .chain(&target_marker) .chain(&up_marker) From 4c921affa535e984ff8a4135122179e9532ef9e2 Mon Sep 17 00:00:00 2001 From: thatcomputerguy0101 Date: Thu, 21 Nov 2024 13:02:17 -0500 Subject: [PATCH 09/11] Clean up camera view example --- examples/camera_view/src/main.rs | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/examples/camera_view/src/main.rs b/examples/camera_view/src/main.rs index d88e8cc94..a02ac8ebd 100644 --- a/examples/camera_view/src/main.rs +++ b/examples/camera_view/src/main.rs @@ -37,7 +37,7 @@ pub fn main() { let light0 = DirectionalLight::new(&context, 1.0, Srgba::WHITE, vec3(0.0, -0.5, -0.5)); let light1 = DirectionalLight::new(&context, 1.0, Srgba::WHITE, vec3(0.0, 0.5, 0.5)); - // Shapes to represent the main camera view through the debug camera + // Shapes to represent the main camera view input through the debug camera let mut marker_sphere = CpuMesh::sphere(16); marker_sphere.transform(Mat4::from_scale(0.15)).unwrap(); let mut marker_arrow = CpuMesh::arrow(0.8, 0.6, 16); @@ -97,6 +97,7 @@ pub fn main() { ), ); + // Shapes to view the main camera view frustum (projection output) through the debug camera let mut marker_vertex = CpuMesh::sphere(16); marker_vertex.transform(Mat4::from_scale(0.05)).unwrap(); let mut marker_edge = CpuMesh::cylinder(16); @@ -151,7 +152,7 @@ pub fn main() { let mut gui = three_d::GUI::new(&context); window.render_loop(move |mut frame_input| { - // Gui panel to control the number of cubes and whether or not instancing is turned on. + // Gui panel to control the projection used for the main camera and enable picking debug features let mut panel_width = 0.0; let mut camera_changed = false; gui.update( @@ -302,7 +303,7 @@ pub fn main() { }; camera.set_viewport(viewport); - let meta_viewport = Viewport { + let debug_viewport = Viewport { x: (panel_width * frame_input.device_pixel_ratio) as i32 + ((frame_input.viewport.width - (panel_width * frame_input.device_pixel_ratio) as u32) @@ -314,7 +315,7 @@ pub fn main() { * (1.0 - camera_ratio)) as u32, height: frame_input.viewport.height, }; - debug_camera.set_viewport(meta_viewport); + debug_camera.set_viewport(debug_viewport); // Camera control must be after the gui update. control.handle_events(&mut camera, &mut frame_input.events); @@ -394,14 +395,12 @@ pub fn main() { .chain(&frustum_vertex_marker) .chain(&frustum_edge_marker) .chain( - show_click_info - .then_some(&view_position_marker) - .into_iter() - .flatten(), - ) - .chain( - show_click_info - .then_some(&view_direction_marker) + show_click_info // only include the view position/direction markers if enabled + .then_some( + view_position_marker + .into_iter() + .chain(&view_direction_marker), + ) .into_iter() .flatten(), ), From e0781838a31b1c6fb654950aafadb35df8fdbd76 Mon Sep 17 00:00:00 2001 From: thatcomputerguy0101 Date: Thu, 21 Nov 2024 13:12:58 -0500 Subject: [PATCH 10/11] Bump three-d-asset version used by view example --- examples/camera_view/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/camera_view/Cargo.toml b/examples/camera_view/Cargo.toml index 4892f379c..19f1e6770 100644 --- a/examples/camera_view/Cargo.toml +++ b/examples/camera_view/Cargo.toml @@ -9,7 +9,7 @@ crate-type = ["cdylib"] [dependencies] three-d = { path = "../../", features=["egui-gui"] } -three-d-asset = {version = "0.7"} +three-d-asset = {version = "0.8"} cgmath = "0.18" [target.'cfg(target_arch = "wasm32")'.dependencies] From 778044256f7138d1c56562442257c301026dd280 Mon Sep 17 00:00:00 2001 From: thatcomputerguy0101 Date: Thu, 28 Nov 2024 12:36:49 -0500 Subject: [PATCH 11/11] Remove invalid near/far plane limits on planar camera --- examples/camera_view/src/main.rs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/examples/camera_view/src/main.rs b/examples/camera_view/src/main.rs index a02ac8ebd..03a1bf42a 100644 --- a/examples/camera_view/src/main.rs +++ b/examples/camera_view/src/main.rs @@ -250,18 +250,6 @@ pub fn main() { camera.set_perspective_projection(fov, near_plane, far_plane) } ProjectionType::Planar { .. } => { - let focal_point = -Angle::cot(fov / 2.0); - if focal_point < 0.0 && near_plane <= focal_point { - near_plane = focal_point + 0.001; - if near_plane > far_plane { - far_plane = near_plane + 0.1; - } - } else if focal_point > 0.0 && far_plane >= focal_point { - far_plane = focal_point - 0.001; - if near_plane > far_plane { - near_plane = far_plane - 0.1; - } - } camera.set_planar_projection(fov, near_plane, far_plane) } }