nuclear@0: #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@0: nuclear@5: /* create the default options database */ nuclear@5: if(!defopt && (defopt = create_options())) { nuclear@5: set_option_float(defopt, VR_OPT_EYE_HEIGHT, 1.675); nuclear@5: set_option_float(defopt, VR_OPT_IPD, 0.064); 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: if(!vrm) { nuclear@0: vr_use_module(0); nuclear@0: } nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: if(!vrm) { nuclear@0: return -1; nuclear@0: } 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@0: void vr_set_opti(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@0: void vr_set_optf(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@0: int vr_get_opti(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@5: get_option_int(defopt, optname, &res); /* fallback */ nuclear@0: } nuclear@0: return res; nuclear@0: } nuclear@0: nuclear@0: float vr_get_optf(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@5: get_option_float(defopt, optname, &res); /* fallback */ nuclear@0: } nuclear@0: return res; nuclear@0: } nuclear@0: 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@0: vec[0] = vec[1] = vec[2] = 0.0f; nuclear@0: 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@0: int have_trans, have_rot; 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@0: have_trans = vr_view_translation(eye, offs); nuclear@0: have_rot = vr_view_rotation(eye, quat); nuclear@0: nuclear@0: if(!have_trans && !have_rot) { nuclear@5: memcpy(mat, idmat, sizeof idmat); nuclear@0: return 0; 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@0: translation_matrix(offs, tmat); nuclear@0: rotation_matrix(quat, rmat); nuclear@0: 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@5: vr_gl_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@5: int i; 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@5: float x0 = i == 0 ? -1 : 0; nuclear@5: float x1 = i == 0 ? 0 : 1; 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@5: } nuclear@5: nuclear@5: glPopMatrix(); nuclear@5: glMatrixMode(GL_MODELVIEW); nuclear@5: glPopMatrix(); nuclear@5: nuclear@5: glPopAttrib(); nuclear@0: }