use openxr as xr;
#[derive(Clone)]
pub struct XrInput {
pub thumbstick: nalgebra_glm::Vec2,
pub right_thumbstick: nalgebra_glm::Vec2,
pub left_trigger: f32,
pub right_trigger: f32,
pub left_grip: f32,
pub right_grip: f32,
pub a_button: bool,
pub b_button: bool,
pub left_thumbstick_click: bool,
pub left_hand_pose: Option<xr::Posef>,
pub right_hand_pose: Option<xr::Posef>,
pub player_position: nalgebra_glm::Vec3,
pub player_yaw: f32,
pub head_yaw: f32,
pub head_position: nalgebra_glm::Vec3,
pub head_orientation: nalgebra_glm::Quat,
}
impl Default for XrInput {
fn default() -> Self {
Self {
thumbstick: nalgebra_glm::vec2(0.0, 0.0),
right_thumbstick: nalgebra_glm::vec2(0.0, 0.0),
left_trigger: 0.0,
right_trigger: 0.0,
left_grip: 0.0,
right_grip: 0.0,
a_button: false,
b_button: false,
left_thumbstick_click: false,
left_hand_pose: None,
right_hand_pose: None,
player_position: nalgebra_glm::vec3(0.0, 0.0, 0.0),
player_yaw: 0.0,
head_yaw: 0.0,
head_position: nalgebra_glm::vec3(0.0, 0.0, 0.0),
head_orientation: nalgebra_glm::quat_identity(),
}
}
}
impl XrInput {
pub fn left_trigger_pressed(&self) -> bool {
self.left_trigger > 0.5
}
pub fn right_trigger_pressed(&self) -> bool {
self.right_trigger > 0.5
}
pub fn left_grip_pressed(&self) -> bool {
self.left_grip > 0.5
}
pub fn right_grip_pressed(&self) -> bool {
self.right_grip > 0.5
}
pub fn a_button_pressed(&self) -> bool {
self.a_button
}
pub fn b_button_pressed(&self) -> bool {
self.b_button
}
fn raw_quat(pose: &xr::Posef) -> nalgebra_glm::Quat {
nalgebra_glm::quat(
pose.orientation.w,
pose.orientation.z,
pose.orientation.y,
pose.orientation.x,
)
}
fn aim_rotation(&self, pose: &xr::Posef) -> nalgebra_glm::Quat {
let player_rotation =
nalgebra_glm::quat_angle_axis(self.player_yaw, &nalgebra_glm::vec3(0.0, 1.0, 0.0));
player_rotation * Self::raw_quat(pose)
}
pub fn left_hand_aim_rotation(&self) -> Option<nalgebra_glm::Quat> {
self.left_hand_pose.map(|pose| self.aim_rotation(&pose))
}
pub fn right_hand_aim_rotation(&self) -> Option<nalgebra_glm::Quat> {
self.right_hand_pose.map(|pose| self.aim_rotation(&pose))
}
pub fn left_hand_aim_direction(&self) -> Option<nalgebra_glm::Vec3> {
self.left_hand_aim_rotation()
.map(|rot| nalgebra_glm::quat_rotate_vec3(&rot, &nalgebra_glm::vec3(0.0, 0.0, 1.0)))
}
pub fn right_hand_aim_direction(&self) -> Option<nalgebra_glm::Vec3> {
self.right_hand_aim_rotation()
.map(|rot| nalgebra_glm::quat_rotate_vec3(&rot, &nalgebra_glm::vec3(0.0, 0.0, 1.0)))
}
pub fn left_hand_position(&self) -> Option<nalgebra_glm::Vec3> {
self.left_hand_pose.map(|pose| {
let local_x = -pose.position.x;
let local_z = -pose.position.z;
let rotated_x = local_x * self.player_yaw.cos() + local_z * self.player_yaw.sin();
let rotated_z = -local_x * self.player_yaw.sin() + local_z * self.player_yaw.cos();
nalgebra_glm::vec3(
rotated_x + self.player_position.x,
pose.position.y + self.player_position.y,
rotated_z + self.player_position.z,
)
})
}
pub fn right_hand_position(&self) -> Option<nalgebra_glm::Vec3> {
self.right_hand_pose.map(|pose| {
let local_x = -pose.position.x;
let local_z = -pose.position.z;
let rotated_x = local_x * self.player_yaw.cos() + local_z * self.player_yaw.sin();
let rotated_z = -local_x * self.player_yaw.sin() + local_z * self.player_yaw.cos();
nalgebra_glm::vec3(
rotated_x + self.player_position.x,
pose.position.y + self.player_position.y,
rotated_z + self.player_position.z,
)
})
}
pub fn left_hand_rotation(&self) -> Option<nalgebra_glm::Quat> {
self.left_hand_pose.map(|pose| {
let openxr_orientation = pose.orientation;
let openxr_quat = nalgebra_glm::quat(
openxr_orientation.w,
openxr_orientation.z,
openxr_orientation.y,
openxr_orientation.x,
);
let flip_x = nalgebra_glm::quat_angle_axis(
180.0_f32.to_radians(),
&nalgebra_glm::vec3(1.0, 0.0, 0.0),
);
let player_rotation =
nalgebra_glm::quat_angle_axis(self.player_yaw, &nalgebra_glm::vec3(0.0, 1.0, 0.0));
player_rotation * flip_x * openxr_quat
})
}
pub fn right_hand_rotation(&self) -> Option<nalgebra_glm::Quat> {
self.right_hand_pose.map(|pose| {
let openxr_orientation = pose.orientation;
let openxr_quat = nalgebra_glm::quat(
openxr_orientation.w,
openxr_orientation.z,
openxr_orientation.y,
openxr_orientation.x,
);
let flip_x = nalgebra_glm::quat_angle_axis(
180.0_f32.to_radians(),
&nalgebra_glm::vec3(1.0, 0.0, 0.0),
);
let player_rotation =
nalgebra_glm::quat_angle_axis(self.player_yaw, &nalgebra_glm::vec3(0.0, 1.0, 0.0));
player_rotation * flip_x * openxr_quat
})
}
}