libgoatvr

view src/vr_openhmd.c @ 8:3d9ec6fe97d7

- added distortion mesh generation for the OpenHMD module (unfinished) - changed internal implementation function naming to use the vrimp_ prefix - added an opengl helper function to load extension entry points
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 20 Sep 2014 13:22:53 +0300
parents 6896f9cf9621
children b536bd21b37f
line source
1 #include "vr_impl.h"
3 #ifdef USE_OPENHMD
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <openhmd/openhmd.h>
7 #include "opt.h"
9 /* a noble spirit embiggens the framebuffer to avoid aliasing in the middle */
10 #define FB_EMBIGGEN 1.5
12 static ohmd_context *ctx;
13 static ohmd_device *dev;
14 static void *optdb;
15 static int new_frame = 1;
17 static int disp_width, disp_height;
18 static float ipd;
20 static struct {
21 unsigned int id;
22 float umin, umax;
23 float vmin, vmax;
24 } eye_tex[2];
27 static int init(void)
28 {
29 int i, num_hmds;
30 float distort_k[6];
32 if(!(ctx = ohmd_ctx_create())) {
33 fprintf(stderr, "failed to create OpenHMD context\n");
34 ohmd_ctx_destroy(ctx);
35 return -1;
36 }
37 if(!(num_hmds = ohmd_ctx_probe(ctx))) {
38 fprintf(stderr, "no HMDs detected\n");
39 return -1;
40 }
42 for(i=0; i<num_hmds; i++) {
43 const char *vendor = ohmd_list_gets(ctx, i, OHMD_VENDOR);
44 const char *product = ohmd_list_gets(ctx, i, OHMD_PRODUCT);
45 const char *devpath = ohmd_list_gets(ctx, i, OHMD_PATH);
47 printf("[%d] %s - %s (path: %s)\n", i, vendor, product, devpath);
48 }
50 printf("opening device 0\n");
52 if(!(dev = ohmd_list_open_device(ctx, 0))) {
53 fprintf(stderr, "failed to open device 0: %s\n", ohmd_ctx_get_error(ctx));
54 return -1;
55 }
57 ohmd_device_geti(dev, OHMD_SCREEN_HORIZONTAL_SIZE, &disp_width);
58 ohmd_device_geti(dev, OHMD_SCREEN_VERTICAL_SIZE, &disp_height);
59 ohmd_device_getf(dev, OHMD_EYE_IPD, &ipd);
60 ipd /= 100.0f; /* convert ipd to meters */
62 if((optdb = create_options())) {
63 set_option_int(optdb, VR_OPT_DISPLAY_WIDTH, disp_width);
64 set_option_int(optdb, VR_OPT_DISPLAY_HEIGHT, disp_height);
65 set_option_float(optdb, VR_OPT_IPD, ipd);
67 set_option_int(optdb, VR_OPT_LEYE_XRES, (int)(disp_width / 2.0 * FB_EMBIGGEN));
68 set_option_int(optdb, VR_OPT_LEYE_YRES, (int)(disp_height * FB_EMBIGGEN));
69 set_option_int(optdb, VR_OPT_REYE_XRES, (int)(disp_width / 2.0 * FB_EMBIGGEN));
70 set_option_int(optdb, VR_OPT_REYE_YRES, (int)(disp_height * FB_EMBIGGEN));
71 }
73 ohmd_device_getf(dev, OHMD_DISTORTION_K, distort_k);
74 printf("k: %g %g %g %g %g %g\n", distort_k[0], distort_k[1], distort_k[2],
75 distort_k[3], distort_k[4], distort_k[5]);
76 /* TODO: DK2 returns all zeros here ... maybe we should detect that and switch to
77 * using the DK2 distortion mesh from the Oculus SDK. I'll have to connect the DK1
78 * again to finish the barrel distortion method.
79 */
81 return 0;
82 }
84 static void cleanup(void)
85 {
86 if(ctx) {
87 ohmd_ctx_destroy(ctx);
88 }
89 }
92 static int set_option(const char *opt, enum opt_type type, void *valp)
93 {
94 switch(type) {
95 case OTYPE_INT:
96 set_option_int(optdb, opt, *(int*)valp);
97 break;
99 case OTYPE_FLOAT:
100 set_option_float(optdb, opt, *(float*)valp);
101 break;
102 }
103 return 0;
104 }
106 static int get_option(const char *opt, enum opt_type type, void *valp)
107 {
108 switch(type) {
109 case OTYPE_INT:
110 return get_option_int(optdb, opt, valp);
111 case OTYPE_FLOAT:
112 return get_option_float(optdb, opt, valp);
113 }
114 return -1;
115 }
117 static void translation(int eye, float *vec)
118 {
119 /* OpenHMD doesn't support positional tracking, so just return the eye offset */
121 vec[0] = (eye == VR_EYE_LEFT ? -ipd : ipd) / 2.0;
122 vec[1] = vec[2] = 0.0f;
123 }
125 static void rotation(int eye, float *quat)
126 {
127 if(!dev) {
128 quat[0] = quat[1] = quat[2] = 0.0f;
129 quat[3] = 1.0f;
130 return;
131 }
133 ohmd_device_getf(dev, OHMD_ROTATION_QUAT, quat);
134 }
137 static void view_matrix(int eye, float *mat)
138 {
139 ohmd_device_getf(dev, OHMD_LEFT_EYE_GL_MODELVIEW_MATRIX + eye, mat);
140 }
142 static void proj_matrix(int eye, float znear, float zfar, float *mat)
143 {
144 ohmd_device_setf(dev, OHMD_PROJECTION_ZNEAR, &znear);
145 ohmd_device_setf(dev, OHMD_PROJECTION_ZFAR, &zfar);
146 ohmd_device_getf(dev, OHMD_LEFT_EYE_GL_PROJECTION_MATRIX + eye, mat);
147 }
149 static void begin(int eye)
150 {
151 if(new_frame) {
152 ohmd_ctx_update(ctx);
153 new_frame = 0;
154 }
155 }
157 static int present(void)
158 {
159 new_frame = 1;
160 return 0;
161 }
163 static void set_eye_texture(int eye, unsigned int tex, float umin, float vmin, float umax, float vmax)
164 {
165 eye_tex[eye].id = tex;
166 eye_tex[eye].umin = umin;
167 eye_tex[eye].umax = umax;
168 eye_tex[eye].vmin = vmin;
169 eye_tex[eye].vmax = vmax;
170 }
172 static void recenter(void)
173 {
174 /* TODO grab the current rotation quat, invert it, and use it to
175 * multiply with the rotation quat query results
176 */
177 }
180 struct vr_module *vr_module_openhmd(void)
181 {
182 static struct vr_module m;
184 if(!m.init) {
185 m.name = "openhmd";
186 m.init = init;
187 m.cleanup = cleanup;
188 m.set_option = set_option;
189 m.get_option = get_option;
190 m.translation = translation;
191 m.rotation = rotation;
192 m.view_matrix = view_matrix;
193 m.proj_matrix = proj_matrix;
194 m.begin = begin;
195 m.present = present;
196 /*m.set_eye_texture = set_eye_texture;*/
197 m.recenter = recenter;
198 }
199 return &m;
200 }
202 #else /* don't use OpenHMD */
204 static int init(void)
205 {
206 return -1;
207 }
209 struct vr_module *vr_module_openhmd(void)
210 {
211 static struct vr_module m;
213 if(!m.init) {
214 m.name = "openhmd";
215 m.init = init;
216 }
217 return &m;
218 }
220 #endif /* USE_OPENHMD */