nuclear@2: #include nuclear@2: #include nuclear@2: #include nuclear@2: #include "opengl.h" nuclear@2: #include "game.h" nuclear@2: #include "goatvr.h" nuclear@3: #include "teapot.h" nuclear@2: nuclear@2: static void draw_scene(); nuclear@2: static void toggle_hmd_fullscr(); nuclear@2: static void create_rtarg(int x, int y); nuclear@2: static int next_pow2(int x); nuclear@2: nuclear@2: static int win_width, win_height; nuclear@2: static unsigned int fb_tex; nuclear@2: static unsigned int fbo, fb_depth; nuclear@2: static int fb_xsz, fb_ysz; nuclear@2: static int fb_tex_xsz, fb_tex_ysz; nuclear@2: nuclear@2: bool game_init() nuclear@2: { nuclear@2: init_opengl(); nuclear@2: nuclear@2: if(vr_init() == -1) { nuclear@2: return false; nuclear@2: } nuclear@2: nuclear@2: glEnable(GL_DEPTH_TEST); nuclear@2: glEnable(GL_CULL_FACE); nuclear@3: glEnable(GL_LIGHTING); nuclear@2: nuclear@2: return true; nuclear@2: } nuclear@2: nuclear@2: void game_cleanup() nuclear@2: { nuclear@2: vr_shutdown(); nuclear@2: } nuclear@2: nuclear@2: void game_update(long tm) nuclear@2: { nuclear@2: } nuclear@2: nuclear@2: void game_display() nuclear@2: { nuclear@2: glBindFramebuffer(GL_FRAMEBUFFER, fbo); nuclear@2: glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); nuclear@2: nuclear@2: for(int i=0; i<2; i++) { nuclear@2: glViewport(i == 0 ? 0 : fb_xsz / 2, 0, fb_xsz / 2, fb_ysz); nuclear@2: vr_begin(i); nuclear@2: nuclear@2: float proj[16]; nuclear@2: if(vr_proj_matrix(i, 0.5, 500.0, proj)) { nuclear@2: glMatrixMode(GL_PROJECTION); nuclear@2: glLoadMatrixf(proj); nuclear@2: } nuclear@2: nuclear@2: glMatrixMode(GL_MODELVIEW); nuclear@2: nuclear@2: float view[16]; nuclear@2: vr_view_matrix(i, view); nuclear@2: glLoadMatrixf(view); nuclear@2: /* move the camera to the eye level of the user */ nuclear@2: glTranslatef(0, -vr_getf_def(VR_EYE_HEIGHT, 1.65), 0); nuclear@2: nuclear@2: draw_scene(); nuclear@2: nuclear@2: vr_end(); nuclear@2: } nuclear@2: nuclear@2: glBindFramebuffer(GL_FRAMEBUFFER, 0); nuclear@2: glViewport(0, 0, win_width, win_height); nuclear@2: nuclear@2: vr_swap_buffers(); nuclear@2: assert(glGetError() == GL_NO_ERROR); nuclear@2: } nuclear@2: nuclear@2: void game_reshape(int x, int y) nuclear@2: { nuclear@2: win_width = x; nuclear@2: win_height = y; nuclear@2: nuclear@2: create_rtarg(vr_geti_def(VR_RENDER_XRES, x), vr_geti_def(VR_RENDER_YRES, y)); nuclear@2: vr_output_texture(fb_tex, 0, 0, (float)fb_xsz / (float)fb_tex_xsz, (float)fb_ysz / (float)fb_tex_ysz); nuclear@2: nuclear@2: /* these might be overriden in VR mode (see game_display) */ nuclear@2: glViewport(0, 0, x, y); nuclear@2: glMatrixMode(GL_PROJECTION); nuclear@2: glLoadIdentity(); nuclear@2: gluPerspective(50.0, (float)x / (float)y, 0.5, 500.0); nuclear@2: } nuclear@2: nuclear@2: void game_keyboard(int key, bool pressed) nuclear@2: { nuclear@2: if(pressed) { nuclear@2: switch(key) { nuclear@2: case 27: nuclear@2: exit_game(); nuclear@2: break; nuclear@2: nuclear@2: case 'f': nuclear@2: toggle_hmd_fullscr(); nuclear@2: break; nuclear@2: nuclear@2: case 'r': nuclear@2: vr_recenter(); nuclear@2: break; nuclear@2: nuclear@2: default: nuclear@2: break; nuclear@2: } nuclear@2: } nuclear@2: } nuclear@2: nuclear@2: void game_mouse_button(int bn, bool state, int x, int y) nuclear@2: { nuclear@2: } nuclear@2: nuclear@2: void game_mouse_motion(int x, int y) nuclear@2: { nuclear@2: } nuclear@2: nuclear@3: static void material(float r, float g, float b, float roughness) nuclear@3: { nuclear@3: float gloss = 1.0 - roughness; nuclear@3: float diffuse[] = {r * roughness, g * roughness, b * roughness, 1.0}; nuclear@3: float specular[] = {gloss, gloss, gloss, 1.0}; nuclear@3: float shin = gloss * 128.0; nuclear@3: nuclear@3: glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, diffuse); nuclear@3: glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular); nuclear@3: glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shin); nuclear@3: } nuclear@3: nuclear@2: static void draw_scene() nuclear@2: { nuclear@3: float lpos[][4] = { nuclear@3: {-0.7, 0.7, 1, 0}, nuclear@3: {1, 0, 1, 0} nuclear@3: }; nuclear@3: float lcol[][4] = { nuclear@3: {0.9, 0.7, 0.6, 1}, nuclear@3: {0.3, 0.4, 0.75, 1} nuclear@3: }; nuclear@3: for(int i=0; i<2; i++) { nuclear@3: glEnable(GL_LIGHT0 + i); nuclear@3: glLightfv(GL_LIGHT0 + i, GL_POSITION, lpos[i]); nuclear@3: glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, lcol[i]); nuclear@3: glLightfv(GL_LIGHT0 + i, GL_SPECULAR, lcol[i]); nuclear@3: } nuclear@3: nuclear@3: glMatrixMode(GL_MODELVIEW); nuclear@3: nuclear@3: material(1, 1, 1, 1); nuclear@3: glBegin(GL_QUADS); nuclear@3: glNormal3f(0, 1, 0); nuclear@3: glVertex3f(-10, 0, 10); nuclear@3: glVertex3f(10, 0, 10); nuclear@3: glVertex3f(10, 0, -10); nuclear@3: glVertex3f(-10, 0, -10); nuclear@3: glEnd(); nuclear@3: nuclear@3: material(1, 1, 1, 0.4); nuclear@3: glPushMatrix(); nuclear@3: glTranslatef(0, 1.3, -10); nuclear@3: glFrontFace(GL_CW); nuclear@3: bezier_teapot(2.0); nuclear@3: glFrontFace(GL_CCW); nuclear@3: glPopMatrix(); nuclear@2: } nuclear@2: nuclear@2: static void toggle_hmd_fullscr() nuclear@2: { nuclear@2: static bool fullscr; nuclear@2: static int prev_x, prev_y; nuclear@2: //static int prev_xsz, prev_ysz; nuclear@2: nuclear@2: fullscr = !fullscr; nuclear@2: if(fullscr) { nuclear@2: /* entering fullscreen on the HMD */ nuclear@2: int xoffs = vr_geti_def(VR_WIN_XOFFS, -1); nuclear@2: int yoffs = vr_geti_def(VR_WIN_YOFFS, -1); nuclear@2: if(xoffs != -1) { nuclear@2: get_window_pos(&prev_x, &prev_y); nuclear@2: move_window(xoffs, yoffs); nuclear@2: } nuclear@2: nuclear@2: int xsz = vr_geti_def(VR_DISPLAY_WIDTH, -1); nuclear@2: int ysz = vr_geti_def(VR_DISPLAY_HEIGHT, -1); nuclear@2: if(xsz != -1) { nuclear@2: //prev_xsz = win_width; nuclear@2: //prev_ysz = win_height; nuclear@2: resize_window(xsz, ysz); nuclear@2: } nuclear@2: enter_fullscreen(); nuclear@2: nuclear@2: } else { nuclear@2: /* leaving fullscreen */ nuclear@2: leave_fullscreen(); nuclear@2: /*move_window(prev_x, prev_y); nuclear@2: resize_window(prev_xsz, prev_ysz);*/ nuclear@2: } nuclear@2: } nuclear@2: nuclear@2: static void create_rtarg(int x, int y) nuclear@2: { nuclear@2: if(x == fb_xsz && y == fb_ysz) { nuclear@2: return; // nothing changed nuclear@2: } nuclear@2: nuclear@2: fb_xsz = x; nuclear@2: fb_ysz = y; nuclear@2: fb_tex_xsz = next_pow2(fb_xsz); nuclear@2: fb_tex_ysz = next_pow2(fb_ysz); nuclear@2: nuclear@2: if(!fbo) { nuclear@2: glGenFramebuffers(1, &fbo); nuclear@2: nuclear@2: glGenTextures(1, &fb_tex); nuclear@2: glBindTexture(GL_TEXTURE_2D, fb_tex); nuclear@2: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); nuclear@2: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); nuclear@2: nuclear@2: glGenRenderbuffers(1, &fb_depth); nuclear@2: } nuclear@2: nuclear@2: glBindFramebuffer(GL_FRAMEBUFFER, fbo); nuclear@2: nuclear@2: glBindTexture(GL_TEXTURE_2D, fb_tex); nuclear@2: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, fb_tex_xsz, fb_tex_ysz, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); nuclear@2: glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb_tex, 0); nuclear@2: nuclear@2: glBindRenderbuffer(GL_RENDERBUFFER, fb_depth); nuclear@2: glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, fb_tex_xsz, fb_tex_ysz); nuclear@2: glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fb_depth); nuclear@2: nuclear@2: assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); nuclear@2: glBindFramebuffer(GL_FRAMEBUFFER, 0); nuclear@2: } nuclear@2: nuclear@2: static int next_pow2(int x) nuclear@2: { nuclear@2: x -= 1; nuclear@2: x |= x >> 1; nuclear@2: x |= x >> 2; nuclear@2: x |= x >> 4; nuclear@2: x |= x >> 8; nuclear@2: x |= x >> 16; nuclear@2: return x + 1; nuclear@2: }