# HG changeset patch # User John Tsiombikas # Date 1412383154 -10800 # Node ID 437fe32ac633e9b36d47c5d4539cc021feed9b80 # Parent 1067274dc7809bf35ba87b87c1cd9174208a5ebb 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 diff -r 1067274dc780 -r 437fe32ac633 example/src/main.c --- a/example/src/main.c Fri Oct 03 23:07:27 2014 +0300 +++ b/example/src/main.c Sat Oct 04 03:39:14 2014 +0300 @@ -155,7 +155,7 @@ * rendering the left eye's view (0, 0, width/2, height), and in the right half * of the framebuffer for the right eye's view (width/2, 0, width/2, height) */ - glViewport(i == 0 ? 0 : fb_width / 2, 0, fb_width / 2, fb_height); + glViewport(i == VR_EYE_LEFT ? 0 : fb_width / 2, 0, fb_width / 2, fb_height); glMatrixMode(GL_PROJECTION); /* -- projection transformation -- @@ -249,11 +249,19 @@ draw_box(0.5, 0.5, 0.5, 1.0); glPopMatrix(); } + + col[0] = 1; + col[1] = 1; + col[2] = 0.4; + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col); + draw_box(0.05, 1.2, 6, 1.0); + draw_box(6, 1.2, 0.05, 1.0); } void draw_box(float xsz, float ysz, float zsz, float norm_sign) { glMatrixMode(GL_MODELVIEW); + glPushMatrix(); glScalef(xsz * 0.5, ysz * 0.5, zsz * 0.5); if(norm_sign < 0.0) { @@ -302,6 +310,7 @@ glEnd(); glFrontFace(GL_CCW); + glPopMatrix(); } /* update_rtarg creates (and/or resizes) the render target used to draw the two stero views */ diff -r 1067274dc780 -r 437fe32ac633 src/opt.c --- a/src/opt.c Fri Oct 03 23:07:27 2014 +0300 +++ b/src/opt.c Sat Oct 04 03:39:14 2014 +0300 @@ -24,6 +24,7 @@ void set_option_int(void *optdb, const char *key, int val) { + int i; struct option *opt = malloc(sizeof *opt); if(!opt) { fprintf(stderr, "failed to set option: %s: %s\n", key, strerror(errno)); @@ -32,6 +33,9 @@ opt->type = OTYPE_INT; opt->ival = val; opt->fval = (float)val; + for(i=0; i<4; i++) { + opt->vval[i] = opt->fval; + } if(rb_insert(optdb, (void*)key, opt) == -1) { fprintf(stderr, "failed to set option: %s\n", key); @@ -40,6 +44,7 @@ void set_option_float(void *optdb, const char *key, float val) { + int i; struct option *opt = malloc(sizeof *opt); if(!opt) { fprintf(stderr, "failed to set option: %s: %s\n", key, strerror(errno)); @@ -48,12 +53,55 @@ opt->type = OTYPE_FLOAT; opt->fval = val; opt->ival = (int)val; + for(i=0; i<4; i++) { + opt->vval[i] = val; + } if(rb_insert(optdb, (void*)key, opt) == -1) { fprintf(stderr, "failed to set option: %s\n", key); } } +void set_option_vec(void *optdb, const char *key, float *val) +{ + int i; + struct option *opt = malloc(sizeof *opt); + if(!opt) { + fprintf(stderr, "failed to set option: %s: %s\n", key, strerror(errno)); + return; + } + opt->type = OTYPE_VEC; + for(i=0; i<4; i++) { + opt->vval[i] = val[i]; + } + opt->fval = val[0]; + opt->ival = (int)val[0]; + + if(rb_insert(optdb, (void*)key, opt) == -1) { + fprintf(stderr, "failed to set option: %s\n", key); + } +} + +void set_option_vec3f(void *optdb, const char *key, float x, float y, float z) +{ + float vec[4]; + vec[0] = x; + vec[1] = y; + vec[2] = z; + vec[3] = 1.0f; + set_option_vec(optdb, key, vec); +} + +void set_option_vec4f(void *optdb, const char *key, float x, float y, float z, float w) +{ + float vec[4]; + vec[0] = x; + vec[1] = y; + vec[2] = z; + vec[3] = w; + set_option_vec(optdb, key, vec); +} + int get_option_int(void *optdb, const char *key, int *val) { struct option *opt = rb_find(optdb, (void*)key); @@ -75,3 +123,18 @@ *val = opt->fval; return 0; } + +int get_option_vec(void *optdb, const char *key, float *val) +{ + int i; + struct option *opt = rb_find(optdb, (void*)key); + if(!opt) { + val[0] = val[1] = val[2] = val[3] = 0.0f; + return -1; + } + + for(i=0; i<4; i++) { + val[i] = opt->vval[i]; + } + return 0; +} \ No newline at end of file diff -r 1067274dc780 -r 437fe32ac633 src/opt.h --- a/src/opt.h Fri Oct 03 23:07:27 2014 +0300 +++ b/src/opt.h Sat Oct 04 03:39:14 2014 +0300 @@ -1,12 +1,13 @@ #ifndef OPT_H_ #define OPT_H_ -enum opt_type { OTYPE_INT, OTYPE_FLOAT }; +enum opt_type { OTYPE_INT, OTYPE_FLOAT, OTYPE_VEC }; struct option { enum opt_type type; int ival; float fval; + float vval[4]; }; void *create_options(void); @@ -14,8 +15,13 @@ void set_option_int(void *optdb, const char *key, int val); void set_option_float(void *optdb, const char *key, float val); +void set_option_vec(void *optdb, const char *key, float *val); +/* convenience functions */ +void set_option_vec3f(void *optdb, const char *key, float x, float y, float z); +void set_option_vec4f(void *optdb, const char *key, float x, float y, float z, float w); int get_option_int(void *optdb, const char *key, int *val); int get_option_float(void *optdb, const char *key, float *val); +int get_option_vec(void *optdb, const char *key, float *val); #endif /* OPT_H_ */ diff -r 1067274dc780 -r 437fe32ac633 src/vr.c --- a/src/vr.c Fri Oct 03 23:07:27 2014 +0300 +++ b/src/vr.c Sat Oct 04 03:39:14 2014 +0300 @@ -6,6 +6,7 @@ #include "vr_impl.h" #include "mathutil.h" +#define DEF_IPD 0.064f static void fallback_present(void); @@ -36,9 +37,11 @@ /* create the default options database */ if(!defopt && (defopt = create_options())) { - set_option_float(defopt, VR_RENDER_RES_SCALE, 1.0); - set_option_float(defopt, VR_EYE_HEIGHT, 1.675); - set_option_float(defopt, VR_IPD, 0.064); + set_option_float(defopt, VR_RENDER_RES_SCALE, 1.0f); + set_option_float(defopt, VR_EYE_HEIGHT, 1.675f); + set_option_float(defopt, VR_IPD, DEF_IPD); + set_option_vec3f(defopt, VR_LEYE_OFFSET, -DEF_IPD * 0.5f, 0.0f, 0.0f); + set_option_vec3f(defopt, VR_REYE_OFFSET, DEF_IPD * 0.5f, 0.0f, 0.0f); set_option_int(defopt, VR_NULL_STEREO, 0); } @@ -168,6 +171,14 @@ return res; } +static float *def_option_vec(const char *optname, float *res) +{ + res[0] = res[1] = res[2] = res[3] = 0.0f; + + get_option_vec(defopt, optname, res); + return res; +} + int vr_geti(const char *optname) { int res = 0; @@ -188,6 +199,17 @@ return res; } +float *vr_getfv(const char *optname, float *res) +{ + static float sres[4]; + if(!res) res = sres; + + if(!vrm || !vrm->get_option || vrm->get_option(optname, OTYPE_VEC, res) == -1) { + def_option_vec(optname, res); + } + return res; +} + int vr_geti_def(const char *optname, int def_val) { int res = 0; @@ -214,17 +236,12 @@ int vr_view_translation(int eye, float *vec) { - float eye_offset; - if(vrm && vrm->translation) { vrm->translation(eye, vec); return 1; } - - eye_offset = vr_getf(VR_IPD) / 2.0; - vec[0] = eye == VR_EYE_LEFT ? -eye_offset : eye_offset; - vec[1] = vec[2] = 0.0f; - return 1; + vec[0] = vec[1] = vec[2] = 0.0f; + return 0; } int vr_view_rotation(int eye, float *quat) @@ -240,31 +257,36 @@ int vr_view_matrix(int eye, float *mat) { - float offs[3], quat[4]; - float rmat[16], tmat[16]; + float offs[3], quat[4], eye_offs[4]; + float rmat[16] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; + float tmat[16] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; if(vrm && vrm->view_matrix) { vrm->view_matrix(eye, mat); return 1; } - if(!vr_view_translation(eye, offs)) { - float eye_offset = vr_getf(VR_IPD) / 2.0; - offs[0] = eye == VR_EYE_LEFT ? -eye_offset : eye_offset; - offs[1] = offs[2]; + memcpy(mat, idmat, sizeof idmat); + + if(vr_view_translation(eye, offs)) { + offs[0] = -offs[0]; + offs[1] = -offs[1]; + offs[2] = -offs[2]; + + vrimp_translation_matrix(offs, tmat); + vrimp_mult_matrix(mat, mat, tmat); } - if(!vr_view_rotation(eye, quat)) { - quat[0] = quat[1] = quat[2] = 0.0f; - quat[3] = 1.0f; + if(vr_view_rotation(eye, quat)) { + vrimp_rotation_matrix(quat, rmat); + vrimp_mult_matrix(mat, mat, rmat); } - offs[0] = -offs[0]; - offs[1] = -offs[1]; - offs[2] = -offs[2]; - - vrimp_translation_matrix(offs, tmat); - vrimp_rotation_matrix(quat, rmat); - vrimp_mult_matrix(mat, tmat, rmat); + vr_getfv(eye == VR_EYE_LEFT ? VR_LEYE_OFFSET : VR_REYE_OFFSET, eye_offs); + eye_offs[0] = -eye_offs[0]; + eye_offs[1] = -eye_offs[1]; + eye_offs[2] = -eye_offs[2]; + vrimp_translation_matrix(eye_offs, tmat); + vrimp_mult_matrix(mat, mat, tmat); return 1; } diff -r 1067274dc780 -r 437fe32ac633 src/vr.h --- a/src/vr.h Fri Oct 03 23:07:27 2014 +0300 +++ b/src/vr.h Sat Oct 04 03:39:14 2014 +0300 @@ -16,6 +16,8 @@ /* unit: meters */ #define VR_EYE_HEIGHT "eye-height" #define VR_IPD "ipd" +#define VR_LEYE_OFFSET "left-eye-offset" /* stereo offset from center of the head */ +#define VR_REYE_OFFSET "right-eye-offset" /* stereo offset from center of the head */ /* misc options */ #define VR_NULL_STEREO "null-stereo" /* bool, default 0 */ @@ -41,6 +43,7 @@ void vr_setf(const char *optname, float val); int vr_geti(const char *optname); float vr_getf(const char *optname); +float *vr_getfv(const char *optname, float *res); /* variants of the get functions, with an additional "default value" * argument, which is returned if the requested option is missing */ diff -r 1067274dc780 -r 437fe32ac633 src/vr_libovr.c --- a/src/vr_libovr.c Fri Oct 03 23:07:27 2014 +0300 +++ b/src/vr_libovr.c Sat Oct 04 03:39:14 2014 +0300 @@ -17,6 +17,7 @@ #include #include +/* undef this if you want the retarded health and safety warning screen */ #define DISABLE_RETARDED_HEALTH_WARNING /* just dropping the prototype here to avoid including CAPI_HSWDisplay.h */ @@ -28,9 +29,14 @@ static ovrSizei eye_res[2]; static ovrGLTexture eye_tex[2]; static ovrFovPort eye_fov[2]; -static ovrPosef pose[2]; +static ovrPosef pose[2] = { + { {0, 0, 0, 1}, {0, 0, 0} }, + { {0, 0, 0, 1}, {0, 0, 0} } +}; static int deferred_init_done; +static int inside_begin_end; + static int init(void) { int i, num_hmds; @@ -107,6 +113,7 @@ union ovrGLConfig glcfg; unsigned int dcaps; void *win = 0; + float leye_offs[3], reye_offs[3]; deferred_init_done = 1; @@ -137,6 +144,16 @@ fprintf(stderr, "failed to configure LibOVR distortion renderer\n"); } + /* set the eye offset options */ + leye_offs[0] = eye_render_desc[ovrEye_Left].ViewAdjust.x; + leye_offs[1] = eye_render_desc[ovrEye_Left].ViewAdjust.y; + leye_offs[2] = eye_render_desc[ovrEye_Left].ViewAdjust.z; + set_option_vec(optdb, VR_LEYE_OFFSET, leye_offs); + reye_offs[0] = eye_render_desc[ovrEye_Right].ViewAdjust.x; + reye_offs[1] = eye_render_desc[ovrEye_Right].ViewAdjust.y; + reye_offs[2] = eye_render_desc[ovrEye_Right].ViewAdjust.z; + set_option_vec(optdb, VR_REYE_OFFSET, reye_offs); + #ifdef DISABLE_RETARDED_HEALTH_WARNING ovrhmd_EnableHSWDisplaySDKRender(hmd, 0); #endif @@ -198,10 +215,16 @@ return; } - pose[eye] = ovrHmd_GetEyePose(hmd, eye == VR_EYE_LEFT ? ovrEye_Left : ovrEye_Right); - vec[0] = pose[eye].Position.x + eye_render_desc[eye].ViewAdjust.x; - vec[1] = pose[eye].Position.y + eye_render_desc[eye].ViewAdjust.y; - vec[2] = pose[eye].Position.z + eye_render_desc[eye].ViewAdjust.z; + /* if we're inside the begin-end block we can get a fresh pose, otherwise we'll just + * reuse the one we got last frame. + */ + if(inside_begin_end) { + pose[eye] = ovrHmd_GetEyePose(hmd, eye == VR_EYE_LEFT ? ovrEye_Left : ovrEye_Right); + } + + vec[0] = pose[eye].Position.x; + vec[1] = pose[eye].Position.y; + vec[2] = pose[eye].Position.z; } static void rotation(int eye, float *quat) @@ -212,7 +235,11 @@ return; } - pose[eye] = ovrHmd_GetEyePose(hmd, eye == VR_EYE_LEFT ? ovrEye_Left : ovrEye_Right); + /* same as above (translation) */ + if(inside_begin_end) { + pose[eye] = ovrHmd_GetEyePose(hmd, eye == VR_EYE_LEFT ? ovrEye_Left : ovrEye_Right); + } + quat[0] = pose[eye].Orientation.x; quat[1] = pose[eye].Orientation.y; quat[2] = pose[eye].Orientation.z; @@ -240,8 +267,6 @@ } } -static int new_frame = 1; - static void begin(int eye) { if(!hmd) return; @@ -250,9 +275,9 @@ deferred_init(); } - if(new_frame) { + if(!inside_begin_end) { ovrHmd_BeginFrame(hmd, 0); - new_frame = 0; + inside_begin_end = 1; } } @@ -261,7 +286,7 @@ if(!hmd) return 0; ovrHmd_EndFrame(hmd, pose, &eye_tex[0].Texture); - new_frame = 1; + inside_begin_end = 0; return 1; }