Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Toast spam fix #37

Merged
merged 2 commits into from
Apr 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
172 changes: 3 additions & 169 deletions src/backend/common.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
use std::{
collections::{BinaryHeap, VecDeque},
f32::consts::PI,
sync::Arc,
time::Instant,
};
use std::sync::Arc;

use once_cell::sync::Lazy;
#[cfg(feature = "openxr")]
use openxr as xr;

use glam::{Affine3A, Vec2, Vec3, Vec3A, Vec3Swizzles};
use glam::{Affine3A, Vec3, Vec3A};
use idmap::IdMap;
use serde::Deserialize;
use thiserror::Error;
Expand All @@ -25,7 +20,7 @@ use crate::{
state::AppState,
};

use super::overlay::{OverlayBackend, OverlayData, OverlayState};
use super::overlay::OverlayData;

#[derive(Error, Debug)]
pub enum BackendError {
Expand Down Expand Up @@ -351,167 +346,6 @@ pub enum OverlaySelector {
Name(Arc<str>),
}

struct AppTask {
pub not_before: Instant,
pub task: TaskType,
}

impl PartialEq<AppTask> for AppTask {
fn eq(&self, other: &Self) -> bool {
self.not_before == other.not_before
}
}
impl PartialOrd<AppTask> for AppTask {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Eq for AppTask {}
impl Ord for AppTask {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.not_before.cmp(&other.not_before).reverse()
}
}

pub enum SystemTask {
ColorGain(ColorChannel, f32),
ResetPlayspace,
FixFloor,
}

pub type OverlayTask = dyn FnOnce(&mut AppState, &mut OverlayState) + Send;
pub type CreateOverlayTask =
dyn FnOnce(&mut AppState) -> Option<(OverlayState, Box<dyn OverlayBackend>)> + Send;

pub enum TaskType {
Global(Box<dyn FnOnce(&mut AppState) + Send>),
Overlay(OverlaySelector, Box<OverlayTask>),
CreateOverlay(OverlaySelector, Box<CreateOverlayTask>),
DropOverlay(OverlaySelector),
System(SystemTask),
}

#[derive(Deserialize, Clone, Copy)]
pub enum ColorChannel {
R,
G,
B,
All,
}

pub struct TaskContainer {
tasks: BinaryHeap<AppTask>,
}

impl TaskContainer {
pub fn new() -> Self {
Self {
tasks: BinaryHeap::new(),
}
}

pub fn enqueue(&mut self, task: TaskType) {
self.tasks.push(AppTask {
not_before: Instant::now(),
task,
});
}

pub fn enqueue_at(&mut self, task: TaskType, not_before: Instant) {
self.tasks.push(AppTask { not_before, task });
}

pub fn retrieve_due(&mut self, dest_buf: &mut VecDeque<TaskType>) {
let now = Instant::now();

while let Some(task) = self.tasks.peek() {
if task.not_before > now {
break;
}

// Safe unwrap because we peeked.
dest_buf.push_back(self.tasks.pop().unwrap().task);
}
}
}

pub fn raycast_plane(
source: &Affine3A,
source_fwd: Vec3A,
plane: &Affine3A,
plane_norm: Vec3A,
) -> Option<(f32, Vec2)> {
let plane_normal = plane.transform_vector3a(plane_norm);
let ray_dir = source.transform_vector3a(source_fwd);

let d = plane.translation.dot(-plane_normal);
let dist = -(d + source.translation.dot(plane_normal)) / ray_dir.dot(plane_normal);

let hit_local = plane
.inverse()
.transform_point3a(source.translation + ray_dir * dist)
.xy();

Some((dist, hit_local))
}

pub fn raycast_cylinder(
source: &Affine3A,
source_fwd: Vec3A,
plane: &Affine3A,
curvature: f32,
) -> Option<(f32, Vec2)> {
// this is solved locally; (0,0) is the center of the cylinder, and the cylinder is aligned with the Y axis
let size = plane.x_axis.length();
let to_local = Affine3A {
matrix3: plane.matrix3.mul_scalar(1.0 / size),
translation: plane.translation,
}
.inverse();

let r = size / (2.0 * PI * curvature);

let ray_dir = to_local.transform_vector3a(source.transform_vector3a(source_fwd));
let ray_origin = to_local.transform_point3a(source.translation) + Vec3A::NEG_Z * r;

let d = ray_dir.xz();
let s = ray_origin.xz();

let a = d.dot(d);
let b = d.dot(s);
let c = s.dot(s) - r * r;

let d = (b * b) - (a * c);
if d < f32::EPSILON {
return None;
}

let sqrt_d = d.sqrt();

let t1 = (-b - sqrt_d) / a;
let t2 = (-b + sqrt_d) / a;

let t = t1.max(t2);

if t < f32::EPSILON {
return None;
}

let mut hit_local = ray_origin + ray_dir * t;
if hit_local.z > 0.0 {
// hitting the opposite half of the cylinder
return None;
}

let max_angle = 2.0 * (size / (2.0 * r));
let x_angle = (hit_local.x / r).asin();

hit_local.x = x_angle / max_angle;
hit_local.y /= size;

Some((t, hit_local.xy()))
}

pub fn snap_upright(transform: Affine3A, up_dir: Vec3A) -> Affine3A {
if transform.x_axis.dot(up_dir).abs() < 0.2 {
let scale = transform.x_axis.length();
Expand Down
89 changes: 82 additions & 7 deletions src/backend/input.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
use std::f32::consts::PI;
use std::{collections::VecDeque, time::Instant};

use glam::{Affine3A, Vec2, Vec3, Vec3A};
use glam::{Affine3A, Vec2, Vec3, Vec3A, Vec3Swizzles};

use smallvec::{smallvec, SmallVec};

use crate::backend::common::{snap_upright, OverlaySelector, TaskType};
use crate::backend::common::{snap_upright, OverlaySelector};
use crate::config::{save_state, AStrMapExt, GeneralConfig};
use crate::overlays::anchor::ANCHOR_NAME;
use crate::state::AppState;

use super::common::TaskContainer;
use super::{
common::{raycast_cylinder, raycast_plane, OverlayContainer},
overlay::OverlayData,
};
use super::task::{TaskContainer, TaskType};
use super::{common::OverlayContainer, overlay::OverlayData};

pub struct TrackedDevice {
pub soc: Option<f32>,
Expand Down Expand Up @@ -590,3 +588,80 @@ impl Pointer {
})
}
}

fn raycast_plane(
source: &Affine3A,
source_fwd: Vec3A,
plane: &Affine3A,
plane_norm: Vec3A,
) -> Option<(f32, Vec2)> {
let plane_normal = plane.transform_vector3a(plane_norm);
let ray_dir = source.transform_vector3a(source_fwd);

let d = plane.translation.dot(-plane_normal);
let dist = -(d + source.translation.dot(plane_normal)) / ray_dir.dot(plane_normal);

let hit_local = plane
.inverse()
.transform_point3a(source.translation + ray_dir * dist)
.xy();

Some((dist, hit_local))
}

fn raycast_cylinder(
source: &Affine3A,
source_fwd: Vec3A,
plane: &Affine3A,
curvature: f32,
) -> Option<(f32, Vec2)> {
// this is solved locally; (0,0) is the center of the cylinder, and the cylinder is aligned with the Y axis
let size = plane.x_axis.length();
let to_local = Affine3A {
matrix3: plane.matrix3.mul_scalar(1.0 / size),
translation: plane.translation,
}
.inverse();

let r = size / (2.0 * PI * curvature);

let ray_dir = to_local.transform_vector3a(source.transform_vector3a(source_fwd));
let ray_origin = to_local.transform_point3a(source.translation) + Vec3A::NEG_Z * r;

let d = ray_dir.xz();
let s = ray_origin.xz();

let a = d.dot(d);
let b = d.dot(s);
let c = s.dot(s) - r * r;

let d = (b * b) - (a * c);
if d < f32::EPSILON {
return None;
}

let sqrt_d = d.sqrt();

let t1 = (-b - sqrt_d) / a;
let t2 = (-b + sqrt_d) / a;

let t = t1.max(t2);

if t < f32::EPSILON {
return None;
}

let mut hit_local = ray_origin + ray_dir * t;
if hit_local.z > 0.0 {
// hitting the opposite half of the cylinder
return None;
}

let max_angle = 2.0 * (size / (2.0 * r));
let x_angle = (hit_local.x / r).asin();

hit_local.x = x_angle / max_angle;
hit_local.y /= size;

Some((t, hit_local.xy()))
}
2 changes: 2 additions & 0 deletions src/backend/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,5 @@ pub mod uidev;
pub mod osc;

pub mod overlay;

pub mod task;
2 changes: 1 addition & 1 deletion src/backend/openvr/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use glam::Affine3A;
use ovr_overlay::{pose::Matrix3x4, settings::SettingsManager, sys::HmdMatrix34_t};
use thiserror::Error;

use crate::backend::common::{BackendError, ColorChannel};
use crate::backend::{common::BackendError, task::ColorChannel};

pub trait Affine3AConvert {
fn from_affine(affine: &Affine3A) -> Self;
Expand Down
5 changes: 2 additions & 3 deletions src/backend/openvr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use vulkano::{

use crate::{
backend::{
common::SystemTask,
common::{BackendError, OverlayContainer},
input::interact,
notifications::NotificationManager,
openvr::{
Expand All @@ -31,6 +31,7 @@ use crate::{
overlay::OpenVrOverlayData,
},
overlay::OverlayData,
task::{SystemTask, TaskType},
},
graphics::WlxGraphics,
overlays::{
Expand All @@ -40,8 +41,6 @@ use crate::{
state::AppState,
};

use super::common::{BackendError, OverlayContainer, TaskType};

pub mod helpers;
pub mod input;
pub mod lines;
Expand Down
21 changes: 3 additions & 18 deletions src/backend/openxr/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,29 +129,14 @@ pub(super) fn hmd_pose_from_views(views: &[xr::View]) -> (Affine3A, f32) {
(pos0 + pos1) * 0.5
};
let rot = {
let rot0 = unsafe { std::mem::transmute(views[0].pose.orientation) };
let rot1 = unsafe { std::mem::transmute(views[1].pose.orientation) };
quat_lerp(rot0, rot1, 0.5)
let rot0: Quat = unsafe { std::mem::transmute(views[0].pose.orientation) };
let rot1: Quat = unsafe { std::mem::transmute(views[1].pose.orientation) };
rot0.lerp(rot1, 0.5)
};

(Affine3A::from_rotation_translation(rot, pos), ipd)
}

fn quat_lerp(a: Quat, mut b: Quat, t: f32) -> Quat {
let l2 = a.dot(b);
if l2 < 0.0 {
b = -b;
}

Quat::from_xyzw(
a.x - t * (a.x - b.x),
a.y - t * (a.y - b.y),
a.z - t * (a.z - b.z),
a.w - t * (a.w - b.w),
)
.normalize()
}

pub(super) fn transform_to_norm_quat(transform: &Affine3A) -> Quat {
let norm_mat3 = transform
.matrix3
Expand Down
5 changes: 2 additions & 3 deletions src/backend/openxr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ use vulkano::{command_buffer::CommandBufferUsage, Handle, VulkanObject};

use crate::{
backend::{
common::{OverlayContainer, TaskType},
common::{BackendError, OverlayContainer},
input::interact,
notifications::NotificationManager,
openxr::{input::DoubleClickCounter, lines::LinePool, overlay::OpenXrOverlayData},
overlay::OverlayData,
task::TaskType,
},
graphics::WlxGraphics,
overlays::{
Expand All @@ -27,8 +28,6 @@ use crate::{
state::AppState,
};

use super::common::BackendError;

mod helpers;
mod input;
mod lines;
Expand Down
Loading
Loading