initial implementation for the off-axis view frustum based on previous code
This commit is contained in:
parent
670e1b1756
commit
10a41fcfce
4 changed files with 118 additions and 76 deletions
|
@ -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
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Add table
Add a link
Reference in a new issue