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}