added threading handler for capturing VRPN input
This commit is contained in:
parent
6c8c9d70cb
commit
d39fd7b0f6
7 changed files with 119 additions and 102 deletions
12
Cargo.lock
generated
12
Cargo.lock
generated
|
@ -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",
|
||||||
|
|
11
README.md
11
README.md
|
@ -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/
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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,12 +92,13 @@ 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
|
||||||
|
|
||||||
let frustum_left = screen_lower_left - pos_eye; // va
|
let frustum_left = screen_lower_left - pos_eye; // va
|
||||||
let frustum_right = screen_lower_right - pos_eye; // vb
|
let frustum_right = screen_lower_right - pos_eye; // vb
|
||||||
let frustum_up = screen_upper_left - pos_eye; // vc
|
let frustum_up = screen_upper_left - pos_eye; // vc
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
174
src/tracker.rs
174
src/tracker.rs
|
@ -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,67 +24,98 @@ 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)]
|
||||||
|
pub struct Tracker;
|
||||||
|
|
||||||
#[derive(Resource,Debug)]
|
impl FromWorld for Tracker {
|
||||||
struct Tracker;
|
fn from_world(world: &mut World) -> Self {
|
||||||
|
let (sender, receiver): (_, Receiver<PoseReport>) = channel();
|
||||||
impl Tracker {
|
|
||||||
|
|
||||||
pub fn start_tracker(&self) {
|
|
||||||
|
|
||||||
std::thread::spawn(move || {
|
std::thread::spawn(move || {
|
||||||
|
|
||||||
let (sender, receiver): (_, Receiver<PoseReport>) = channel();
|
|
||||||
|
|
||||||
|
|
||||||
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();
|
||||||
|
|
||||||
// We first write our cookie, then read and check the server's cookie, before the loop.
|
// We first write our cookie, then read and check the server's cookie, before the loop.
|
||||||
write_cookie(&mut stream, CookieData::from(MAGIC_DATA)).unwrap();
|
write_cookie(&mut stream, CookieData::from(MAGIC_DATA)).unwrap();
|
||||||
let cookie_buf = read_cookie(&mut stream).unwrap();
|
let cookie_buf = read_cookie(&mut stream).unwrap();
|
||||||
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();
|
// Not actually doing anything with the messages here, just receiving them and printing them.
|
||||||
|
|
||||||
//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();
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
let mut buf = BytesMut::new();
|
||||||
// vrpn implementation is rather verbose - we need to see what specific errors
|
|
||||||
// should be handled properly!
|
// Read the message header and padding
|
||||||
endpoint.poll_endpoint(&mut dispatcher).unwrap_or_else(|err| {
|
buf.resize(24, 0);
|
||||||
info!("error from tracker thread {:?}",err);
|
stream.read_exact(buf.as_mut()).unwrap();
|
||||||
})
|
|
||||||
|
// Peek the size field, to compute the MessageSize.
|
||||||
// dispatcher.han
|
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;
|
||||||
// fn handle_typed_bodyless(&mut self, header: &vrpn::MessageHeader) -> Result<HandlerCode> {
|
// fn handle_typed_bodyless(&mut self, header: &vrpn::MessageHeader) -> Result<HandlerCode> {
|
||||||
|
@ -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
|
||||||
info!("error from tracker thread {:?}",err);
|
.poll_endpoint(&mut dispatcher)
|
||||||
})
|
.unwrap_or_else(|err| {
|
||||||
|
info!("error from tracker thread {:?}", err);
|
||||||
|
})
|
||||||
|
|
||||||
// dispatcher.han
|
// dispatcher.han
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue