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@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@7: char *vrmod_env; nuclear@0: nuclear@5: /* create the default options database */ nuclear@5: if(!defopt && (defopt = create_options())) { nuclear@16: set_option_float(defopt, VR_RENDER_RES_SCALE, 1.0); nuclear@11: set_option_float(defopt, VR_EYE_HEIGHT, 1.675); nuclear@11: set_option_float(defopt, VR_IPD, 0.064); nuclear@17: set_option_int(defopt, VR_NULL_STEREO, 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@7: if((vrmod_env = getenv("VR_MODULE"))) { nuclear@7: vr_use_module_named(vrmod_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@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@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@18: float eye_offset; nuclear@18: nuclear@0: if(vrm && vrm->translation) { nuclear@0: vrm->translation(eye, vec); nuclear@0: return 1; nuclear@0: } nuclear@18: nuclear@18: eye_offset = vr_getf(VR_IPD) / 2.0; nuclear@18: vec[0] = eye == VR_EYE_LEFT ? -eye_offset : eye_offset; nuclear@18: vec[1] = vec[2] = 0.0f; nuclear@18: return 1; 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@0: float offs[3], quat[4]; nuclear@0: float rmat[16], tmat[16]; 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@18: if(!vr_view_translation(eye, offs)) { nuclear@18: float eye_offset = vr_getf(VR_IPD) / 2.0; nuclear@18: offs[0] = eye == VR_EYE_LEFT ? -eye_offset : eye_offset; nuclear@18: offs[1] = offs[2]; nuclear@18: } nuclear@18: if(!vr_view_rotation(eye, quat)) { nuclear@18: quat[0] = quat[1] = quat[2] = 0.0f; nuclear@18: quat[3] = 1.0f; nuclear@0: } nuclear@0: nuclear@0: offs[0] = -offs[0]; nuclear@0: offs[1] = -offs[1]; nuclear@0: offs[2] = -offs[2]; nuclear@0: nuclear@8: vrimp_translation_matrix(offs, tmat); nuclear@8: vrimp_rotation_matrix(quat, rmat); nuclear@8: vrimp_mult_matrix(mat, tmat, rmat); 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@17: int i, show_both = vr_geti(VR_NULL_STEREO); 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@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@5: for(i=0; i<2; i++) { nuclear@17: float x0, x1; nuclear@17: nuclear@17: if(show_both) { 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@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@17: if(!show_both) break; nuclear@5: } nuclear@5: nuclear@5: glPopMatrix(); nuclear@5: glMatrixMode(GL_MODELVIEW); nuclear@5: glPopMatrix(); nuclear@5: nuclear@5: glPopAttrib(); nuclear@0: }