omg: curved screens

This commit is contained in:
galister
2024-03-21 21:04:20 +01:00
parent 82374a60a0
commit 155f653f32
8 changed files with 192 additions and 53 deletions

View File

@@ -1,5 +1,5 @@
use anyhow::{bail, ensure};
use glam::{Affine3A, Quat, Vec3};
use glam::{Affine3A, Quat, Vec3, Vec3A};
use openxr as xr;
use xr::OverlaySessionCreateFlagsEXTX;
@@ -139,12 +139,14 @@ fn quat_lerp(a: Quat, mut b: Quat, t: f32) -> Quat {
.normalize()
}
pub(super) fn transform_to_posef(transform: &Affine3A) -> xr::Posef {
let translation = transform.translation;
pub(super) fn transform_to_norm_quat(transform: &Affine3A) -> Quat {
let norm_mat3 = transform
.matrix3
.mul_scalar(1.0 / transform.matrix3.x_axis.length());
let mut rotation = Quat::from_mat3a(&norm_mat3).normalize();
Quat::from_mat3a(&norm_mat3).normalize()
}
pub(super) fn translation_rotation_to_posef(translation: Vec3A, mut rotation: Quat) -> xr::Posef {
if !rotation.is_finite() {
rotation = Quat::IDENTITY;
}
@@ -163,3 +165,9 @@ pub(super) fn transform_to_posef(transform: &Affine3A) -> xr::Posef {
},
}
}
pub(super) fn transform_to_posef(transform: &Affine3A) -> xr::Posef {
let translation = transform.translation;
let rotation = transform_to_norm_quat(transform);
translation_rotation_to_posef(translation, rotation)
}

View File

@@ -19,7 +19,7 @@ use crate::{
use super::{
swapchain::{create_swapchain_render_data, SwapchainRenderData},
XrState,
CompositionLayer, XrState,
};
static AUTO_INCREMENT: AtomicUsize = AtomicUsize::new(1);
@@ -135,7 +135,7 @@ impl LinePool {
&'a mut self,
xr: &'a XrState,
command_buffer: &mut WlxCommandBuffer,
) -> anyhow::Result<Vec<xr::CompositionLayerQuad<xr::Vulkan>>> {
) -> anyhow::Result<Vec<CompositionLayer>> {
let mut quads = Vec::new();
for line in self.lines.values_mut() {
@@ -155,7 +155,7 @@ impl LinePool {
height: inner.length,
});
quads.push(quad);
quads.push(CompositionLayer::Quad(quad));
}
}

View File

@@ -275,13 +275,18 @@ pub fn openxr_run(running: Arc<AtomicBool>) -> Result<(), BackendError> {
continue;
}
if let Some(quad) = o.present_xr(&xr_state, &mut command_buffer)? {
layers.push((dist_sq, quad));
};
let maybe_layer = o.present_xr(&xr_state, &mut command_buffer)?;
if let CompositionLayer::None = maybe_layer {
continue;
}
layers.push((dist_sq, maybe_layer));
}
for quad in lines.present_xr(&xr_state, &mut command_buffer)? {
layers.push((0.0, quad));
for maybe_layer in lines.present_xr(&xr_state, &mut command_buffer)? {
if let CompositionLayer::None = maybe_layer {
continue;
}
layers.push((0.0, maybe_layer));
}
command_buffer.build_and_execute_now()?;
@@ -290,7 +295,11 @@ pub fn openxr_run(running: Arc<AtomicBool>) -> Result<(), BackendError> {
let frame_ref = layers
.iter()
.map(|f| &f.1 as &xr::CompositionLayerBase<xr::Vulkan>)
.map(|f| match f.1 {
CompositionLayer::Quad(ref l) => l as &xr::CompositionLayerBase<xr::Vulkan>,
CompositionLayer::Cylinder(ref l) => l as &xr::CompositionLayerBase<xr::Vulkan>,
CompositionLayer::None => unreachable!(),
})
.collect::<Vec<_>>();
frame_stream.end(
@@ -351,3 +360,9 @@ pub fn openxr_run(running: Arc<AtomicBool>) -> Result<(), BackendError> {
Ok(())
}
pub(super) enum CompositionLayer<'a> {
None,
Quad(xr::CompositionLayerQuad<'a, xr::Vulkan>),
Cylinder(xr::CompositionLayerCylinderKHR<'a, xr::Vulkan>),
}

View File

@@ -1,8 +1,9 @@
use glam::Vec3A;
use openxr as xr;
use std::sync::Arc;
use std::{f32::consts::PI, sync::Arc};
use xr::{CompositionLayerFlags, EyeVisibility};
use super::{helpers, swapchain::SwapchainRenderData, XrState};
use super::{helpers, swapchain::SwapchainRenderData, CompositionLayer, XrState};
use crate::{
backend::{openxr::swapchain::create_swapchain_render_data, overlay::OverlayData},
graphics::WlxCommandBuffer,
@@ -23,7 +24,7 @@ impl OverlayData<OpenXrOverlayData> {
&'a mut self,
xr: &'a XrState,
command_buffer: &mut WlxCommandBuffer,
) -> anyhow::Result<Option<xr::CompositionLayerQuad<xr::Vulkan>>> {
) -> anyhow::Result<CompositionLayer> {
if let Some(new_view) = self.view() {
self.data.last_view = Some(new_view);
}
@@ -32,7 +33,7 @@ impl OverlayData<OpenXrOverlayData> {
view.clone()
} else {
log::warn!("{}: Will not show - image not ready", self.state.name);
return Ok(None);
return Ok(CompositionLayer::None);
};
let extent = my_view.image().extent();
@@ -55,10 +56,8 @@ impl OverlayData<OpenXrOverlayData> {
};
let sub_image = data.acquire_present_release(command_buffer, my_view, self.state.alpha)?;
let posef = helpers::transform_to_posef(&self.state.transform);
let aspect_ratio = extent[1] as f32 / extent[0] as f32;
let (scale_x, scale_y) = if aspect_ratio < 1.0 {
let major = self.state.transform.matrix3.col(0).length();
(major, major * aspect_ratio)
@@ -67,17 +66,38 @@ impl OverlayData<OpenXrOverlayData> {
(major / aspect_ratio, major)
};
let quad = xr::CompositionLayerQuad::new()
.pose(posef)
.sub_image(sub_image)
.eye_visibility(EyeVisibility::BOTH)
.layer_flags(CompositionLayerFlags::CORRECT_CHROMATIC_ABERRATION)
.space(&xr.stage)
.size(xr::Extent2Df {
width: scale_x,
height: scale_y,
});
Ok(Some(quad))
if let Some(curvature) = self.state.curvature {
let radius = scale_x / (2.0 * PI * curvature);
let quat = helpers::transform_to_norm_quat(&self.state.transform);
let center_point = self.state.transform.translation + quat.mul_vec3a(Vec3A::Z * radius);
let posef = helpers::translation_rotation_to_posef(center_point, quat);
let angle = 2.0 * (scale_x / (2.0 * radius));
let cylinder = xr::CompositionLayerCylinderKHR::new()
.pose(posef)
.sub_image(sub_image)
.eye_visibility(EyeVisibility::BOTH)
.layer_flags(CompositionLayerFlags::CORRECT_CHROMATIC_ABERRATION)
.space(&xr.stage)
.radius(radius)
.central_angle(angle)
.aspect_ratio(aspect_ratio);
Ok(CompositionLayer::Cylinder(cylinder))
} else {
let posef = helpers::transform_to_posef(&self.state.transform);
let quad = xr::CompositionLayerQuad::new()
.pose(posef)
.sub_image(sub_image)
.eye_visibility(EyeVisibility::BOTH)
.layer_flags(CompositionLayerFlags::CORRECT_CHROMATIC_ABERRATION)
.space(&xr.stage)
.size(xr::Extent2Df {
width: scale_x,
height: scale_y,
});
Ok(CompositionLayer::Quad(quad))
}
}
pub(super) fn after_input(&mut self, app: &mut AppState) -> anyhow::Result<()> {