From 204d730fb2d5086699776d052f9e8ee0f0ff179e Mon Sep 17 00:00:00 2001 From: Nova Date: Tue, 5 Jul 2022 05:46:21 -0400 Subject: [PATCH] feat: input pointer specialization --- Cargo.toml | 1 + src/nodes/input.rs | 69 +++++++++++++++++++++++------- src/nodes/input_pointer.rs | 86 ++++++++++++++++++++++++++++++++++++++ src/nodes/mod.rs | 1 + 4 files changed, 143 insertions(+), 14 deletions(-) create mode 100644 src/nodes/input_pointer.rs diff --git a/Cargo.toml b/Cargo.toml index aa72590..2845334 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ libstardustxr = {path = "../libstardustxr-rs"} anyhow = "1.0.57" ctrlc = "3.2.2" dashmap = "5.3.4" +flatbuffers = "2.1.2" flexbuffers = "2.0.0" glam = {version = "0.20.5", features = ["mint"]} lazy_static = "1.4.0" diff --git a/src/nodes/input.rs b/src/nodes/input.rs index c695407..f2adaf4 100644 --- a/src/nodes/input.rs +++ b/src/nodes/input.rs @@ -5,7 +5,9 @@ use crate::core::client::Client; use crate::core::eventloop::FRAME; use crate::core::registry::Registry; use anyhow::{anyhow, ensure, Result}; +use glam::Mat4; use lazy_static::lazy_static; +use libstardustxr::schemas::input::{InputData, InputDataArgs, InputDataRaw}; use std::ops::Deref; use std::sync::atomic::Ordering; use std::sync::{Arc, Weak}; @@ -16,8 +18,17 @@ lazy_static! { } pub trait InputSpecializationTrait { - fn distance(&self, space: &Spatial, field: &Field) -> f32; - fn serialize(&self, space: &Spatial, distance: f32) -> Vec; + fn distance(&self, space: &Arc, field: &Field) -> f32; + fn serialize( + &self, + fbb: &mut flatbuffers::FlatBufferBuilder, + distance_link: &DistanceLink, + local_to_handler_matrix: Mat4, + ) -> ( + InputDataRaw, + flatbuffers::WIPOffset, + ); + fn serialize_datamap(&self) -> Vec; } enum InputSpecialization {} impl Deref for InputSpecialization { @@ -31,7 +42,8 @@ impl Deref for InputSpecialization { } pub struct InputMethod { - spatial: Arc, + uid: String, + pub spatial: Arc, specialization: InputSpecialization, } impl InputMethod { @@ -42,6 +54,7 @@ impl InputMethod { ); let method = InputMethod { + uid: node.uid.clone(), spatial: node.spatial.get().unwrap().clone(), specialization, }; @@ -61,10 +74,10 @@ impl Drop for InputMethod { } } -struct DistanceLink { - distance: f32, - method: Weak, - handler: Weak, +pub struct DistanceLink { + pub distance: f32, + pub method: Weak, + pub handler: Weak, } impl DistanceLink { fn from(method: &Arc, handler: &Arc) -> Option { @@ -77,18 +90,44 @@ impl DistanceLink { fn serialize(&self) -> Option> { self.method.upgrade().and_then(|method| { self.handler.upgrade().map(|handler| { - method - .specialization - .serialize(&handler.spatial.upgrade().unwrap(), self.distance) + let mut fbb = flatbuffers::FlatBufferBuilder::with_capacity(1024); + let uid = Some(fbb.create_string(&method.uid)); + let datamap = Some(fbb.create_vector(&self.serialize_datamap())); + + let (input_type, input_data) = method.specialization.serialize( + &mut fbb, + self, + Spatial::space_to_space_matrix(Some(&method.spatial), Some(&handler.spatial)), + ); + + let root = InputData::create( + &mut fbb, + &InputDataArgs { + uid, + input_type, + input: Some(input_data), + distance: self.distance, + datamap, + }, + ); + fbb.finish(root, None); + Vec::from(fbb.finished_data()) }) }) } + fn serialize_datamap(&self) -> Vec { + if let Some(method) = self.method.upgrade() { + method.specialization.serialize_datamap() + } else { + Default::default() + } + } } pub struct InputHandler { node: Weak, - spatial: Weak, - field: Weak, + spatial: Arc, + pub field: Weak, } impl InputHandler { pub fn add_to(node: &Arc, field: &Arc) -> Result<()> { @@ -99,7 +138,7 @@ impl InputHandler { let handler = InputHandler { node: Arc::downgrade(node), - spatial: Arc::downgrade(node.spatial.get().unwrap()), + spatial: node.spatial.get().unwrap().clone(), field: Arc::downgrade(field), }; let handler = INPUT_HANDLER_REGISTRY.add(handler); @@ -117,7 +156,9 @@ impl InputHandler { return; } - if let Some(data) = distance_link.serialize() { + let serialized_data = distance_link.serialize(); + + if let Some(data) = serialized_data { let _ = self.node.upgrade().unwrap().execute_remote_method( "input", &data, diff --git a/src/nodes/input_pointer.rs b/src/nodes/input_pointer.rs new file mode 100644 index 0000000..5b4a26c --- /dev/null +++ b/src/nodes/input_pointer.rs @@ -0,0 +1,86 @@ +use super::field::{ray_march, Field, Ray, RayMarchResult}; +use super::input::{DistanceLink, InputSpecializationTrait}; +use super::spatial::Spatial; +use glam::{vec3, vec3a, Mat4}; +use libstardustxr::schemas::common; +use libstardustxr::schemas::input::InputDataRaw; +use libstardustxr::schemas::input_pointer; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::Arc; + +pub struct Pointer { + grab: AtomicBool, + select: AtomicBool, +} +impl Default for Pointer { + fn default() -> Self { + Pointer { + grab: Default::default(), + select: Default::default(), + } + } +} +impl Pointer { + fn ray_march(&self, space: &Arc, field: &Field) -> RayMarchResult { + ray_march( + Ray { + origin: vec3(0_f32, 0_f32, 0_f32), + direction: vec3(0_f32, 0_f32, 1_f32), + space: space.clone(), + }, + field, + ) + } +} + +impl InputSpecializationTrait for Pointer { + fn distance(&self, space: &Arc, field: &Field) -> f32 { + self.ray_march(space, field).distance + } + fn serialize( + &self, + fbb: &mut flatbuffers::FlatBufferBuilder, + distance_link: &DistanceLink, + local_to_handler_matrix: Mat4, + ) -> ( + InputDataRaw, + flatbuffers::WIPOffset, + ) { + let origin = local_to_handler_matrix.transform_point3a(vec3a(0_f32, 0_f32, 0_f32)); + let direction = local_to_handler_matrix.transform_vector3a(vec3a(0_f32, 0_f32, 1_f32)); + let ray_march = self.ray_march( + &distance_link.method.upgrade().unwrap().spatial, + &distance_link + .handler + .upgrade() + .unwrap() + .field + .upgrade() + .unwrap(), + ); + let deepest_point = (direction * ray_march.deepest_point_distance) + origin; + + let pointer = input_pointer::Pointer::create( + fbb, + &input_pointer::PointerArgs { + origin: Some(&common::Vec3::new(origin.x, origin.y, origin.z)), + direction: Some(&common::Vec3::new(direction.x, direction.y, direction.z)), + tilt: 0_f32, + deepest_point: Some(&common::Vec3::new( + deepest_point.x, + deepest_point.y, + deepest_point.z, + )), + }, + ); + (InputDataRaw::Pointer, pointer.as_union_value()) + } + fn serialize_datamap(&self) -> Vec { + let mut fbb = flexbuffers::Builder::default(); + let mut map = fbb.start_map(); + map.push("grab", self.grab.load(Ordering::Relaxed)); + map.push("select", self.select.load(Ordering::Relaxed)); + map.end_map(); + fbb.view().to_vec() + } +} diff --git a/src/nodes/mod.rs b/src/nodes/mod.rs index 25d4ae0..55755cc 100644 --- a/src/nodes/mod.rs +++ b/src/nodes/mod.rs @@ -2,6 +2,7 @@ pub mod core; pub mod data; pub mod field; pub mod input; +pub mod input_pointer; pub mod item; pub mod root; pub mod spatial;