nuclear@0: #include nuclear@7: #include nuclear@0: #include nuclear@5: #include "opengl.h" nuclear@0: #include "vr.h" nuclear@0: #include "vr_impl.h" nuclear@0: #include "mathutil.h" nuclear@0: nuclear@19: #define DEF_IPD 0.064f nuclear@0: nuclear@5: static void fallback_present(void); nuclear@0: nuclear@0: nuclear@0: static struct vr_module *vrm; nuclear@0: static float idmat[] = { nuclear@0: 1, 0, 0, 0, nuclear@0: 0, 1, 0, 0, nuclear@0: 0, 0, 1, 0, nuclear@0: 0, 0, 0, 1 nuclear@0: }; nuclear@0: static float fbtex_rect[] = { nuclear@0: 0, 0, 1, 1 nuclear@0: }; nuclear@0: nuclear@5: static void *defopt; /* default options db */ nuclear@5: nuclear@5: static struct { nuclear@5: float umin, umax, vmin, vmax; nuclear@5: int tex; nuclear@5: } rtarg[2]; nuclear@5: nuclear@5: nuclear@0: int vr_init(void) nuclear@0: { nuclear@0: int i, nmodules; nuclear@24: char *env; nuclear@0: nuclear@5: /* create the default options database */ nuclear@5: if(!defopt && (defopt = create_options())) { nuclear@19: set_option_float(defopt, VR_RENDER_RES_SCALE, 1.0f); nuclear@19: set_option_float(defopt, VR_EYE_HEIGHT, 1.675f); nuclear@19: set_option_float(defopt, VR_IPD, DEF_IPD); nuclear@19: set_option_vec3f(defopt, VR_LEYE_OFFSET, -DEF_IPD * 0.5f, 0.0f, 0.0f); nuclear@19: set_option_vec3f(defopt, VR_REYE_OFFSET, DEF_IPD * 0.5f, 0.0f, 0.0f); nuclear@24: nuclear@33: set_option_int(defopt, VR_NULL_STEREO_SBS, nuclear@33: (env = getenv("VR_NULL_STEREO_SBS")) && atoi(env) ? 1 : 0); nuclear@33: set_option_int(defopt, VR_NULL_STEREO_GL, nuclear@33: (env = getenv("VR_NULL_STEREO_GL")) && atoi(env) ? 1 : 0); nuclear@33: set_option_int(defopt, VR_NULL_STEREO_REDCYAN, nuclear@33: (env = getenv("VR_NULL_STEREO_REDCYAN")) && atoi(env) ? 1 : 0); nuclear@5: } nuclear@5: nuclear@0: if(vrm) { nuclear@0: vr_shutdown(); nuclear@0: } nuclear@0: nuclear@0: vr_init_modules(); nuclear@0: nuclear@0: nmodules = vr_get_num_modules(); nuclear@0: for(i=0; iinit() != -1) { nuclear@0: /* add to the active modules array */ nuclear@0: vr_activate_module(i); nuclear@0: } nuclear@0: } nuclear@0: nuclear@7: if(!vr_get_num_active_modules()) { nuclear@0: return -1; nuclear@0: } nuclear@7: nuclear@24: if((env = getenv("VR_MODULE"))) { nuclear@24: vr_use_module_named(env); nuclear@7: } else { nuclear@7: vr_use_module(0); nuclear@7: } nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@0: void vr_shutdown(void) nuclear@0: { nuclear@0: vr_clear_modules(); nuclear@0: vrm = 0; nuclear@0: fbtex_rect[0] = fbtex_rect[1] = 0; nuclear@0: fbtex_rect[2] = fbtex_rect[3] = 1; nuclear@0: } nuclear@0: nuclear@0: int vr_module_count(void) nuclear@0: { nuclear@0: return vr_get_num_active_modules(); nuclear@0: } nuclear@0: nuclear@0: const char *vr_module_name(int idx) nuclear@0: { nuclear@0: struct vr_module *m = vr_get_active_module(idx); nuclear@0: if(!m) { nuclear@0: return 0; nuclear@0: } nuclear@0: return m->name; nuclear@0: } nuclear@0: nuclear@0: int vr_use_module(int idx) nuclear@0: { nuclear@0: if(idx >= 0 && idx < vr_get_num_active_modules()) { nuclear@0: struct vr_module *m = vr_get_active_module(idx); nuclear@0: if(m != vrm) { nuclear@0: vrm = m; nuclear@0: printf("using vr module: %s\n", vrm->name); nuclear@0: } nuclear@0: return 0; nuclear@0: } nuclear@0: return -1; nuclear@0: } nuclear@0: nuclear@0: int vr_use_module_named(const char *name) nuclear@0: { nuclear@0: int i, count = vr_get_num_active_modules(); nuclear@0: nuclear@0: for(i=0; iname, name) == 0) { nuclear@0: return vr_use_module(i); nuclear@0: } nuclear@0: } nuclear@0: return -1; nuclear@0: } nuclear@0: nuclear@11: void vr_seti(const char *optname, int val) nuclear@0: { nuclear@0: if(vrm && vrm->set_option) { nuclear@0: vrm->set_option(optname, OTYPE_INT, &val); nuclear@5: } else { nuclear@5: set_option_int(defopt, optname, val); nuclear@0: } nuclear@0: } nuclear@0: nuclear@11: void vr_setf(const char *optname, float val) nuclear@0: { nuclear@0: if(vrm && vrm->set_option) { nuclear@0: vrm->set_option(optname, OTYPE_FLOAT, &val); nuclear@5: } else { nuclear@5: set_option_float(defopt, optname, val); nuclear@0: } nuclear@0: } nuclear@0: nuclear@16: static int def_option_int(const char *optname) nuclear@16: { nuclear@16: int res = 0; nuclear@16: int left, right; nuclear@16: nuclear@16: if(strcmp(optname, VR_RENDER_XRES) == 0) { nuclear@16: if(vrm && vrm->get_option && vrm->get_option(optname, OTYPE_INT, &left) != -1 && nuclear@16: vrm->get_option(optname, OTYPE_INT, &right) != -1) { nuclear@16: return left + right; nuclear@16: } nuclear@16: } else if(strcmp(optname, VR_RENDER_YRES) == 0) { nuclear@16: if(vrm && vrm->get_option && vrm->get_option(optname, OTYPE_INT, &left) != -1 && nuclear@16: vrm->get_option(optname, OTYPE_INT, &right) != -1) { nuclear@16: return left > right ? left : right; nuclear@16: } nuclear@16: } nuclear@16: nuclear@16: get_option_int(defopt, optname, &res); nuclear@16: return res; nuclear@16: } nuclear@16: nuclear@16: static float def_option_float(const char *optname) nuclear@16: { nuclear@18: float res = 0.0f; nuclear@16: nuclear@16: if(strcmp(optname, VR_RENDER_XRES) == 0 || strcmp(optname, VR_RENDER_YRES) == 0) { nuclear@16: return (float)def_option_int(optname); nuclear@16: } nuclear@16: nuclear@16: get_option_float(defopt, optname, &res); nuclear@16: return res; nuclear@16: } nuclear@16: nuclear@19: static float *def_option_vec(const char *optname, float *res) nuclear@19: { nuclear@19: res[0] = res[1] = res[2] = res[3] = 0.0f; nuclear@19: nuclear@19: get_option_vec(defopt, optname, res); nuclear@19: return res; nuclear@19: } nuclear@19: nuclear@11: int vr_geti(const char *optname) nuclear@0: { nuclear@0: int res = 0; nuclear@0: nuclear@5: if(!vrm || !vrm->get_option || vrm->get_option(optname, OTYPE_INT, &res) == -1) { nuclear@16: res = def_option_int(optname); nuclear@0: } nuclear@0: return res; nuclear@0: } nuclear@0: nuclear@11: float vr_getf(const char *optname) nuclear@0: { nuclear@0: float res = 0.0f; nuclear@0: nuclear@5: if(!vrm || !vrm->get_option || vrm->get_option(optname, OTYPE_FLOAT, &res) == -1) { nuclear@16: res = def_option_float(optname); nuclear@0: } nuclear@0: return res; nuclear@0: } nuclear@0: nuclear@19: float *vr_getfv(const char *optname, float *res) nuclear@19: { nuclear@19: static float sres[4]; nuclear@19: if(!res) res = sres; nuclear@19: nuclear@19: if(!vrm || !vrm->get_option || vrm->get_option(optname, OTYPE_VEC, res) == -1) { nuclear@19: def_option_vec(optname, res); nuclear@19: } nuclear@19: return res; nuclear@19: } nuclear@19: nuclear@12: int vr_geti_def(const char *optname, int def_val) nuclear@12: { nuclear@12: int res = 0; nuclear@12: nuclear@12: if(!vrm || !vrm->get_option || vrm->get_option(optname, OTYPE_INT, &res) == -1) { nuclear@12: if(get_option_int(defopt, optname, &res) == -1) { /* fallback */ nuclear@12: return def_val; nuclear@12: } nuclear@12: } nuclear@12: return res; nuclear@12: } nuclear@12: nuclear@12: float vr_getf_def(const char *optname, float def_val) nuclear@12: { nuclear@12: float res = 0.0f; nuclear@12: nuclear@12: if(!vrm || !vrm->get_option || vrm->get_option(optname, OTYPE_FLOAT, &res) == -1) { nuclear@12: if(get_option_float(defopt, optname, &res) == -1) { /* fallback */ nuclear@12: return def_val; nuclear@12: } nuclear@12: } nuclear@12: return res; nuclear@12: } nuclear@0: nuclear@0: int vr_view_translation(int eye, float *vec) nuclear@0: { nuclear@0: if(vrm && vrm->translation) { nuclear@0: vrm->translation(eye, vec); nuclear@0: return 1; nuclear@0: } nuclear@19: vec[0] = vec[1] = vec[2] = 0.0f; nuclear@19: return 0; nuclear@0: } nuclear@0: nuclear@0: int vr_view_rotation(int eye, float *quat) nuclear@0: { nuclear@0: if(vrm && vrm->rotation) { nuclear@0: vrm->rotation(eye, quat); nuclear@0: return 1; nuclear@0: } nuclear@0: quat[0] = quat[1] = quat[2] = 0.0f; nuclear@0: quat[3] = 1.0f; nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@0: int vr_view_matrix(int eye, float *mat) nuclear@0: { nuclear@19: float offs[3], quat[4], eye_offs[4]; nuclear@19: float rmat[16] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; nuclear@19: float tmat[16] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; nuclear@0: nuclear@0: if(vrm && vrm->view_matrix) { nuclear@0: vrm->view_matrix(eye, mat); nuclear@0: return 1; nuclear@0: } nuclear@0: nuclear@19: memcpy(mat, idmat, sizeof idmat); nuclear@19: nuclear@19: if(vr_view_translation(eye, offs)) { nuclear@19: offs[0] = -offs[0]; nuclear@19: offs[1] = -offs[1]; nuclear@19: offs[2] = -offs[2]; nuclear@19: nuclear@19: vrimp_translation_matrix(offs, tmat); nuclear@19: vrimp_mult_matrix(mat, mat, tmat); nuclear@18: } nuclear@19: if(vr_view_rotation(eye, quat)) { nuclear@19: vrimp_rotation_matrix(quat, rmat); nuclear@19: vrimp_mult_matrix(mat, mat, rmat); nuclear@0: } nuclear@0: nuclear@19: vr_getfv(eye == VR_EYE_LEFT ? VR_LEYE_OFFSET : VR_REYE_OFFSET, eye_offs); nuclear@19: eye_offs[0] = -eye_offs[0]; nuclear@19: eye_offs[1] = -eye_offs[1]; nuclear@19: eye_offs[2] = -eye_offs[2]; nuclear@19: vrimp_translation_matrix(eye_offs, tmat); nuclear@19: vrimp_mult_matrix(mat, mat, tmat); nuclear@0: return 1; nuclear@0: } nuclear@0: nuclear@0: int vr_proj_matrix(int eye, float znear, float zfar, float *mat) nuclear@0: { nuclear@0: if(vrm && vrm->proj_matrix) { nuclear@0: vrm->proj_matrix(eye, znear, zfar, mat); nuclear@0: return 1; nuclear@0: } nuclear@0: memcpy(mat, idmat, sizeof idmat); nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@0: void vr_begin(int eye) nuclear@0: { nuclear@0: if(vrm && vrm->begin) { nuclear@0: vrm->begin(eye); nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: void vr_end(void) nuclear@0: { nuclear@0: if(vrm && vrm->end) { nuclear@0: vrm->end(); nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: int vr_swap_buffers(void) nuclear@0: { nuclear@0: int res = 0; nuclear@0: nuclear@0: if(vrm && vrm->present) { nuclear@0: res = vrm->present(); nuclear@0: } nuclear@0: nuclear@0: if(!res) { nuclear@5: fallback_present(); nuclear@8: vrimp_swap_buffers(); nuclear@0: } nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@0: void vr_output_texture(unsigned int tex, float umin, float vmin, float umax, float vmax) nuclear@0: { nuclear@0: float halfu = (umax + umin) * 0.5f; nuclear@0: nuclear@0: vr_output_texture_eye(VR_EYE_LEFT, tex, umin, vmin, halfu, vmax); nuclear@0: vr_output_texture_eye(VR_EYE_RIGHT, tex, halfu, vmin, umax, vmax); nuclear@0: } nuclear@0: nuclear@0: void vr_output_texture_eye(int eye, unsigned int tex, float umin, float vmin, float umax, float vmax) nuclear@0: { nuclear@0: if(vrm && vrm->set_eye_texture) { nuclear@0: vrm->set_eye_texture(eye, tex, umin, vmin, umax, vmax); nuclear@5: } else { nuclear@5: rtarg[eye].tex = tex; nuclear@5: rtarg[eye].umin = umin; nuclear@5: rtarg[eye].umax = umax; nuclear@5: rtarg[eye].vmin = vmin; nuclear@5: rtarg[eye].vmax = vmax; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: void vr_recenter(void) nuclear@0: { nuclear@0: if(vrm && vrm->recenter) { nuclear@0: vrm->recenter(); nuclear@0: } nuclear@0: } nuclear@0: nuclear@5: static void fallback_present(void) nuclear@5: { nuclear@32: int i, show_sbs = vr_geti(VR_NULL_STEREO_SBS); nuclear@32: int use_quadbuf = vr_geti(VR_NULL_STEREO_GL); nuclear@33: int use_redcyan = vr_geti(VR_NULL_STEREO_REDCYAN); nuclear@0: nuclear@5: glPushAttrib(GL_ENABLE_BIT | GL_TRANSFORM_BIT); nuclear@0: nuclear@5: glDisable(GL_LIGHTING); nuclear@5: glDisable(GL_DEPTH_TEST); nuclear@5: glDisable(GL_ALPHA_TEST); nuclear@5: glDisable(GL_STENCIL_TEST); nuclear@5: glDisable(GL_FOG); nuclear@33: glDisable(GL_BLEND); nuclear@5: nuclear@5: glEnable(GL_TEXTURE_2D); nuclear@5: nuclear@5: glMatrixMode(GL_MODELVIEW); nuclear@5: glPushMatrix(); nuclear@5: glLoadIdentity(); nuclear@5: glMatrixMode(GL_PROJECTION); nuclear@5: glPushMatrix(); nuclear@5: glLoadIdentity(); nuclear@5: nuclear@33: glClear(GL_COLOR_BUFFER_BIT); nuclear@33: nuclear@5: for(i=0; i<2; i++) { nuclear@17: float x0, x1; nuclear@17: nuclear@33: if(show_sbs && !use_quadbuf && !use_redcyan) { nuclear@17: x0 = i == 0 ? -1 : 0; nuclear@17: x1 = i == 0 ? 0 : 1; nuclear@17: } else { nuclear@17: x0 = -1; nuclear@17: x1 = 1; nuclear@17: } nuclear@5: nuclear@5: glBindTexture(GL_TEXTURE_2D, rtarg[i].tex); nuclear@5: nuclear@32: if(use_quadbuf) { nuclear@32: glDrawBuffer(GL_BACK_LEFT + i); nuclear@32: } nuclear@32: nuclear@33: if(use_redcyan) { nuclear@33: if(i == 0) { nuclear@33: glColorMask(1, 0, 0, 1); nuclear@33: } else { nuclear@33: glColorMask(0, 1, 1, 1); nuclear@33: nuclear@33: glEnable(GL_BLEND); nuclear@33: glBlendFunc(GL_ONE, GL_ONE); nuclear@33: } nuclear@33: } nuclear@33: nuclear@5: glBegin(GL_QUADS); nuclear@5: glTexCoord2f(rtarg[i].umin, rtarg[i].vmin); nuclear@5: glVertex2f(x0, -1); nuclear@5: glTexCoord2f(rtarg[i].umax, rtarg[i].vmin); nuclear@5: glVertex2f(x1, -1); nuclear@5: glTexCoord2f(rtarg[i].umax, rtarg[i].vmax); nuclear@5: glVertex2f(x1, 1); nuclear@5: glTexCoord2f(rtarg[i].umin, rtarg[i].vmax); nuclear@5: glVertex2f(x0, 1); nuclear@5: glEnd(); nuclear@17: nuclear@33: if(!show_sbs && !use_quadbuf && !use_redcyan) break; nuclear@32: } nuclear@32: nuclear@32: if(use_quadbuf) { nuclear@32: glDrawBuffer(GL_BACK); nuclear@5: } nuclear@33: if(use_redcyan) { nuclear@33: glColorMask(1, 1, 1, 1); nuclear@33: } nuclear@5: nuclear@5: glPopMatrix(); nuclear@5: glMatrixMode(GL_MODELVIEW); nuclear@5: glPopMatrix(); nuclear@5: nuclear@5: glPopAttrib(); nuclear@0: }