openhmd_rs/
lib.rs

1extern crate openhmd_rs_sys;
2
3use openhmd_rs_sys::*;
4
5pub use openhmd_rs_sys::{ohmd_float_value, ohmd_int_value, ohmd_string_value};
6
7pub struct Context {
8    context: &'static ohmd_context,
9}
10
11pub struct Device {
12    device: &'static ohmd_device,
13}
14
15pub const SHADER_DISTORTION_VERT: &'static str = r#"
16version 120
17void main(void)
18{
19	gl_TexCoord[0] = gl_MultiTexCoord0;
20    gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;
21}
22"#;
23
24pub const SHADER_SIMPLE_FRAG: &'static str = r#"
25version 120
26
27//per eye texture to warp for lens distortion
28uniform sampler2D warpTexture;
29
30//Position of lens center in m (usually eye_w/2, eye_h/2)
31uniform vec2 LensCenter;
32//Scale from texture co-ords to m (usually eye_w, eye_h)
33uniform vec2 ViewportScale;
34//Distortion overall scale in m (usually ~eye_w/2)
35uniform float WarpScale;
36//Distoriton coefficients (PanoTools model) [a,b,c,d]
37uniform vec4 HmdWarpParam;
38
39//chromatic distortion post scaling
40uniform vec3 aberr;
41
42void main()
43{
44    //output_loc is the fragment location on screen from [0,1]x[0,1]
45    vec2 output_loc = vec2(gl_TexCoord[0].s, gl_TexCoord[0].t);
46    //Compute fragment location in lens-centered co-ordinates at world scale
47	vec2 r = output_loc * ViewportScale - LensCenter;
48    //scale for distortion model
49    //distortion model has r=1 being the largest circle inscribed (e.g. eye_w/2)
50    r /= WarpScale;
51
52    //|r|**2
53    float r_mag = length(r);
54    //offset for which fragment is sourced
55    vec2 r_displaced = r * (HmdWarpParam.w + HmdWarpParam.z * r_mag +
56		HmdWarpParam.y * r_mag * r_mag +
57		HmdWarpParam.x * r_mag * r_mag * r_mag);
58    //back to world scale
59    r_displaced *= WarpScale;
60    //back to viewport co-ord
61    vec2 tc_r = (LensCenter + aberr.r * r_displaced) / ViewportScale;
62    vec2 tc_g = (LensCenter + aberr.g * r_displaced) / ViewportScale;
63    vec2 tc_b = (LensCenter + aberr.b * r_displaced) / ViewportScale;
64
65    float red = texture2D(warpTexture, tc_r).r;
66    float green = texture2D(warpTexture, tc_g).g;
67    float blue = texture2D(warpTexture, tc_b).b;
68    //Black edges off the texture
69    gl_FragColor = ((tc_g.x < 0.0) || (tc_g.x > 1.0) || (tc_g.y < 0.0) || (tc_g.y > 1.0)) ? vec4(0.0, 0.0, 0.0, 1.0) : vec4(red, green, blue, 1.0);
70}
71"#;
72
73impl Context {
74    pub fn new() -> Context {
75        unsafe {
76            Context {
77                context: ohmd_ctx_create(),
78            }
79        }
80    }
81
82    pub fn probe(&self) -> i32 {
83        unsafe { ohmd_ctx_probe(self.context) as i32 }
84    }
85
86    pub fn update(&self) {
87        unsafe {
88            ohmd_ctx_update(self.context);
89        }
90    }
91
92    pub fn list_open_device(&self, index: i32) -> Device {
93        unsafe {
94            Device {
95                device: ohmd_list_open_device(self.context, index),
96            }
97        }
98    }
99
100    pub fn get_error(&self) -> i32 {
101        unsafe { ohmd_ctx_get_error(self.context) as i32 }
102    }
103
104    pub fn destroy(&self) {
105        unsafe {
106            ohmd_ctx_destroy(self.context);
107        }
108    }
109
110    pub fn list_gets(&self, index: i32, otype: ohmd_string_value) -> &str {
111        use std::ffi::CStr;
112        unsafe {
113            let raw = ohmd_list_gets(self.context, index, otype);
114            CStr::from_ptr(raw).to_str().unwrap()
115        }
116    }
117}
118
119impl Drop for Context {
120    fn drop(&mut self) {
121        self.destroy();
122    }
123}
124
125impl Device {
126    pub fn getf(&self, otype: ohmd_float_value) -> Option<[f32; 16]> {
127        let mut out: [f32; 16] = [0.0; 16];
128        unsafe {
129            match ohmd_device_getf(self.device, otype, &mut out) {
130                0 => return Some(out),
131                _ => return None,
132            };
133        }
134    }
135
136    pub fn get_rotation_quat(&self) -> [f32; 4] {
137        let ohmd_orient = match self.getf(ohmd_float_value::OHMD_ROTATION_QUAT) {
138            Some(x) => [x[0], x[1], x[2], x[3]],
139            _ => [0.0; 4],
140        };
141        ohmd_orient
142    }
143
144    pub fn get_position_vec(&self) -> [f32; 3] {
145        let ohmd_position = match self.getf(ohmd_float_value::OHMD_POSITION_VECTOR) {
146            Some(x) => [x[0], x[1], x[2]],
147            _ => [0.0; 3],
148        };
149        ohmd_position
150    }
151
152    pub fn get_view_matrix_l(&self) -> [f32; 16] {
153        let view_left = match self.getf(ohmd_float_value::OHMD_LEFT_EYE_GL_MODELVIEW_MATRIX) {
154            Some(x) => x,
155            None => [0.0; 16],
156        };
157        view_left
158    }
159
160    pub fn get_view_matrix_r(&self) -> [f32; 16] {
161        let view_right = match self.getf(ohmd_float_value::OHMD_RIGHT_EYE_GL_MODELVIEW_MATRIX) {
162            Some(x) => x,
163            None => [0.0; 16],
164        };
165        view_right
166    }
167
168    pub fn get_proj_matrix_l(&self) -> [f32; 16] {
169        let oproj = match self.getf(ohmd_float_value::OHMD_LEFT_EYE_GL_PROJECTION_MATRIX) {
170            Some(x) => x,
171            _ => [0.0; 16],
172        };
173        oproj
174    }
175
176    pub fn get_proj_matrix_r(&self) -> [f32; 16] {
177        let oproj = match self.getf(ohmd_float_value::OHMD_RIGHT_EYE_GL_PROJECTION_MATRIX) {
178            Some(x) => x,
179            _ => [0.0; 16],
180        };
181        oproj
182    }
183
184    pub fn get_scr_size_w(&self) -> f32 {
185        let scr_size_w = match self.getf(ohmd_float_value::OHMD_SCREEN_HORIZONTAL_SIZE) {
186            Some(x) => x[0],
187            _ => 0.149760,
188        };
189        scr_size_w
190    }
191
192    pub fn get_scr_size_h(&self) -> f32 {
193        let scr_size_h = match self.getf(ohmd_float_value::OHMD_SCREEN_VERTICAL_SIZE) {
194            Some(x) => x[0],
195            _ => 0.093600,
196        };
197        scr_size_h
198    }
199
200    pub fn get_scr_res_w(&self) -> u32 {
201        let scrw = match self.geti(ohmd_int_value::OHMD_SCREEN_HORIZONTAL_RESOLUTION) {
202            Some(x) => x,
203            _ => 1280,
204        } as u32;
205        scrw
206    }
207
208    pub fn get_scr_res_h(&self) -> u32 {
209        let scrh = match self.geti(ohmd_int_value::OHMD_SCREEN_VERTICAL_RESOLUTION) {
210            Some(x) => x,
211            _ => 800,
212        } as u32;
213        scrh
214    }
215
216    pub fn get_distortion_k(&self) -> [f32; 4] {
217        let distortion_k = match self.getf(ohmd_float_value::OHMD_UNIVERSAL_DISTORTION_K) {
218            Some(x) => [x[0], x[1], x[2], x[3]],
219            _ => [0.0, 0.0, 0.0, 1.0],
220        };
221        distortion_k
222    }
223
224    pub fn get_aberration_k(&self) -> [f32; 3] {
225        let aberration_k = match self.getf(ohmd_float_value::OHMD_UNIVERSAL_ABERRATION_K) {
226            Some(x) => [x[0], x[1], x[2]],
227            _ => [0.0, 0.0, 1.0],
228        };
229        aberration_k
230    }
231
232    pub fn setf(&self, otype: ohmd_float_value, value: &mut [f32; 16]) -> Option<bool> {
233        unsafe {
234            match ohmd_device_setf(self.device, otype, value) {
235                0 => return Some(true),
236                _ => return None,
237            };
238        }
239    }
240
241    pub fn geti(&self, otype: ohmd_int_value) -> Option<i32> {
242        let mut out: [i32; 1] = [0];
243        unsafe {
244            match ohmd_device_geti(self.device, otype, &mut out) {
245                0 => return Some(out[0]),
246                _ => return None,
247            };
248        }
249    }
250    fn close(&self) -> i32 {
251        unsafe { ohmd_close_device(self.device) as i32 }
252    }
253}
254
255impl Drop for Device {
256    fn drop(&mut self) {
257        self.close();
258    }
259}