libgoatvr

changeset 19:437fe32ac633

ops... wasn't handling the stereo eye separation correctly. also fixed a bug in vr_libovr.c causing an assertion inside LibOVR when ovrHmd_GetEyePose was called as a result of calls to view_rotation or view_translation outside of vr_begin/vr_end
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 04 Oct 2014 03:39:14 +0300
parents 1067274dc780
children 827ec716c275
files example/src/main.c src/opt.c src/opt.h src/vr.c src/vr.h src/vr_libovr.c
diffstat 6 files changed, 167 insertions(+), 39 deletions(-) [+]
line diff
     1.1 --- a/example/src/main.c	Fri Oct 03 23:07:27 2014 +0300
     1.2 +++ b/example/src/main.c	Sat Oct 04 03:39:14 2014 +0300
     1.3 @@ -155,7 +155,7 @@
     1.4  		 * rendering the left eye's view (0, 0, width/2, height), and in the right half
     1.5  		 * of the framebuffer for the right eye's view (width/2, 0, width/2, height)
     1.6  		 */
     1.7 -		glViewport(i == 0 ? 0 : fb_width / 2, 0, fb_width / 2, fb_height);
     1.8 +		glViewport(i == VR_EYE_LEFT ? 0 : fb_width / 2, 0, fb_width / 2, fb_height);
     1.9  
    1.10  		glMatrixMode(GL_PROJECTION);
    1.11  		/* -- projection transformation --
    1.12 @@ -249,11 +249,19 @@
    1.13  		draw_box(0.5, 0.5, 0.5, 1.0);
    1.14  		glPopMatrix();
    1.15  	}
    1.16 +
    1.17 +	col[0] = 1;
    1.18 +	col[1] = 1;
    1.19 +	col[2] = 0.4;
    1.20 +	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col);
    1.21 +	draw_box(0.05, 1.2, 6, 1.0);
    1.22 +	draw_box(6, 1.2, 0.05, 1.0);
    1.23  }
    1.24  
    1.25  void draw_box(float xsz, float ysz, float zsz, float norm_sign)
    1.26  {
    1.27  	glMatrixMode(GL_MODELVIEW);
    1.28 +	glPushMatrix();
    1.29  	glScalef(xsz * 0.5, ysz * 0.5, zsz * 0.5);
    1.30  
    1.31  	if(norm_sign < 0.0) {
    1.32 @@ -302,6 +310,7 @@
    1.33  	glEnd();
    1.34  
    1.35  	glFrontFace(GL_CCW);
    1.36 +	glPopMatrix();
    1.37  }
    1.38  
    1.39  /* update_rtarg creates (and/or resizes) the render target used to draw the two stero views */
     2.1 --- a/src/opt.c	Fri Oct 03 23:07:27 2014 +0300
     2.2 +++ b/src/opt.c	Sat Oct 04 03:39:14 2014 +0300
     2.3 @@ -24,6 +24,7 @@
     2.4  
     2.5  void set_option_int(void *optdb, const char *key, int val)
     2.6  {
     2.7 +	int i;
     2.8  	struct option *opt = malloc(sizeof *opt);
     2.9  	if(!opt) {
    2.10  		fprintf(stderr, "failed to set option: %s: %s\n", key, strerror(errno));
    2.11 @@ -32,6 +33,9 @@
    2.12  	opt->type = OTYPE_INT;
    2.13  	opt->ival = val;
    2.14  	opt->fval = (float)val;
    2.15 +	for(i=0; i<4; i++) {
    2.16 +		opt->vval[i] = opt->fval;
    2.17 +	}
    2.18  
    2.19  	if(rb_insert(optdb, (void*)key, opt) == -1) {
    2.20  		fprintf(stderr, "failed to set option: %s\n", key);
    2.21 @@ -40,6 +44,7 @@
    2.22  
    2.23  void set_option_float(void *optdb, const char *key, float val)
    2.24  {
    2.25 +	int i;
    2.26  	struct option *opt = malloc(sizeof *opt);
    2.27  	if(!opt) {
    2.28  		fprintf(stderr, "failed to set option: %s: %s\n", key, strerror(errno));
    2.29 @@ -48,12 +53,55 @@
    2.30  	opt->type = OTYPE_FLOAT;
    2.31  	opt->fval = val;
    2.32  	opt->ival = (int)val;
    2.33 +	for(i=0; i<4; i++) {
    2.34 +		opt->vval[i] = val;
    2.35 +	}
    2.36  
    2.37  	if(rb_insert(optdb, (void*)key, opt) == -1) {
    2.38  		fprintf(stderr, "failed to set option: %s\n", key);
    2.39  	}
    2.40  }
    2.41  
    2.42 +void set_option_vec(void *optdb, const char *key, float *val)
    2.43 +{
    2.44 +	int i;
    2.45 +	struct option *opt = malloc(sizeof *opt);
    2.46 +	if(!opt) {
    2.47 +		fprintf(stderr, "failed to set option: %s: %s\n", key, strerror(errno));
    2.48 +		return;
    2.49 +	}
    2.50 +	opt->type = OTYPE_VEC;
    2.51 +	for(i=0; i<4; i++) {
    2.52 +		opt->vval[i] = val[i];
    2.53 +	}
    2.54 +	opt->fval = val[0];
    2.55 +	opt->ival = (int)val[0];
    2.56 +
    2.57 +	if(rb_insert(optdb, (void*)key, opt) == -1) {
    2.58 +		fprintf(stderr, "failed to set option: %s\n", key);
    2.59 +	}
    2.60 +}
    2.61 +
    2.62 +void set_option_vec3f(void *optdb, const char *key, float x, float y, float z)
    2.63 +{
    2.64 +	float vec[4];
    2.65 +	vec[0] = x;
    2.66 +	vec[1] = y;
    2.67 +	vec[2] = z;
    2.68 +	vec[3] = 1.0f;
    2.69 +	set_option_vec(optdb, key, vec);
    2.70 +}
    2.71 +
    2.72 +void set_option_vec4f(void *optdb, const char *key, float x, float y, float z, float w)
    2.73 +{
    2.74 +	float vec[4];
    2.75 +	vec[0] = x;
    2.76 +	vec[1] = y;
    2.77 +	vec[2] = z;
    2.78 +	vec[3] = w;
    2.79 +	set_option_vec(optdb, key, vec);
    2.80 +}
    2.81 +
    2.82  int get_option_int(void *optdb, const char *key, int *val)
    2.83  {
    2.84  	struct option *opt = rb_find(optdb, (void*)key);
    2.85 @@ -75,3 +123,18 @@
    2.86  	*val = opt->fval;
    2.87  	return 0;
    2.88  }
    2.89 +
    2.90 +int get_option_vec(void *optdb, const char *key, float *val)
    2.91 +{
    2.92 +	int i;
    2.93 +	struct option *opt = rb_find(optdb, (void*)key);
    2.94 +	if(!opt) {
    2.95 +		val[0] = val[1] = val[2] = val[3] = 0.0f;
    2.96 +		return -1;
    2.97 +	}
    2.98 +
    2.99 +	for(i=0; i<4; i++) {
   2.100 +		val[i] = opt->vval[i];
   2.101 +	}
   2.102 +	return 0;
   2.103 +}
   2.104 \ No newline at end of file
     3.1 --- a/src/opt.h	Fri Oct 03 23:07:27 2014 +0300
     3.2 +++ b/src/opt.h	Sat Oct 04 03:39:14 2014 +0300
     3.3 @@ -1,12 +1,13 @@
     3.4  #ifndef OPT_H_
     3.5  #define OPT_H_
     3.6  
     3.7 -enum opt_type { OTYPE_INT, OTYPE_FLOAT };
     3.8 +enum opt_type { OTYPE_INT, OTYPE_FLOAT, OTYPE_VEC };
     3.9  
    3.10  struct option {
    3.11  	enum opt_type type;
    3.12  	int ival;
    3.13  	float fval;
    3.14 +	float vval[4];
    3.15  };
    3.16  
    3.17  void *create_options(void);
    3.18 @@ -14,8 +15,13 @@
    3.19  
    3.20  void set_option_int(void *optdb, const char *key, int val);
    3.21  void set_option_float(void *optdb, const char *key, float val);
    3.22 +void set_option_vec(void *optdb, const char *key, float *val);
    3.23 +/* convenience functions */
    3.24 +void set_option_vec3f(void *optdb, const char *key, float x, float y, float z);
    3.25 +void set_option_vec4f(void *optdb, const char *key, float x, float y, float z, float w);
    3.26  
    3.27  int get_option_int(void *optdb, const char *key, int *val);
    3.28  int get_option_float(void *optdb, const char *key, float *val);
    3.29 +int get_option_vec(void *optdb, const char *key, float *val);
    3.30  
    3.31  #endif	/* OPT_H_ */
     4.1 --- a/src/vr.c	Fri Oct 03 23:07:27 2014 +0300
     4.2 +++ b/src/vr.c	Sat Oct 04 03:39:14 2014 +0300
     4.3 @@ -6,6 +6,7 @@
     4.4  #include "vr_impl.h"
     4.5  #include "mathutil.h"
     4.6  
     4.7 +#define DEF_IPD		0.064f
     4.8  
     4.9  static void fallback_present(void);
    4.10  
    4.11 @@ -36,9 +37,11 @@
    4.12  
    4.13  	/* create the default options database */
    4.14  	if(!defopt && (defopt = create_options())) {
    4.15 -		set_option_float(defopt, VR_RENDER_RES_SCALE, 1.0);
    4.16 -		set_option_float(defopt, VR_EYE_HEIGHT, 1.675);
    4.17 -		set_option_float(defopt, VR_IPD, 0.064);
    4.18 +		set_option_float(defopt, VR_RENDER_RES_SCALE, 1.0f);
    4.19 +		set_option_float(defopt, VR_EYE_HEIGHT, 1.675f);
    4.20 +		set_option_float(defopt, VR_IPD, DEF_IPD);
    4.21 +		set_option_vec3f(defopt, VR_LEYE_OFFSET, -DEF_IPD * 0.5f, 0.0f, 0.0f);
    4.22 +		set_option_vec3f(defopt, VR_REYE_OFFSET, DEF_IPD * 0.5f, 0.0f, 0.0f);
    4.23  		set_option_int(defopt, VR_NULL_STEREO, 0);
    4.24  	}
    4.25  
    4.26 @@ -168,6 +171,14 @@
    4.27  	return res;
    4.28  }
    4.29  
    4.30 +static float *def_option_vec(const char *optname, float *res)
    4.31 +{
    4.32 +	res[0] = res[1] = res[2] = res[3] = 0.0f;
    4.33 +
    4.34 +	get_option_vec(defopt, optname, res);
    4.35 +	return res;
    4.36 +}
    4.37 +
    4.38  int vr_geti(const char *optname)
    4.39  {
    4.40  	int res = 0;
    4.41 @@ -188,6 +199,17 @@
    4.42  	return res;
    4.43  }
    4.44  
    4.45 +float *vr_getfv(const char *optname, float *res)
    4.46 +{
    4.47 +	static float sres[4];
    4.48 +	if(!res) res = sres;
    4.49 +
    4.50 +	if(!vrm || !vrm->get_option || vrm->get_option(optname, OTYPE_VEC, res) == -1) {
    4.51 +		def_option_vec(optname, res);
    4.52 +	}
    4.53 +	return res;
    4.54 +}
    4.55 +
    4.56  int vr_geti_def(const char *optname, int def_val)
    4.57  {
    4.58  	int res = 0;
    4.59 @@ -214,17 +236,12 @@
    4.60  
    4.61  int vr_view_translation(int eye, float *vec)
    4.62  {
    4.63 -	float eye_offset;
    4.64 -
    4.65  	if(vrm && vrm->translation) {
    4.66  		vrm->translation(eye, vec);
    4.67  		return 1;
    4.68  	}
    4.69 -
    4.70 -	eye_offset = vr_getf(VR_IPD) / 2.0;
    4.71 -	vec[0] = eye == VR_EYE_LEFT ? -eye_offset : eye_offset;
    4.72 -	vec[1] = vec[2] = 0.0f;
    4.73 -	return 1;
    4.74 +	vec[0] = vec[1] = vec[2] = 0.0f;
    4.75 +	return 0;
    4.76  }
    4.77  
    4.78  int vr_view_rotation(int eye, float *quat)
    4.79 @@ -240,31 +257,36 @@
    4.80  
    4.81  int vr_view_matrix(int eye, float *mat)
    4.82  {
    4.83 -	float offs[3], quat[4];
    4.84 -	float rmat[16], tmat[16];
    4.85 +	float offs[3], quat[4], eye_offs[4];
    4.86 +	float rmat[16] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
    4.87 +	float tmat[16] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
    4.88  
    4.89  	if(vrm && vrm->view_matrix) {
    4.90  		vrm->view_matrix(eye, mat);
    4.91  		return 1;
    4.92  	}
    4.93  
    4.94 -	if(!vr_view_translation(eye, offs)) {
    4.95 -		float eye_offset = vr_getf(VR_IPD) / 2.0;
    4.96 -		offs[0] = eye == VR_EYE_LEFT ? -eye_offset : eye_offset;
    4.97 -		offs[1] = offs[2];
    4.98 +	memcpy(mat, idmat, sizeof idmat);
    4.99 +
   4.100 +	if(vr_view_translation(eye, offs)) {
   4.101 +		offs[0] = -offs[0];
   4.102 +		offs[1] = -offs[1];
   4.103 +		offs[2] = -offs[2];
   4.104 +
   4.105 +		vrimp_translation_matrix(offs, tmat);
   4.106 +		vrimp_mult_matrix(mat, mat, tmat);
   4.107  	}
   4.108 -	if(!vr_view_rotation(eye, quat)) {
   4.109 -		quat[0] = quat[1] = quat[2] = 0.0f;
   4.110 -		quat[3] = 1.0f;
   4.111 +	if(vr_view_rotation(eye, quat)) {
   4.112 +		vrimp_rotation_matrix(quat, rmat);
   4.113 +		vrimp_mult_matrix(mat, mat, rmat);
   4.114  	}
   4.115  
   4.116 -	offs[0] = -offs[0];
   4.117 -	offs[1] = -offs[1];
   4.118 -	offs[2] = -offs[2];
   4.119 -
   4.120 -	vrimp_translation_matrix(offs, tmat);
   4.121 -	vrimp_rotation_matrix(quat, rmat);
   4.122 -	vrimp_mult_matrix(mat, tmat, rmat);
   4.123 +	vr_getfv(eye == VR_EYE_LEFT ? VR_LEYE_OFFSET : VR_REYE_OFFSET, eye_offs);
   4.124 +	eye_offs[0] = -eye_offs[0];
   4.125 +	eye_offs[1] = -eye_offs[1];
   4.126 +	eye_offs[2] = -eye_offs[2];
   4.127 +	vrimp_translation_matrix(eye_offs, tmat);
   4.128 +	vrimp_mult_matrix(mat, mat, tmat);
   4.129  	return 1;
   4.130  }
   4.131  
     5.1 --- a/src/vr.h	Fri Oct 03 23:07:27 2014 +0300
     5.2 +++ b/src/vr.h	Sat Oct 04 03:39:14 2014 +0300
     5.3 @@ -16,6 +16,8 @@
     5.4  /* unit: meters */
     5.5  #define VR_EYE_HEIGHT		"eye-height"
     5.6  #define VR_IPD				"ipd"
     5.7 +#define VR_LEYE_OFFSET		"left-eye-offset"	/* stereo offset from center of the head */
     5.8 +#define VR_REYE_OFFSET		"right-eye-offset"	/* stereo offset from center of the head */
     5.9  /* misc options */
    5.10  #define VR_NULL_STEREO		"null-stereo"	/* bool, default 0 */
    5.11  
    5.12 @@ -41,6 +43,7 @@
    5.13  void vr_setf(const char *optname, float val);
    5.14  int vr_geti(const char *optname);
    5.15  float vr_getf(const char *optname);
    5.16 +float *vr_getfv(const char *optname, float *res);
    5.17  /* variants of the get functions, with an additional "default value"
    5.18   * argument, which is returned if the requested option is missing
    5.19   */
     6.1 --- a/src/vr_libovr.c	Fri Oct 03 23:07:27 2014 +0300
     6.2 +++ b/src/vr_libovr.c	Sat Oct 04 03:39:14 2014 +0300
     6.3 @@ -17,6 +17,7 @@
     6.4  #include <OVR_CAPI.h>
     6.5  #include <OVR_CAPI_GL.h>
     6.6  
     6.7 +/* undef this if you want the retarded health and safety warning screen */
     6.8  #define DISABLE_RETARDED_HEALTH_WARNING
     6.9  
    6.10  /* just dropping the prototype here to avoid including CAPI_HSWDisplay.h */
    6.11 @@ -28,9 +29,14 @@
    6.12  static ovrSizei eye_res[2];
    6.13  static ovrGLTexture eye_tex[2];
    6.14  static ovrFovPort eye_fov[2];
    6.15 -static ovrPosef pose[2];
    6.16 +static ovrPosef pose[2] = {
    6.17 +		{ {0, 0, 0, 1}, {0, 0, 0} },
    6.18 +		{ {0, 0, 0, 1}, {0, 0, 0} }
    6.19 +};
    6.20  static int deferred_init_done;
    6.21  
    6.22 +static int inside_begin_end;
    6.23 +
    6.24  static int init(void)
    6.25  {
    6.26  	int i, num_hmds;
    6.27 @@ -107,6 +113,7 @@
    6.28  	union ovrGLConfig glcfg;
    6.29  	unsigned int dcaps;
    6.30  	void *win = 0;
    6.31 +	float leye_offs[3], reye_offs[3];
    6.32  
    6.33  	deferred_init_done = 1;
    6.34  
    6.35 @@ -137,6 +144,16 @@
    6.36  		fprintf(stderr, "failed to configure LibOVR distortion renderer\n");
    6.37  	}
    6.38  
    6.39 +	/* set the eye offset options */
    6.40 +	leye_offs[0] = eye_render_desc[ovrEye_Left].ViewAdjust.x;
    6.41 +	leye_offs[1] = eye_render_desc[ovrEye_Left].ViewAdjust.y;
    6.42 +	leye_offs[2] = eye_render_desc[ovrEye_Left].ViewAdjust.z;
    6.43 +	set_option_vec(optdb, VR_LEYE_OFFSET, leye_offs);
    6.44 +	reye_offs[0] = eye_render_desc[ovrEye_Right].ViewAdjust.x;
    6.45 +	reye_offs[1] = eye_render_desc[ovrEye_Right].ViewAdjust.y;
    6.46 +	reye_offs[2] = eye_render_desc[ovrEye_Right].ViewAdjust.z;
    6.47 +	set_option_vec(optdb, VR_REYE_OFFSET, reye_offs);
    6.48 +
    6.49  #ifdef DISABLE_RETARDED_HEALTH_WARNING
    6.50  	ovrhmd_EnableHSWDisplaySDKRender(hmd, 0);
    6.51  #endif
    6.52 @@ -198,10 +215,16 @@
    6.53  		return;
    6.54  	}
    6.55  
    6.56 -	pose[eye] = ovrHmd_GetEyePose(hmd, eye == VR_EYE_LEFT ? ovrEye_Left : ovrEye_Right);
    6.57 -	vec[0] = pose[eye].Position.x + eye_render_desc[eye].ViewAdjust.x;
    6.58 -	vec[1] = pose[eye].Position.y + eye_render_desc[eye].ViewAdjust.y;
    6.59 -	vec[2] = pose[eye].Position.z + eye_render_desc[eye].ViewAdjust.z;
    6.60 +	/* if we're inside the begin-end block we can get a fresh pose, otherwise we'll just
    6.61 +	 * reuse the one we got last frame.
    6.62 +	 */
    6.63 +	if(inside_begin_end) {
    6.64 +		pose[eye] = ovrHmd_GetEyePose(hmd, eye == VR_EYE_LEFT ? ovrEye_Left : ovrEye_Right);
    6.65 +	}
    6.66 +
    6.67 +	vec[0] = pose[eye].Position.x;
    6.68 +	vec[1] = pose[eye].Position.y;
    6.69 +	vec[2] = pose[eye].Position.z;
    6.70  }
    6.71  
    6.72  static void rotation(int eye, float *quat)
    6.73 @@ -212,7 +235,11 @@
    6.74  		return;
    6.75  	}
    6.76  
    6.77 -	pose[eye] = ovrHmd_GetEyePose(hmd, eye == VR_EYE_LEFT ? ovrEye_Left : ovrEye_Right);
    6.78 +	/* same as above (translation) */
    6.79 +	if(inside_begin_end) {
    6.80 +		pose[eye] = ovrHmd_GetEyePose(hmd, eye == VR_EYE_LEFT ? ovrEye_Left : ovrEye_Right);
    6.81 +	}
    6.82 +
    6.83  	quat[0] = pose[eye].Orientation.x;
    6.84  	quat[1] = pose[eye].Orientation.y;
    6.85  	quat[2] = pose[eye].Orientation.z;
    6.86 @@ -240,8 +267,6 @@
    6.87  	}
    6.88  }
    6.89  
    6.90 -static int new_frame = 1;
    6.91 -
    6.92  static void begin(int eye)
    6.93  {
    6.94  	if(!hmd) return;
    6.95 @@ -250,9 +275,9 @@
    6.96  		deferred_init();
    6.97  	}
    6.98  
    6.99 -	if(new_frame) {
   6.100 +	if(!inside_begin_end) {
   6.101  		ovrHmd_BeginFrame(hmd, 0);
   6.102 -		new_frame = 0;
   6.103 +		inside_begin_end = 1;
   6.104  	}
   6.105  }
   6.106  
   6.107 @@ -261,7 +286,7 @@
   6.108  	if(!hmd) return 0;
   6.109  
   6.110  	ovrHmd_EndFrame(hmd, pose, &eye_tex[0].Texture);
   6.111 -	new_frame = 1;
   6.112 +	inside_begin_end = 0;
   6.113  
   6.114  	return 1;
   6.115  }