nightshade 0.13.0

A cross-platform data-oriented game engine.
Documentation
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
        })
    }
}