From 10a41fcfcebb86dd78f36b9bdf44e02ac3347355 Mon Sep 17 00:00:00 2001 From: Hartmut Seichter Date: Sun, 11 Dec 2022 12:41:34 +0100 Subject: [PATCH] initial implementation for the off-axis view frustum based on previous code --- Cargo.toml | 4 ++ src/projection.rs | 55 ++++++++++++++++++++++++ src/screeninfo.rs | 104 ++++++++++++++++++++-------------------------- src/viewer.rs | 31 ++++++-------- 4 files changed, 118 insertions(+), 76 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 92bd5c6..f3fb560 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,3 +10,7 @@ edition = "2021" bevy = { version = "0.9.1", features = ["dynamic"] } rand = "0.8.4" # vrpn = "0.1.0" # not compatible with 2021 + + +[profile.release] +opt-level = 3 \ No newline at end of file diff --git a/src/projection.rs b/src/projection.rs index 3790373..4923bcc 100644 --- a/src/projection.rs +++ b/src/projection.rs @@ -57,6 +57,61 @@ pub fn make_projection_rh_custom(fov_y: f32, aspect_ratio: f32, z_near: f32, z_f } +fn create_offaxis_matrices( + screen_lower_left: Vec3, + screen_lower_right: Vec3, + screen_upper_left: Vec3, + pos_eye: Vec3, + z_far: f32 + ) -> (Mat4,Mat4) +{ + + // + let vec_right = screen_lower_right - screen_lower_left; // vr + let vec_up = screen_upper_left - screen_lower_left; // vu + + let frustum_left = screen_lower_left - pos_eye; // va + let frustum_right = screen_lower_right - pos_eye; // vb + let frustum_up = screen_upper_left - pos_eye; // vc + + let vec_right_normalized = vec_right.normalize(); + let vec_up_normalized = vec_up.normalize(); + + let vec_normal = vec_right_normalized.cross(vec_up_normalized).normalize(); + + let dist = -vec_right.dot(vec_normal); + + let z_near = 0.001_f32.max(dist - 0.01); + + let left = vec_right.dot(frustum_left) * z_near / dist; + let right = vec_right.dot(frustum_right) * z_near / dist; + let bottom = vec_up.dot(frustum_left) * z_near / dist; + let top = vec_up.dot(frustum_up) * z_near / dist; + + + let projection_matrix = make_projection_rh_from_frustum_reversed(left,right,bottom,top,z_near,z_far); + + let view_matrix_rotation = Mat4::from_cols( + Vec4::new(vec_right.x, vec_up.x, vec_normal.x ,0.0), + Vec4::new(vec_right.y, vec_up.y, vec_normal.y ,0.0), + Vec4::new(vec_right.z, vec_up.z, vec_normal.z ,0.0), + Vec4::W + ); + + let view_matrix_eye = Mat4::from_cols( + Vec4::X, + Vec4::Y, + Vec4::Z, + (-pos_eye).extend(1.0) + ); + + let view_matrix = view_matrix_rotation * view_matrix_eye; + + (view_matrix,projection_matrix) +} + + + #[cfg(test)] mod tests { use bevy::prelude::Mat4; diff --git a/src/screeninfo.rs b/src/screeninfo.rs index 704de24..64fa812 100644 --- a/src/screeninfo.rs +++ b/src/screeninfo.rs @@ -1,99 +1,87 @@ - -use bevy::{prelude::*, math::bool, prelude::shape::Quad }; -use rand::prelude::*; use bevy::render::primitives::Plane; +use bevy::{math::bool, prelude::shape::Quad, prelude::*}; +use rand::prelude::*; enum EyePos { Left, - Right + Right, } - -#[derive(Default,Component)] +#[derive(Default, Component)] pub struct ScreenInfo { - pub name : String, // main (to identify the screen) - width : f32, // 3.08 (full width in m) - height : f32, // 2.33 (full height in m) - - center : Vec3, // 0.0 -1.15 -3.08 (mid point of screen in global coordinated - tracking!) - normal : Vec3, // 0.0 0.0 1.0 (orientation of front side) - up: Vec3, // 0.0 1.0 0.0 (vertical axis) - horizontal: Vec3, // right vector computed as orthonormal - - top : Vec3, - bottom : Vec3, - left : Vec3, - right : Vec3 + pub name: String, // main (to identify the screen) + width: f32, // 3.08 (full width in m) + height: f32, // 2.33 (full height in m) + + center: Vec3, // 0.0 -1.15 -3.08 (mid point of screen in global coordinated - tracking!) + normal: Vec3, // 0.0 0.0 1.0 (orientation of front side) + up: Vec3, // 0.0 1.0 0.0 (vertical axis) + horizontal: Vec3, // right vector computed as orthonormal + } impl ScreenInfo { - pub fn new(name: &str) -> Self { Self { name: name.to_string(), width: 3.08, height: 2.33, - center: Vec3 { x: 0.0, y: -1.15, z: -3.08 }, + center: Vec3 { + x: 0.0, + y: -1.15, + z: -3.08, + }, normal: Vec3::Z, up: Vec3::Y, - horizontal: Vec3::ZERO, - top: Vec3::ZERO, - bottom: Vec3::ZERO, - left: Vec3::ZERO, - right: Vec3::ZERO, + horizontal: Vec3::ZERO, } } - pub fn build_debug_geometry(&self, + pub fn build_debug_geometry( + &self, mut commands: Commands, mut meshes: ResMut>, mut materials: ResMut>, - ) - { - // plane + ) { + // plane commands.spawn(PbrBundle { - mesh: meshes.add(Mesh::from( Quad { size: Vec2 { x: self.width, y: self.height }, flip:false })), - material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()), - ..default() + mesh: meshes.add(Mesh::from(Quad { + size: Vec2 { + x: self.width, + y: self.height, + }, + flip: false, + })), + material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()), + ..default() }); } - pub fn update(&mut self) -> &mut Self { - - // compute right as up ^ forward - self.horizontal = self.up.cross(self.normal); + // pub fn update(&mut self) -> &mut Self { + // // compute right as up ^ forward + // self.horizontal = self.up.cross(self.normal); - // points of screen - self.top = self.center + self.up * (self.height * 0.5); - self.bottom = self.center - self.up * (self.height * 0.5); - self.left = self.center - self.horizontal * (self.height * 0.5); - self.right = self.center + self.horizontal * (self.height * 0.5); + // // points of screen + // self.top = self.center + self.up * (self.height * 0.5); + // self.bottom = self.center - self.up * (self.height * 0.5); + // self.left = self.center - self.horizontal * (self.height * 0.5); + // self.right = self.center + self.horizontal * (self.height * 0.5); - self - - } - - fn intersection( - &self, - p1: Vec3, - p2: Vec3) -> (bool,Vec3) - { + // self + // } + fn intersection(&self, p1: Vec3, p2: Vec3) -> (bool, Vec3) { let u = self.normal.dot(self.center - p1) / self.normal.dot(p2 - p1); let intersection_point = p1 + ((p2 - p1) * u); // returns a tuple if the intersection point is in front and the actual point - (u >= 0.0 && u <= 1.0,intersection_point) + (u >= 0.0 && u <= 1.0, intersection_point) } - - fn normal_intersection(&self, - p1: Vec3) -> (bool,Vec3) - { + fn normal_intersection(&self, p1: Vec3) -> (bool, Vec3) { let p2 = p1 - self.normal * 10.0; - + self.intersection(p1, p2) } - } diff --git a/src/viewer.rs b/src/viewer.rs index 798335d..1c95127 100644 --- a/src/viewer.rs +++ b/src/viewer.rs @@ -1,10 +1,9 @@ -use bevy::{prelude::*, window::PresentMode, render::camera::CameraProjectionPlugin}; +use bevy::{prelude::*, render::camera::CameraProjectionPlugin, window::PresentMode}; use crate::screeninfo::ScreenInfo; // use offaxis::{offaxis_camera_setup, OffAxisProjection}; - -#[derive(Component,Default)] +#[derive(Component, Default)] pub struct Viewer { pub position: Vec3, pub orientation: Quat, @@ -13,13 +12,11 @@ pub struct Viewer { } impl Viewer { - - pub fn new(position: Vec3) ->Self { + pub fn new(position: Vec3) -> Self { Self { position, orientation: Quat::IDENTITY, alpha: 0.0, - } } @@ -27,34 +24,32 @@ impl Viewer { Self { position: Vec3::ZERO, orientation: Quat::IDENTITY, - alpha: 0.0 + alpha: 0.0, } } } -pub fn simulate_viewer(mut query: Query<&mut Viewer>) -{ - for mut v in query.iter_mut() { +pub fn simulate_viewer(mut query: Query<&mut Viewer>, screen_info: Query<&ScreenInfo>) { + for mut v in query.iter_mut() { //v.position += Vec3::Y * 0.005; v.alpha += 0.01; let radius = 1.5; let z_distance = 8.0_f32; - v.position = Vec3::new(v.alpha.sin()*radius,v.alpha.cos()*radius + 1.0_f32,z_distance); + v.position = Vec3::new( + v.alpha.sin() * radius, + v.alpha.cos() * radius + 1.0_f32, + z_distance, + ); let vm = Mat4::look_at_rh(v.position, Vec3::ZERO, Vec3::Y); - - - - - println!("{:?}",vm); + println!("{:?}", vm); // view matrices should be orientation only let dir = Quat::from_mat4(&vm); v.orientation = dir; - } -} \ No newline at end of file +}