feat(input): hand

This commit is contained in:
Nova
2022-09-17 17:26:50 -04:00
parent 8542a5c02b
commit ee250b33fa
6 changed files with 188 additions and 13 deletions

84
src/nodes/input/hand.rs Normal file
View File

@@ -0,0 +1,84 @@
use crate::nodes::fields::Field;
use crate::nodes::spatial::Spatial;
use glam::{vec3a, Mat4};
use libstardustxr::schemas::input_hand::HandT;
use libstardustxr::schemas::{common::JointT, input::InputDataRaw};
use std::sync::Arc;
use super::{DistanceLink, InputSpecialization};
impl InputSpecialization for HandT {
fn distance(&self, space: &Arc<Spatial>, field: &Field) -> f32 {
let mut min_distance = f32::MAX;
for tip in [
&self.thumb.tip.position,
&self.index.tip.position,
&self.middle.tip.position,
&self.ring.tip.position,
&self.little.tip.position,
] {
min_distance = min_distance.min(field.distance(space, vec3a(tip.x, tip.y, tip.z)));
}
min_distance
}
fn serialize(
&self,
fbb: &mut flatbuffers::FlatBufferBuilder,
_distance_link: &DistanceLink,
local_to_handler_matrix: Mat4,
) -> (
InputDataRaw,
flatbuffers::WIPOffset<flatbuffers::UnionWIPOffset>,
) {
let mut hand = self.clone();
let mut joints: Vec<&mut JointT> = Vec::new();
joints.extend([&mut hand.palm, &mut hand.wrist]);
if let Some(elbow) = &mut hand.elbow {
joints.push(elbow);
}
for finger in [
&mut hand.index,
&mut hand.middle,
&mut hand.ring,
&mut hand.little,
] {
joints.extend([
&mut finger.tip,
&mut finger.distal,
&mut finger.intermediate,
&mut finger.proximal,
&mut finger.metacarpal,
]);
}
joints.extend([
&mut hand.thumb.tip,
&mut hand.thumb.distal,
&mut hand.thumb.proximal,
&mut hand.thumb.metacarpal,
]);
for joint in joints {
let rotation: mint::Quaternion<f32> = joint.rotation.clone().into();
let position: mint::Vector3<f32> = joint.position.clone().into();
let joint_matrix = Mat4::from_rotation_translation(rotation.into(), position.into())
* local_to_handler_matrix;
let (_, rotation, position) = joint_matrix.to_scale_rotation_translation();
let rotation: mint::Quaternion<f32> = rotation.into();
let position: mint::Vector3<f32> = position.into();
joint.position = position.into();
joint.rotation = rotation.into();
}
(InputDataRaw::Hand, hand.pack(fbb).as_union_value())
}
fn serialize_datamap(&self) -> Vec<u8> {
let mut fbb = flexbuffers::Builder::default();
let mut map = fbb.start_map();
map.push("right", self.right);
map.end_map();
fbb.view().to_vec()
}
}

View File

@@ -1,3 +1,4 @@
pub mod hand;
pub mod pointer;
use self::pointer::Pointer;
@@ -11,7 +12,9 @@ use crate::core::registry::Registry;
use anyhow::{anyhow, ensure, Result};
use glam::Mat4;
use libstardustxr::schemas::input::{InputData, InputDataArgs, InputDataRaw};
use libstardustxr::schemas::input_hand::HandT;
use nanoid::nanoid;
use parking_lot::Mutex;
use std::ops::Deref;
use std::sync::atomic::Ordering;
use std::sync::{Arc, Weak};
@@ -34,28 +37,32 @@ pub trait InputSpecialization: Send + Sync {
}
pub enum InputType {
Pointer(Pointer),
Hand(Box<HandT>),
}
impl Deref for InputType {
type Target = dyn InputSpecialization;
fn deref(&self) -> &Self::Target {
match self {
InputType::Pointer(p) => p,
InputType::Hand(h) => h.as_ref(),
}
}
}
pub struct InputMethod {
pub uid: String,
pub enabled: Mutex<bool>,
pub spatial: Arc<Spatial>,
pub specialization: InputType,
pub specialization: Mutex<InputType>,
pub captures: Registry<InputHandler>,
}
impl InputMethod {
pub fn new(spatial: Arc<Spatial>, specialization: InputType) -> Arc<InputMethod> {
let method = InputMethod {
uid: nanoid!(),
enabled: Mutex::new(true),
spatial,
specialization,
specialization: Mutex::new(specialization),
captures: Registry::new(),
};
INPUT_METHOD_REGISTRY.add(method)
@@ -69,8 +76,9 @@ impl InputMethod {
let method = InputMethod {
uid: node.uid.clone(),
enabled: Mutex::new(true),
spatial: node.spatial.get().unwrap().clone(),
specialization,
specialization: Mutex::new(specialization),
captures: Registry::new(),
};
let method = INPUT_METHOD_REGISTRY.add(method);
@@ -78,10 +86,10 @@ impl InputMethod {
Ok(())
}
fn distance(&self, to: &Field) -> f32 {
self.specialization.distance(&self.spatial, &to)
self.specialization.lock().distance(&self.spatial, to)
}
fn serialize_datamap(&self) -> Vec<u8> {
self.specialization.serialize_datamap()
self.specialization.lock().serialize_datamap()
}
}
impl Drop for InputMethod {
@@ -115,7 +123,7 @@ impl DistanceLink {
let uid = Some(fbb.create_string(&self.method.uid));
let datamap = Some(fbb.create_vector(datamap));
let (input_type, input_data) = self.method.specialization.serialize(
let (input_type, input_data) = self.method.specialization.lock().serialize(
&mut fbb,
self,
Spatial::space_to_space_matrix(Some(&self.method.spatial), Some(&self.handler.spatial)),
@@ -227,7 +235,11 @@ pub fn create_input_handler_flex(
}
pub fn process_input() {
for method in INPUT_METHOD_REGISTRY.get_valid_contents() {
for method in INPUT_METHOD_REGISTRY
.get_valid_contents()
.iter()
.filter(|method| *method.enabled.lock())
{
let mut distance_links: Vec<DistanceLink> = INPUT_HANDLER_REGISTRY
.get_valid_contents()
.into_iter()

View File

@@ -1,14 +1,12 @@
use super::{DistanceLink, InputSpecialization};
use crate::nodes::fields::{ray_march, Field, Ray, RayMarchResult};
use crate::nodes::spatial::Spatial;
use glam::{vec3, Mat4};
use libstardustxr::schemas::input::InputDataRaw;
use libstardustxr::schemas::input_pointer;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use crate::nodes::fields::{ray_march, Field, Ray, RayMarchResult};
use crate::nodes::spatial::Spatial;
use super::{DistanceLink, InputSpecialization};
#[derive(Default)]
pub struct Pointer {
grab: AtomicBool,