libgoatvr

view src/vr_openhmd.c @ 7:6896f9cf9621

- configure now emits config.status with the current confure invocation - now vr_init will heed the VR_MODULE env var for the name of the module to use - more stuff on the openhmd module
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 19 Sep 2014 15:16:51 +0300
parents d861e4d6850f
children 3d9ec6fe97d7
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;
31 if(!(ctx = ohmd_ctx_create())) {
32 fprintf(stderr, "failed to create OpenHMD context\n");
33 ohmd_ctx_destroy(ctx);
34 return -1;
35 }
36 if(!(num_hmds = ohmd_ctx_probe(ctx))) {
37 fprintf(stderr, "no HMDs detected\n");
38 return -1;
39 }
41 for(i=0; i<num_hmds; i++) {
42 const char *vendor = ohmd_list_gets(ctx, i, OHMD_VENDOR);
43 const char *product = ohmd_list_gets(ctx, i, OHMD_PRODUCT);
44 const char *devpath = ohmd_list_gets(ctx, i, OHMD_PATH);
46 printf("[%d] %s - %s (path: %s)\n", i, vendor, product, devpath);
47 }
49 printf("opening device 0\n");
51 if(!(dev = ohmd_list_open_device(ctx, 0))) {
52 fprintf(stderr, "failed to open device 0: %s\n", ohmd_ctx_get_error(ctx));
53 return -1;
54 }
56 ohmd_device_geti(dev, OHMD_SCREEN_HORIZONTAL_SIZE, &disp_width);
57 ohmd_device_geti(dev, OHMD_SCREEN_VERTICAL_SIZE, &disp_height);
58 ohmd_device_getf(dev, OHMD_EYE_IPD, &ipd);
59 ipd /= 100.0f; /* convert ipd to meters */
61 if((optdb = create_options())) {
62 set_option_int(optdb, VR_OPT_DISPLAY_WIDTH, disp_width);
63 set_option_int(optdb, VR_OPT_DISPLAY_HEIGHT, disp_height);
64 set_option_float(optdb, VR_OPT_IPD, ipd);
66 set_option_int(optdb, VR_OPT_LEYE_XRES, (int)(disp_width / 2.0 * FB_EMBIGGEN));
67 set_option_int(optdb, VR_OPT_LEYE_YRES, (int)(disp_height * FB_EMBIGGEN));
68 set_option_int(optdb, VR_OPT_REYE_XRES, (int)(disp_width / 2.0 * FB_EMBIGGEN));
69 set_option_int(optdb, VR_OPT_REYE_YRES, (int)(disp_height * FB_EMBIGGEN));
70 }
72 return 0;
73 }
75 static void cleanup(void)
76 {
77 if(ctx) {
78 ohmd_ctx_destroy(ctx);
79 }
80 }
83 static int set_option(const char *opt, enum opt_type type, void *valp)
84 {
85 switch(type) {
86 case OTYPE_INT:
87 set_option_int(optdb, opt, *(int*)valp);
88 break;
90 case OTYPE_FLOAT:
91 set_option_float(optdb, opt, *(float*)valp);
92 break;
93 }
94 return 0;
95 }
97 static int get_option(const char *opt, enum opt_type type, void *valp)
98 {
99 switch(type) {
100 case OTYPE_INT:
101 return get_option_int(optdb, opt, valp);
102 case OTYPE_FLOAT:
103 return get_option_float(optdb, opt, valp);
104 }
105 return -1;
106 }
108 static void translation(int eye, float *vec)
109 {
110 /* OpenHMD doesn't support positional tracking, so just return the eye offset */
112 vec[0] = (eye == VR_EYE_LEFT ? -ipd : ipd) / 2.0;
113 vec[1] = vec[2] = 0.0f;
114 }
116 static void rotation(int eye, float *quat)
117 {
118 if(!dev) {
119 quat[0] = quat[1] = quat[2] = 0.0f;
120 quat[3] = 1.0f;
121 return;
122 }
124 ohmd_device_getf(dev, OHMD_ROTATION_QUAT, quat);
125 }
128 static void view_matrix(int eye, float *mat)
129 {
130 ohmd_device_getf(dev, OHMD_LEFT_EYE_GL_MODELVIEW_MATRIX + eye, mat);
131 }
133 static void proj_matrix(int eye, float znear, float zfar, float *mat)
134 {
135 ohmd_device_setf(dev, OHMD_PROJECTION_ZNEAR, &znear);
136 ohmd_device_setf(dev, OHMD_PROJECTION_ZFAR, &zfar);
137 ohmd_device_getf(dev, OHMD_LEFT_EYE_GL_PROJECTION_MATRIX + eye, mat);
138 }
140 static void begin(int eye)
141 {
142 if(new_frame) {
143 ohmd_ctx_update(ctx);
144 new_frame = 0;
145 }
146 }
148 static int present(void)
149 {
150 new_frame = 1;
151 return 0;
152 }
154 static void set_eye_texture(int eye, unsigned int tex, float umin, float vmin, float umax, float vmax)
155 {
156 eye_tex[eye].id = tex;
157 eye_tex[eye].umin = umin;
158 eye_tex[eye].umax = umax;
159 eye_tex[eye].vmin = vmin;
160 eye_tex[eye].vmax = vmax;
161 }
163 static void recenter(void)
164 {
165 /* TODO grab the current rotation quat, invert it, and use it to
166 * multiply with the rotation quat query results
167 */
168 }
171 struct vr_module *vr_module_openhmd(void)
172 {
173 static struct vr_module m;
175 if(!m.init) {
176 m.name = "openhmd";
177 m.init = init;
178 m.cleanup = cleanup;
179 m.set_option = set_option;
180 m.get_option = get_option;
181 m.translation = translation;
182 m.rotation = rotation;
183 m.view_matrix = view_matrix;
184 m.proj_matrix = proj_matrix;
185 m.begin = begin;
186 m.present = present;
187 m.set_eye_texture = set_eye_texture;
188 m.recenter = recenter;
189 }
190 return &m;
191 }
193 #else /* don't use OpenHMD */
195 static int init(void)
196 {
197 return -1;
198 }
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 }
208 return &m;
209 }
211 #endif /* USE_OPENHMD */