conworlds
diff src/vr/vr_openhmd.c @ 10:e3f0ca1d008a
added preliminary OpenHMD module
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Fri, 22 Aug 2014 20:11:15 +0300 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/vr/vr_openhmd.c Fri Aug 22 20:11:15 2014 +0300 1.3 @@ -0,0 +1,210 @@ 1.4 +#include "vr_impl.h" 1.5 + 1.6 +#ifdef USE_OPENHMD 1.7 +#include <stdio.h> 1.8 +#include <stdlib.h> 1.9 +#include <openhmd/openhmd.h> 1.10 +#include "opt.h" 1.11 + 1.12 +/* a noble spirit embiggens the framebuffer to avoid aliasing in the middle */ 1.13 +#define EMBIGGEN 1.5 1.14 + 1.15 +static ohmd_context *ctx; 1.16 +static ohmd_device *dev; 1.17 +static void *optdb; 1.18 +static int new_frame = 1; 1.19 + 1.20 +static int disp_width, disp_height; 1.21 +static float ipd; 1.22 + 1.23 +static struct { 1.24 + unsigned int id; 1.25 + float umin, umax; 1.26 + float vmin, vmax; 1.27 +} eye_tex[2]; 1.28 + 1.29 + 1.30 +static int init(void) 1.31 +{ 1.32 + int i, num_hmds; 1.33 + 1.34 + if(!(ctx = ohmd_ctx_create())) { 1.35 + fprintf(stderr, "failed to create OpenHMD context\n"); 1.36 + ohmd_ctx_destroy(ctx); 1.37 + return -1; 1.38 + } 1.39 + if(!(num_hmds = ohmd_ctx_probe(ctx))) { 1.40 + fprintf(stderr, "no HMDs detected\n"); 1.41 + return -1; 1.42 + } 1.43 + 1.44 + for(i=0; i<num_hmds; i++) { 1.45 + const char *vendor = ohmd_list_gets(ctx, i, OHMD_VENDOR); 1.46 + const char *product = ohmd_list_gets(ctx, i, OHMD_PRODUCT); 1.47 + const char *devpath = ohmd_list_gets(ctx, i, OHMD_PATH); 1.48 + 1.49 + printf("[%d] %s - %s (path: %s)\n", i, vendor, product, devpath); 1.50 + } 1.51 + 1.52 + printf("opening device 0\n"); 1.53 + 1.54 + if(!(dev = ohmd_list_open_device(ctx, 0))) { 1.55 + fprintf(stderr, "failed to open device 0: %s\n", ohmd_ctx_get_error(ctx)); 1.56 + return -1; 1.57 + } 1.58 + 1.59 + ohmd_device_geti(dev, OHMD_SCREEN_HORIZONTAL_SIZE, &disp_width); 1.60 + ohmd_device_geti(dev, OHMD_SCREEN_VERTICAL_SIZE, &disp_height); 1.61 + ohmd_device_getf(dev, OHMD_EYE_IPD, &ipd); 1.62 + 1.63 + if((optdb = create_options())) { 1.64 + set_option_int(optdb, VR_OPT_DISPLAY_WIDTH, disp_width); 1.65 + set_option_int(optdb, VR_OPT_DISPLAY_HEIGHT, disp_height); 1.66 + set_option_float(optdb, VR_OPT_IPD, ipd); 1.67 + 1.68 + set_option_int(optdb, VR_OPT_LEYE_XRES, (int)(disp_width / 2.0 * FB_EMBIGGEN)); 1.69 + set_option_int(optdb, VR_OPT_LEYE_YRES, (int)(disp_height * FB_EMBIGGEN)); 1.70 + set_option_int(optdb, VR_OPT_REYE_XRES, (int)(disp_width / 2.0 * FB_EMBIGGEN)); 1.71 + set_option_int(optdb, VR_OPT_REYE_YRES, (int)(disp_height * FB_EMBIGGEN)); 1.72 + } 1.73 + 1.74 + return 0; 1.75 +} 1.76 + 1.77 +static void cleanup(void) 1.78 +{ 1.79 + if(ctx) { 1.80 + ohmd_ctx_destroy(ctx); 1.81 + } 1.82 +} 1.83 + 1.84 + 1.85 +static int set_option(const char *opt, enum opt_type type, void *valp) 1.86 +{ 1.87 + switch(type) { 1.88 + case OTYPE_INT: 1.89 + set_option_int(optdb, opt, *(int*)valp); 1.90 + break; 1.91 + 1.92 + case OTYPE_FLOAT: 1.93 + set_option_float(optdb, opt, *(float*)valp); 1.94 + break; 1.95 + } 1.96 + return 0; 1.97 +} 1.98 + 1.99 +static int get_option(const char *opt, enum opt_type type, void *valp) 1.100 +{ 1.101 + switch(type) { 1.102 + case OTYPE_INT: 1.103 + return get_option_int(optdb, opt, valp); 1.104 + case OTYPE_FLOAT: 1.105 + return get_option_float(optdb, opt, valp); 1.106 + } 1.107 + return -1; 1.108 +} 1.109 + 1.110 +static int translation(int eye, float *vec) 1.111 +{ 1.112 + float xform[16]; 1.113 + 1.114 + view_matrix(eye, xform); 1.115 + 1.116 + vec[0] = xform[3]; 1.117 + vec[1] = xform[7]; 1.118 + vec[2] = xform[11]; 1.119 + return 0; 1.120 +} 1.121 + 1.122 +static int rotation(int eye, float *quat) 1.123 +{ 1.124 + if(!dev) { 1.125 + quat[0] = quat[1] = quat[2] = 0.0f; 1.126 + quat[3] = 1.0f; 1.127 + return -1; 1.128 + } 1.129 + 1.130 + ohmd_device_getf(dev, OHMD_ROTATION_QUAT, quat); 1.131 + return 0; 1.132 +} 1.133 + 1.134 + 1.135 +static void view_matrix(int eye, float *mat) 1.136 +{ 1.137 + ohmd_device_getf(dev, OHMD_LEFT_EYE_GL_MODELVIEW_MATRIX + eye, mat); 1.138 +} 1.139 + 1.140 +static void proj_matrix(int eye, float znear, float zfar, float *mat) 1.141 +{ 1.142 + ohmd_device_setf(dev, OHMD_PROJECTION_ZNEAR, znear); 1.143 + ohmd_device_setf(dev, OHMD_PROJECTION_ZFAR, zfar); 1.144 + ohmd_device_getf(dev, OHMD_LEFT_EYE_GL_PROJECTION_MATRIX + eye, mat); 1.145 +} 1.146 + 1.147 +static void begin(int eye) 1.148 +{ 1.149 + if(new_frame) { 1.150 + ohmd_ctx_update(ctx); 1.151 + new_frame = 0; 1.152 + } 1.153 +} 1.154 + 1.155 +static int present(void) 1.156 +{ 1.157 + new_frame = 1; 1.158 + return 0; 1.159 +} 1.160 + 1.161 +static void set_eye_texture(int eye, unsigned int tex, float umin, float vmin, float umax, float vmax) 1.162 +{ 1.163 + eye_tex[eye].id = tex; 1.164 + eye_tex[eye].umin = umin; 1.165 + eye_tex[eye].umax = umax; 1.166 + eye_tex[eye].vmin = vmin; 1.167 + eye_tex[eye].vmax = vmax; 1.168 +} 1.169 + 1.170 +static void recenter(void) 1.171 +{ 1.172 + /* TODO does OHMD support the magnetometer? */ 1.173 +} 1.174 + 1.175 + 1.176 +struct vr_module *vr_module_openhmd(void) 1.177 +{ 1.178 + static struct vr_module m; 1.179 + 1.180 + if(!m.init) { 1.181 + m.name = "openhmd"; 1.182 + m.init = init; 1.183 + m.cleanup = cleanup; 1.184 + m.set_option = set_option; 1.185 + m.get_option = get_option; 1.186 + m.view_matrix = view_matrix; 1.187 + m.proj_matrix = proj_matrix; 1.188 + m.begin = begin; 1.189 + m.present = present; 1.190 + m.set_eye_texture = set_eye_texture; 1.191 + m.recenter = recenter; 1.192 + } 1.193 +} 1.194 + 1.195 +#else /* don't use OpenHMD */ 1.196 + 1.197 +static int init(void) 1.198 +{ 1.199 + return -1; 1.200 +} 1.201 + 1.202 +struct vr_module *vr_module_openhmd(void) 1.203 +{ 1.204 + static struct vr_module m; 1.205 + 1.206 + if(!m.init) { 1.207 + m.name = "openhmd"; 1.208 + m.init = init; 1.209 + } 1.210 + return &m; 1.211 +} 1.212 + 1.213 +#endif /* USE_OPENHMD */