vrchess

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 */