initial implementation for the off-axis view frustum based on previous code

This commit is contained in:
Hartmut Seichter 2022-12-11 12:41:34 +01:00
parent 670e1b1756
commit 10a41fcfce
4 changed files with 118 additions and 76 deletions

View file

@ -10,3 +10,7 @@ edition = "2021"
bevy = { version = "0.9.1", features = ["dynamic"] } bevy = { version = "0.9.1", features = ["dynamic"] }
rand = "0.8.4" rand = "0.8.4"
# vrpn = "0.1.0" # not compatible with 2021 # vrpn = "0.1.0" # not compatible with 2021
[profile.release]
opt-level = 3

View file

@ -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)] #[cfg(test)]
mod tests { mod tests {
use bevy::prelude::Mat4; use bevy::prelude::Mat4;

View file

@ -1,14 +1,12 @@
use bevy::{prelude::*, math::bool, prelude::shape::Quad };
use rand::prelude::*;
use bevy::render::primitives::Plane; use bevy::render::primitives::Plane;
use bevy::{math::bool, prelude::shape::Quad, prelude::*};
use rand::prelude::*;
enum EyePos { enum EyePos {
Left, Left,
Right Right,
} }
#[derive(Default, Component)] #[derive(Default, Component)]
pub struct ScreenInfo { pub struct ScreenInfo {
pub name: String, // main (to identify the screen) pub name: String, // main (to identify the screen)
@ -20,65 +18,59 @@ pub struct ScreenInfo {
up: Vec3, // 0.0 1.0 0.0 (vertical axis) up: Vec3, // 0.0 1.0 0.0 (vertical axis)
horizontal: Vec3, // right vector computed as orthonormal horizontal: Vec3, // right vector computed as orthonormal
top : Vec3,
bottom : Vec3,
left : Vec3,
right : Vec3
} }
impl ScreenInfo { impl ScreenInfo {
pub fn new(name: &str) -> Self { pub fn new(name: &str) -> Self {
Self { Self {
name: name.to_string(), name: name.to_string(),
width: 3.08, width: 3.08,
height: 2.33, 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, normal: Vec3::Z,
up: Vec3::Y, up: Vec3::Y,
horizontal: Vec3::ZERO, horizontal: Vec3::ZERO,
top: Vec3::ZERO,
bottom: Vec3::ZERO,
left: Vec3::ZERO,
right: Vec3::ZERO,
} }
} }
pub fn build_debug_geometry(&self, pub fn build_debug_geometry(
&self,
mut commands: Commands, mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>, mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>, mut materials: ResMut<Assets<StandardMaterial>>,
) ) {
{
// plane // plane
commands.spawn(PbrBundle { commands.spawn(PbrBundle {
mesh: meshes.add(Mesh::from( Quad { size: Vec2 { x: self.width, y: self.height }, flip:false })), 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()), material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()),
..default() ..default()
}); });
} }
pub fn update(&mut self) -> &mut Self { // pub fn update(&mut self) -> &mut Self {
// // compute right as up ^ forward
// self.horizontal = self.up.cross(self.normal);
// compute right as up ^ forward // // points of screen
self.horizontal = self.up.cross(self.normal); // 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
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)
{
fn intersection(&self, p1: Vec3, p2: Vec3) -> (bool, Vec3) {
let u = self.normal.dot(self.center - p1) / self.normal.dot(p2 - p1); let u = self.normal.dot(self.center - p1) / self.normal.dot(p2 - p1);
let intersection_point = p1 + ((p2 - p1) * u); let intersection_point = p1 + ((p2 - p1) * u);
@ -87,13 +79,9 @@ impl ScreenInfo {
(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; let p2 = p1 - self.normal * 10.0;
self.intersection(p1, p2) self.intersection(p1, p2)
} }
} }

View file

@ -1,9 +1,8 @@
use bevy::{prelude::*, window::PresentMode, render::camera::CameraProjectionPlugin}; use bevy::{prelude::*, render::camera::CameraProjectionPlugin, window::PresentMode};
use crate::screeninfo::ScreenInfo; use crate::screeninfo::ScreenInfo;
// use offaxis::{offaxis_camera_setup, OffAxisProjection}; // use offaxis::{offaxis_camera_setup, OffAxisProjection};
#[derive(Component, Default)] #[derive(Component, Default)]
pub struct Viewer { pub struct Viewer {
pub position: Vec3, pub position: Vec3,
@ -13,13 +12,11 @@ pub struct Viewer {
} }
impl Viewer { impl Viewer {
pub fn new(position: Vec3) -> Self { pub fn new(position: Vec3) -> Self {
Self { Self {
position, position,
orientation: Quat::IDENTITY, orientation: Quat::IDENTITY,
alpha: 0.0, alpha: 0.0,
} }
} }
@ -27,13 +24,12 @@ impl Viewer {
Self { Self {
position: Vec3::ZERO, position: Vec3::ZERO,
orientation: Quat::IDENTITY, orientation: Quat::IDENTITY,
alpha: 0.0 alpha: 0.0,
} }
} }
} }
pub fn simulate_viewer(mut query: Query<&mut Viewer>) pub fn simulate_viewer(mut query: Query<&mut Viewer>, screen_info: Query<&ScreenInfo>) {
{
for mut v in query.iter_mut() { for mut v in query.iter_mut() {
//v.position += Vec3::Y * 0.005; //v.position += Vec3::Y * 0.005;
v.alpha += 0.01; v.alpha += 0.01;
@ -41,20 +37,19 @@ pub fn simulate_viewer(mut query: Query<&mut Viewer>)
let z_distance = 8.0_f32; 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); let vm = Mat4::look_at_rh(v.position, Vec3::ZERO, Vec3::Y);
println!("{:?}", vm); println!("{:?}", vm);
// view matrices should be orientation only // view matrices should be orientation only
let dir = Quat::from_mat4(&vm); let dir = Quat::from_mat4(&vm);
v.orientation = dir; v.orientation = dir;
} }
} }