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 }