/* * OpenHMD - Free and Open Source API and drivers for immersive technology. * Copyright (C) 2013 Fredrik Hultin. * Copyright (C) 2013 Jakob Bornecrantz. * Distributed under the Boost 1.0 licence, see LICENSE for full text. */ /* OpenGL Test - Main Implementation */ #include #include #include #include #include "gl.h" #include #include #include #define OVERSAMPLE_SCALE 2.0 float randf() { return (float)rand() / (float)RAND_MAX; } GLuint gen_cubes() { GLuint list = glGenLists(1); // Set the random seed. srand(42); glNewList(list, GL_COMPILE); for (float a = 0.0f; a < 360.0f; a += 20.0f) { glPushMatrix(); glRotatef(a, 0, 1, 0); glTranslatef(0, 0, -1); glScalef(0.2, 0.2, 0.2); glRotatef(randf() * 360, randf(), randf(), randf()); glColor4f(randf(), randf(), randf(), randf() * .5f + .5f); draw_cube(); glPopMatrix(); } // draw floor glColor4f(0, 1.0f, .25f, .25f); glTranslatef(0, -2.5f, 0); draw_cube(); glEndList(); return list; } void draw_scene(GLuint list) { // draw cubes glCallList(list); } int main(int argc, char** argv) { ohmd_context * ctx = ohmd_ctx_create(); int num_devices = ohmd_ctx_probe(ctx); if (num_devices < 0) { printf("failed to probe devices: %s\n", ohmd_ctx_get_error(ctx)); return 1; } ohmd_device_settings * settings = ohmd_device_settings_create(ctx); // If OHMD_IDS_AUTOMATIC_UPDATE is set to 0, ohmd_ctx_update() must be called at least 10 times per second. // It is enabled by default. int auto_update = 1; ohmd_device_settings_seti(settings, OHMD_IDS_AUTOMATIC_UPDATE, &auto_update); ohmd_device * hmd = ohmd_list_open_device_s(ctx, 0, settings); if (!hmd) { printf("failed to open device: %s\n", ohmd_ctx_get_error(ctx)); return 1; } int hmd_w = 0; int hmd_h = 0; ohmd_device_geti(hmd, OHMD_SCREEN_HORIZONTAL_RESOLUTION, &hmd_w); ohmd_device_geti(hmd, OHMD_SCREEN_VERTICAL_RESOLUTION, &hmd_h); ohmd_device_settings_destroy(settings); struct lvrcInstance * compositor = lvrcCreateInstance(hmd); if (!compositor) { return -1; } const int window_w = hmd_w/2; const int window_h = hmd_h; gl_ctx gl; init_gl(&gl, window_w, window_h); GLuint list = gen_cubes(); bool bCompositorInit = lvrcInitRenderingEGL(compositor, gl.egl_display, gl.egl_context, gl.egl_surface); if (!bCompositorInit) { printf ("Could not create compositor\n"); return -1; } int eye_w = hmd_w/2*OVERSAMPLE_SCALE; int eye_h = hmd_h*OVERSAMPLE_SCALE; GLuint textures [2]; bool bSwapChainInit = lvrcInitSwapChain(compositor, eye_w, eye_h, textures); if (!bSwapChainInit) { printf ("Could not create swapchain\n"); return -1; } GLuint left_color_tex = textures[0], left_depth_tex = 0, left_fbo = 0; create_fbo(eye_w, eye_h, &left_fbo, left_color_tex, &left_depth_tex); GLuint right_color_tex = textures[1], right_depth_tex = 0, right_fbo = 0; create_fbo(eye_w, eye_h, &right_fbo, right_color_tex, &right_depth_tex); bool done = false; while (!done) { ohmd_ctx_update(ctx); lvrcBeginFrame(compositor); eglMakeCurrent(gl.egl_display, gl.egl_surface, gl.egl_surface, gl.egl_context); // Common scene state glEnable(GL_BLEND); glEnable(GL_DEPTH_TEST); float matrix[16]; // set hmd rotation, for left eye. glMatrixMode(GL_PROJECTION); ohmd_device_getf(hmd, OHMD_LEFT_EYE_GL_PROJECTION_MATRIX, matrix); glLoadMatrixf(matrix); glMatrixMode(GL_MODELVIEW); ohmd_device_getf(hmd, OHMD_LEFT_EYE_GL_MODELVIEW_MATRIX, matrix); glLoadMatrixf(matrix); // Draw scene into framebuffer. glBindFramebuffer(GL_FRAMEBUFFER_EXT, left_fbo); glViewport(0, 0, eye_w, eye_h); glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); draw_scene(list); // set hmd rotation, for right eye. glMatrixMode(GL_PROJECTION); ohmd_device_getf(hmd, OHMD_RIGHT_EYE_GL_PROJECTION_MATRIX, matrix); glLoadMatrixf(matrix); glMatrixMode(GL_MODELVIEW); ohmd_device_getf(hmd, OHMD_RIGHT_EYE_GL_MODELVIEW_MATRIX, matrix); glLoadMatrixf(matrix); // Draw scene into framebuffer. glBindFramebuffer(GL_FRAMEBUFFER_EXT, right_fbo); glViewport(0, 0, eye_w, eye_h); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); draw_scene(list); // Clean up common draw state glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); glDisable(GL_BLEND); glDisable(GL_DEPTH_TEST); // Setup ortho state. glViewport(0, 0, window_w, window_h); glEnable(GL_TEXTURE_2D); glColor4d(1, 1, 1, 1); // Setup simple render state glMatrixMode(GL_PROJECTION); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // Draw left eye glBindTexture(GL_TEXTURE_2D, left_color_tex); glBegin(GL_QUADS); glTexCoord2d( 0, 0); glVertex3d( -1, -1, 1); glTexCoord2d( 1, 0); glVertex3d( 1, -1, 1); glTexCoord2d( 1, 1); glVertex3d( 1, 1, 1); glTexCoord2d( 0, 1); glVertex3d( -1, 1, 1); glEnd(); // Clean up state. glBindTexture(GL_TEXTURE_2D, 0); glDisable(GL_TEXTURE_2D); glUseProgram(0); // Da swap-dawup! eglSwapBuffers(gl.egl_display, gl.egl_surface); lvrcEndFrame(compositor); } lvrcDestroyInstance(compositor); ohmd_ctx_destroy(ctx); return 0; }