libgoatvr

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