From f5f33268ff45c4fba75801c52b0607051a0aa189 Mon Sep 17 00:00:00 2001 From: awtterpip Date: Fri, 12 Jan 2024 08:22:45 -0600 Subject: [PATCH] finish oxr rendering implementation --- xr_api/src/backend/oxr.rs | 98 ++++++++++++++++++++++++++++++++- xr_api/src/backend/oxr/utils.rs | 17 +++++- xr_api/src/types.rs | 8 ++- 3 files changed, 119 insertions(+), 4 deletions(-) diff --git a/xr_api/src/backend/oxr.rs b/xr_api/src/backend/oxr.rs index 544765c..e253414 100644 --- a/xr_api/src/backend/oxr.rs +++ b/xr_api/src/backend/oxr.rs @@ -3,7 +3,7 @@ mod utils; use std::sync::Mutex; -use glam::UVec2; +use glam::{Mat4, UVec2}; use openxr::EnvironmentBlendMode; use tracing::{info, info_span, warn}; @@ -240,7 +240,101 @@ impl ViewTrait for OXrView { } fn projection_matrix(&self) -> glam::Mat4 { - todo!() + // symmetric perspective for debugging + // let x_fov = (self.fov.angle_left.abs() + self.fov.angle_right.abs()); + // let y_fov = (self.fov.angle_up.abs() + self.fov.angle_down.abs()); + // return Mat4::perspective_infinite_reverse_rh(y_fov, x_fov / y_fov, self.near); + + let fov = self.view.fov; + let is_vulkan_api = false; // FIXME wgpu probably abstracts this + let near_z = 0.1; + let far_z = -1.; // use infinite proj + // let far_z = self.far; + + let tan_angle_left = fov.angle_left.tan(); + let tan_angle_right = fov.angle_right.tan(); + + let tan_angle_down = fov.angle_down.tan(); + let tan_angle_up = fov.angle_up.tan(); + + let tan_angle_width = tan_angle_right - tan_angle_left; + + // Set to tanAngleDown - tanAngleUp for a clip space with positive Y + // down (Vulkan). Set to tanAngleUp - tanAngleDown for a clip space with + // positive Y up (OpenGL / D3D / Metal). + // const float tanAngleHeight = + // graphicsApi == GRAPHICS_VULKAN ? (tanAngleDown - tanAngleUp) : (tanAngleUp - tanAngleDown); + let tan_angle_height = if is_vulkan_api { + tan_angle_down - tan_angle_up + } else { + tan_angle_up - tan_angle_down + }; + + // Set to nearZ for a [-1,1] Z clip space (OpenGL / OpenGL ES). + // Set to zero for a [0,1] Z clip space (Vulkan / D3D / Metal). + // const float offsetZ = + // (graphicsApi == GRAPHICS_OPENGL || graphicsApi == GRAPHICS_OPENGL_ES) ? nearZ : 0; + // FIXME handle enum of graphics apis + let offset_z = 0.; + + let mut cols: [f32; 16] = [0.0; 16]; + + if far_z <= near_z { + // place the far plane at infinity + cols[0] = 2. / tan_angle_width; + cols[4] = 0.; + cols[8] = (tan_angle_right + tan_angle_left) / tan_angle_width; + cols[12] = 0.; + + cols[1] = 0.; + cols[5] = 2. / tan_angle_height; + cols[9] = (tan_angle_up + tan_angle_down) / tan_angle_height; + cols[13] = 0.; + + cols[2] = 0.; + cols[6] = 0.; + cols[10] = -1.; + cols[14] = -(near_z + offset_z); + + cols[3] = 0.; + cols[7] = 0.; + cols[11] = -1.; + cols[15] = 0.; + + // bevy uses the _reverse_ infinite projection + // https://dev.theomader.com/depth-precision/ + let z_reversal = Mat4::from_cols_array_2d(&[ + [1f32, 0., 0., 0.], + [0., 1., 0., 0.], + [0., 0., -1., 0.], + [0., 0., 1., 1.], + ]); + + return z_reversal * Mat4::from_cols_array(&cols); + } else { + // normal projection + cols[0] = 2. / tan_angle_width; + cols[4] = 0.; + cols[8] = (tan_angle_right + tan_angle_left) / tan_angle_width; + cols[12] = 0.; + + cols[1] = 0.; + cols[5] = 2. / tan_angle_height; + cols[9] = (tan_angle_up + tan_angle_down) / tan_angle_height; + cols[13] = 0.; + + cols[2] = 0.; + cols[6] = 0.; + cols[10] = -(far_z + offset_z) / (far_z - near_z); + cols[14] = -(far_z * (near_z + offset_z)) / (far_z - near_z); + + cols[3] = 0.; + cols[7] = 0.; + cols[11] = -1.; + cols[15] = 0.; + } + + Mat4::from_cols_array(&cols) } } diff --git a/xr_api/src/backend/oxr/utils.rs b/xr_api/src/backend/oxr/utils.rs index 5217ad8..f17f442 100644 --- a/xr_api/src/backend/oxr/utils.rs +++ b/xr_api/src/backend/oxr/utils.rs @@ -1,3 +1,4 @@ +use glam::Quat; use openxr::Posef; use crate::{error::XrError, prelude::Pose}; @@ -10,6 +11,20 @@ impl From for XrError { impl From for Pose { fn from(value: Posef) -> Self { - todo!() + let translation = { + let openxr::Vector3f { x, y, z } = value.position; + [x, y, z].into() + }; + + let rotation = { + let openxr::Quaternionf { x, y, z, w } = value.orientation; + + Quat::from_xyzw(x, y, z, w) + }; + + Pose { + translation, + rotation, + } } } diff --git a/xr_api/src/types.rs b/xr_api/src/types.rs index 8e598be..f246749 100644 --- a/xr_api/src/types.rs +++ b/xr_api/src/types.rs @@ -1,5 +1,7 @@ use std::rc::Rc; +use glam::{Quat, Vec3}; + use crate::api::Action; use crate::api_traits::{ActionInputTrait, HapticTrait, InputTrait}; use crate::error::Result; @@ -55,7 +57,11 @@ pub enum Handedness { } pub struct Haptic; -pub struct Pose; + +pub struct Pose { + pub translation: Vec3, + pub rotation: Quat, +} pub trait ActionType: Sized { type Inner: ?Sized;