added threading handler for capturing VRPN input

This commit is contained in:
Hartmut Seichter 2022-12-20 23:23:03 +01:00
parent 6c8c9d70cb
commit d39fd7b0f6
7 changed files with 119 additions and 102 deletions

12
Cargo.lock generated
View file

@ -74,9 +74,9 @@ checksum = "85965b6739a430150bdd138e2374a98af0c3ee0d030b3bb7fc3bddff58d0102e"
[[package]] [[package]]
name = "android_logger" name = "android_logger"
version = "0.11.2" version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c0c6cfd3264e874d461c0316a78fb78e4147562c68a64881af36fe10573613e" checksum = "8619b80c242aa7bd638b5c7ddd952addeecb71f69c75e33f1d47b2804f8f883a"
dependencies = [ dependencies = [
"android_log-sys", "android_log-sys",
"env_logger", "env_logger",
@ -1817,9 +1817,9 @@ dependencies = [
[[package]] [[package]]
name = "hermit-abi" name = "hermit-abi"
version = "0.1.19" version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
dependencies = [ dependencies = [
"libc", "libc",
] ]
@ -2506,9 +2506,9 @@ dependencies = [
[[package]] [[package]]
name = "num_cpus" name = "num_cpus"
version = "1.14.0" version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5" checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
dependencies = [ dependencies = [
"hermit-abi", "hermit-abi",
"libc", "libc",

View file

@ -18,11 +18,11 @@ PixSpace deals/ plans to deal with:
* [x] custom projection matrices * [x] custom projection matrices
* [~] build a system that updates a cameras frustum (w/ offaxis) * [~] build a system that updates a cameras frustum (w/ offaxis)
* [~] VRPN (https://github.com/seichter/vrpn-rs) - sync_client.rs seems to do what we need - issue it is Rust 2018
* [ ] multiple cameras * [ ] multiple cameras
* [ ] render to texture * [ ] render to texture
* [~] VRPN (https://github.com/seichter/vrpn-rs) - sync_client.rs seems to do what we need - issue it is Rust 2018
# Contributions # Contributions / Notes
Though, I am mostly writing this software on my own, I often ask for help and fortunately FOSS Though, I am mostly writing this software on my own, I often ask for help and fortunately FOSS
people will be happy to help people will be happy to help
@ -34,3 +34,10 @@ https://github.com/bevyengine/bevy/blob/main/examples/3d/split_screen.rs
https://github.com/bevyengine/bevy/blob/main/examples/3d/render_to_texture.rs https://github.com/bevyengine/bevy/blob/main/examples/3d/render_to_texture.rs
And ria8651 on bevy #rendering Discord channel explained pointed me towards reversed Z frustum And ria8651 on bevy #rendering Discord channel explained pointed me towards reversed Z frustum
further
https://thxforthefish.com/posts/reverse_z/
https://vincent-p.github.io/posts/vulkan_perspective_matrix/

View file

@ -52,7 +52,9 @@ fn main() {
.add_startup_system(offaxis_camera_setup) .add_startup_system(offaxis_camera_setup)
// .add_startup_system(setup_tracker) // .add_startup_system(setup_tracker)
// .add_system(update_tracker) // .add_system(update_tracker)
.add_startup_system(setup_threaded_tracker) // .add_startup_system(setup_threaded_tracker)
// .add_startup_system(setup_threaded_tracker_simple)
.init_resource::<Tracker>()
.add_plugin(CameraProjectionPlugin::<OffAxisProjection>::default()) .add_plugin(CameraProjectionPlugin::<OffAxisProjection>::default())
// .add_system(simulate_viewer_with_circle) // .add_system(simulate_viewer_with_circle)

View file

@ -24,7 +24,11 @@ impl CameraProjection for OffAxisProjection {
// what to do on window resize // what to do on window resize
fn update(&mut self, width: f32, height: f32) { fn update(&mut self, width: f32, height: f32) {
// self.aspect = width / height;
// extract sx and sy from matrix
// let sx = self.projection_matrix.x_axis.x;
// let sy = self.projection_matrix.y_axis.y;
} }
fn far(&self) -> f32 { fn far(&self) -> f32 {

View file

@ -48,11 +48,8 @@ pub fn make_projection_rh_from_frustum_reversed(
info!("near {:?}", z_near); info!("near {:?}", z_near);
// //
// reversed z 0..1 projection based on https://thxforthefish.com/posts/reverse_z/ and // reversed z 0..1 projection
// https://vincent-p.github.io/posts/vulkan_perspective_matrix/
// //
let a = (right + left) / (right - left); // position in frame horizontal let a = (right + left) / (right - left); // position in frame horizontal
let b = (top + bottom) / (top - bottom); // position in frame vertical let b = (top + bottom) / (top - bottom); // position in frame vertical
@ -95,7 +92,8 @@ pub fn create_offaxis_matrices(
screen_upper_left: Vec3, screen_upper_left: Vec3,
pos_eye: Vec3, pos_eye: Vec3,
z_far: f32, z_far: f32,
) -> (Mat4, Mat4) { ) -> (Mat4, Mat4)
{
// //
let vec_right = screen_lower_right - screen_lower_left; // vr let vec_right = screen_lower_right - screen_lower_left; // vr
let vec_up = screen_upper_left - screen_lower_left; // vu let vec_up = screen_upper_left - screen_lower_left; // vu

View file

@ -26,7 +26,7 @@ pub fn build_scene(
shadows_enabled: true, shadows_enabled: true,
..default() ..default()
}, },
transform: Transform::from_xyz(4.0, 4.0, -1.5), transform: Transform::from_xyz(4.0, 4.0, 0.0),
..default() ..default()
}); });
} }

View file

@ -1,3 +1,4 @@
use bevy::prelude::*; use bevy::prelude::*;
extern crate bytes; extern crate bytes;
@ -13,7 +14,7 @@ use std::{
net::{SocketAddr, TcpStream}, net::{SocketAddr, TcpStream},
}; };
use std::sync::mpsc::{Receiver,channel}; use std::sync::mpsc::{channel, Receiver};
use vrpn::{ use vrpn::{
codec::peek_u32, codec::peek_u32,
@ -23,25 +24,20 @@ use vrpn::{
message::MessageSize, message::MessageSize,
sync_io::{read_cookie, write_cookie, EndpointSyncTcp}, sync_io::{read_cookie, write_cookie, EndpointSyncTcp},
tracker::PoseReport, tracker::PoseReport,
unbuffer, CookieData, Message, Result, SequencedGenericMessage, TypeDispatcher, Unbuffer, TypedBodylessHandler, unbuffer, CookieData, Message, Result, SequencedGenericMessage, TypeDispatcher,
TypedBodylessHandler, Unbuffer,
}; };
struct TrackerProxy; struct TrackerProxy;
#[derive(Resource, Debug)] #[derive(Resource, Debug)]
struct Tracker; pub struct Tracker;
impl Tracker {
pub fn start_tracker(&self) {
std::thread::spawn(move || {
impl FromWorld for Tracker {
fn from_world(world: &mut World) -> Self {
let (sender, receiver): (_, Receiver<PoseReport>) = channel(); let (sender, receiver): (_, Receiver<PoseReport>) = channel();
std::thread::spawn(move || {
let addr: SocketAddr = "127.0.0.1:3883".parse().unwrap(); let addr: SocketAddr = "127.0.0.1:3883".parse().unwrap();
let mut stream = TcpStream::connect(addr).unwrap(); let mut stream = TcpStream::connect(addr).unwrap();
stream.set_nodelay(true).unwrap(); stream.set_nodelay(true).unwrap();
@ -52,37 +48,73 @@ impl Tracker {
let mut cookie_buf = Bytes::from(&cookie_buf[..]); let mut cookie_buf = Bytes::from(&cookie_buf[..]);
CookieData::unbuffer_ref(&mut cookie_buf) CookieData::unbuffer_ref(&mut cookie_buf)
.and_then(|msg| check_ver_nonfile_compatible(msg.version)).unwrap(); .and_then(|msg| check_ver_nonfile_compatible(msg.version))
.unwrap();
let mut endpoint = EndpointSyncTcp::new(stream);
let mut dispatcher = TypeDispatcher::new();
//let _ = dispatcher.add_typed_handler(Box::new(TrackerHandler {}), None).unwrap();
let _ = dispatcher.add_typed_handler(Box::new( Tracker {} ), None).unwrap();
// setup a channel
// let (tx, rx) = mpsc::channel();
// Not actually doing anything with the messages here, just receiving them and printing them.
loop { loop {
let mut buf = BytesMut::new();
// vrpn implementation is rather verbose - we need to see what specific errors // Read the message header and padding
// should be handled properly! buf.resize(24, 0);
endpoint.poll_endpoint(&mut dispatcher).unwrap_or_else(|err| { stream.read_exact(buf.as_mut()).unwrap();
info!("error from tracker thread {:?}",err);
})
// dispatcher.han // Peek the size field, to compute the MessageSize.
let total_len = peek_u32(&buf.clone().freeze()).unwrap().unwrap();
let size = MessageSize::from_length_field(total_len);
// Read the body of the message
let mut body_buf = BytesMut::new();
body_buf.resize(size.padded_body_size(), 0);
stream.read_exact(body_buf.as_mut()).unwrap();
// Combine the body with the header
buf.extend_from_slice(&body_buf[..]);
let mut buf = buf.freeze();
// Unbuffer the message.
let unbuffered = SequencedGenericMessage::unbuffer_ref(&mut buf).unwrap();
let message = Message::from(unbuffered);
// let result: Message<PoseReport> = Message::try_from_generic(&message)?;
let result = Message::<PoseReport>::try_from_generic(&message);
match result {
Ok(result) => { eprintln!("Ok! {:?}",result.body);},
Err(_) => {}
}
// match result {
// Ok(i) => i,
// _ => false
// }
// match result {
// Message<PoseReport> => println!("")
// }
// eprintln!(
// "{:?} {:?}",
// typed_message.body.sensor, typed_message.body.pos
// );
} }
}); });
Self {}
}
} }
} // pub fn setup_threaded_tracker_simple(mut commands: Commands) {
// commands.spawn(Tracker::new());
// }
// impl TypedBodylessHandler for Tracker { // impl TypedBodylessHandler for Tracker {
// type Item = PoseReport; // type Item = PoseReport;
@ -92,41 +124,13 @@ impl Tracker {
// } // }
// } // }
impl TypedHandler for Tracker { // impl TypedHandler for Tracker {
type Item = PoseReport; // type Item = PoseReport;
fn handle_typed(&mut self, msg: &Message<PoseReport>) -> Result<HandlerCode> { // fn handle_typed(&mut self, msg: &Message<PoseReport>) -> Result<HandlerCode> {
println!("{:?}\n {:?}", msg.header, msg.body); // println!("{:?}\n {:?}", msg.header, msg.body);
Ok(HandlerCode::ContinueProcessing) // Ok(HandlerCode::ContinueProcessing)
} // }
} // }
impl FromWorld for Tracker {
fn from_world(world: &mut World) -> Self {
Self {}
}
}
#[derive(Debug)] #[derive(Debug)]
struct TrackerHandler; struct TrackerHandler;
@ -151,27 +155,29 @@ pub fn setup_threaded_tracker(mut commands: Commands) {
let mut cookie_buf = Bytes::from(&cookie_buf[..]); let mut cookie_buf = Bytes::from(&cookie_buf[..]);
CookieData::unbuffer_ref(&mut cookie_buf) CookieData::unbuffer_ref(&mut cookie_buf)
.and_then(|msg| check_ver_nonfile_compatible(msg.version)).unwrap(); .and_then(|msg| check_ver_nonfile_compatible(msg.version))
.unwrap();
let mut endpoint = EndpointSyncTcp::new(stream); let mut endpoint = EndpointSyncTcp::new(stream);
let mut dispatcher = TypeDispatcher::new(); let mut dispatcher = TypeDispatcher::new();
let _ = dispatcher.add_typed_handler(Box::new(TrackerHandler {}), None).unwrap(); let _ = dispatcher
.add_typed_handler(Box::new(TrackerHandler {}), None)
.unwrap();
// setup a channel // setup a channel
// let (tx, rx) = mpsc::channel(); // let (tx, rx) = mpsc::channel();
loop { loop {
// vrpn implementation is rather verbose - we need to see what specific errors // vrpn implementation is rather verbose - we need to see what specific errors
// should be handled properly! // should be handled properly!
endpoint.poll_endpoint(&mut dispatcher).unwrap_or_else(|err| { endpoint
.poll_endpoint(&mut dispatcher)
.unwrap_or_else(|err| {
info!("error from tracker thread {:?}", err); info!("error from tracker thread {:?}", err);
}) })
// dispatcher.han // dispatcher.han
} }
}); });
} }