libgoatvr

view src/vr_openhmd.c @ 21:7f9cc8a4d3a5

ported the libovr backend to 0.4.4
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 12 Jan 2015 07:16:39 +0200
parents 27fcd4c2969d
children
line source
1 #include "vr_impl.h"
3 #ifdef USE_OPENHMD
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <openhmd/openhmd.h>
8 #include "opt.h"
10 /* a noble spirit embiggens the framebuffer to avoid aliasing in the middle */
11 #define FB_EMBIGGEN 1.5
13 static ohmd_context *ctx;
14 static ohmd_device *dev;
15 static void *optdb;
16 static int new_frame = 1;
18 static int disp_width, disp_height;
19 static float ipd;
21 static struct {
22 unsigned int id;
23 float umin, umax;
24 float vmin, vmax;
25 } eye_tex[2];
28 static int init(void)
29 {
30 int i, num_hmds;
31 float distort_k[6];
33 if(!(ctx = ohmd_ctx_create())) {
34 fprintf(stderr, "failed to create OpenHMD context\n");
35 ohmd_ctx_destroy(ctx);
36 return -1;
37 }
38 if(!(num_hmds = ohmd_ctx_probe(ctx))) {
39 fprintf(stderr, "no HMDs detected\n");
40 return -1;
41 }
43 for(i=0; i<num_hmds; i++) {
44 const char *vendor = ohmd_list_gets(ctx, i, OHMD_VENDOR);
45 const char *product = ohmd_list_gets(ctx, i, OHMD_PRODUCT);
46 const char *devpath = ohmd_list_gets(ctx, i, OHMD_PATH);
48 printf("[%d] %s - %s (path: %s)\n", i, vendor, product, devpath);
49 }
51 printf("opening device 0\n");
53 if(!(dev = ohmd_list_open_device(ctx, 0))) {
54 fprintf(stderr, "failed to open device 0: %s\n", ohmd_ctx_get_error(ctx));
55 return -1;
56 }
58 ohmd_device_geti(dev, OHMD_SCREEN_HORIZONTAL_SIZE, &disp_width);
59 ohmd_device_geti(dev, OHMD_SCREEN_VERTICAL_SIZE, &disp_height);
60 ohmd_device_getf(dev, OHMD_EYE_IPD, &ipd);
61 ipd /= 100.0f; /* convert ipd to meters */
63 if((optdb = create_options())) {
64 int eye_width, eye_height;
66 set_option_int(optdb, VR_DISPLAY_WIDTH, disp_width);
67 set_option_int(optdb, VR_DISPLAY_HEIGHT, disp_height);
68 set_option_float(optdb, VR_IPD, ipd);
70 eye_width = (int)((float)(disp_width / 2) * FB_EMBIGGEN);
71 eye_height = (int)((float)disp_height * FB_EMBIGGEN);
72 set_option_int(optdb, VR_LEYE_XRES, eye_width);
73 set_option_int(optdb, VR_LEYE_YRES, eye_height);
74 set_option_int(optdb, VR_REYE_XRES, eye_width);
75 set_option_int(optdb, VR_REYE_YRES, eye_height);
76 }
78 ohmd_device_getf(dev, OHMD_DISTORTION_K, distort_k);
79 printf("k: %g %g %g %g %g %g\n", distort_k[0], distort_k[1], distort_k[2],
80 distort_k[3], distort_k[4], distort_k[5]);
81 /* TODO: DK2 returns all zeros here ... maybe we should detect that and switch to
82 * using the DK2 distortion mesh from the Oculus SDK. I'll have to connect the DK1
83 * again to finish the barrel distortion method.
84 */
86 return 0;
87 }
89 static void cleanup(void)
90 {
91 if(ctx) {
92 ohmd_ctx_destroy(ctx);
93 }
94 }
97 static int set_option(const char *opt, enum opt_type type, void *valp)
98 {
99 float fval;
101 switch(type) {
102 case OTYPE_INT:
103 fval = (float)*(int*)valp;
104 set_option_int(optdb, opt, *(int*)valp);
105 break;
107 case OTYPE_FLOAT:
108 fval = *(float*)valp;
109 set_option_float(optdb, opt, fval);
110 break;
111 }
113 if(strcmp(opt, VR_RENDER_RES_SCALE) == 0) {
114 int eye_width, eye_height;
115 eye_width = (int)((float)(disp_width / 2) * FB_EMBIGGEN * fval);
116 eye_height = (int)((float)disp_height * FB_EMBIGGEN * fval);
117 set_option_int(optdb, VR_LEYE_XRES, eye_width);
118 set_option_int(optdb, VR_LEYE_YRES, eye_height);
119 set_option_int(optdb, VR_REYE_XRES, eye_width);
120 set_option_int(optdb, VR_REYE_YRES, eye_height);
121 }
123 return 0;
124 }
126 static int get_option(const char *opt, enum opt_type type, void *valp)
127 {
128 switch(type) {
129 case OTYPE_INT:
130 return get_option_int(optdb, opt, valp);
131 case OTYPE_FLOAT:
132 return get_option_float(optdb, opt, valp);
133 }
134 return -1;
135 }
137 static void translation(int eye, float *vec)
138 {
139 /* OpenHMD doesn't support positional tracking, so just return the eye offset */
141 vec[0] = (eye == VR_EYE_LEFT ? -ipd : ipd) / 2.0;
142 vec[1] = vec[2] = 0.0f;
143 }
145 static void rotation(int eye, float *quat)
146 {
147 if(!dev) {
148 quat[0] = quat[1] = quat[2] = 0.0f;
149 quat[3] = 1.0f;
150 return;
151 }
153 ohmd_device_getf(dev, OHMD_ROTATION_QUAT, quat);
154 }
157 static void view_matrix(int eye, float *mat)
158 {
159 ohmd_device_getf(dev, OHMD_LEFT_EYE_GL_MODELVIEW_MATRIX + eye, mat);
160 }
162 static void proj_matrix(int eye, float znear, float zfar, float *mat)
163 {
164 ohmd_device_setf(dev, OHMD_PROJECTION_ZNEAR, &znear);
165 ohmd_device_setf(dev, OHMD_PROJECTION_ZFAR, &zfar);
166 ohmd_device_getf(dev, OHMD_LEFT_EYE_GL_PROJECTION_MATRIX + eye, mat);
167 }
169 static void begin(int eye)
170 {
171 if(new_frame) {
172 ohmd_ctx_update(ctx);
173 new_frame = 0;
174 }
175 }
177 static int present(void)
178 {
179 new_frame = 1;
180 return 0;
181 }
183 static void set_eye_texture(int eye, unsigned int tex, float umin, float vmin, float umax, float vmax)
184 {
185 eye_tex[eye].id = tex;
186 eye_tex[eye].umin = umin;
187 eye_tex[eye].umax = umax;
188 eye_tex[eye].vmin = vmin;
189 eye_tex[eye].vmax = vmax;
190 }
192 static void recenter(void)
193 {
194 /* TODO grab the current rotation quat, invert it, and use it to
195 * multiply with the rotation quat query results
196 */
197 }
200 struct vr_module *vr_module_openhmd(void)
201 {
202 static struct vr_module m;
204 if(!m.init) {
205 m.name = "openhmd";
206 m.init = init;
207 m.cleanup = cleanup;
208 m.set_option = set_option;
209 m.get_option = get_option;
210 m.translation = translation;
211 m.rotation = rotation;
212 m.view_matrix = view_matrix;
213 m.proj_matrix = proj_matrix;
214 m.begin = begin;
215 m.present = present;
216 /*m.set_eye_texture = set_eye_texture;*/
217 m.recenter = recenter;
218 }
219 return &m;
220 }
222 #else /* don't use OpenHMD */
224 static int init(void)
225 {
226 return -1;
227 }
229 struct vr_module *vr_module_openhmd(void)
230 {
231 static struct vr_module m;
233 if(!m.init) {
234 m.name = "openhmd";
235 m.init = init;
236 }
237 return &m;
238 }
240 #endif /* USE_OPENHMD */