libgoatvr

annotate src/vr_openhmd.c @ 15:27fcd4c2969d

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