From 5b6b28664f2a56c9e2e6ee41e0da67bac94d3d43 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 1 May 2013 18:22:45 -0700 Subject: [PATCH 1/7] Most of the way towards basic Oculus support. --- interface/src/main.cpp | 386 ++++++++++++++++++++++++++++------------- 1 file changed, 263 insertions(+), 123 deletions(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index c68c6aee9c..13a7768210 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -174,7 +174,9 @@ int menuOn = 1; // Whether to show onscreen menu ChatEntry chatEntry; // chat entry field bool chatEntryOn = false; // Whether to show the chat entry - +bool oculusOn = false; // Whether to configure the display for the Oculus Rift +GLuint oculusTextureID = 0; // The texture to which we render for Oculus distortion +GLuint oculusProgramID = 0; // The GLSL program containing the distortion shader // // Serial USB Variables @@ -688,6 +690,252 @@ void renderViewFrustum(ViewFrustum& viewFrustum) { glEnable(GL_LIGHTING); } +// displays a single side (left, right, or combined for non-Oculus) +void displaySide(Camera& whichCamera) { + glPushMatrix(); + + if (::starsOn) { + // should be the first rendering pass - w/o depth buffer / lighting + + // finally render the starfield + stars.render(whichCamera.getFieldOfView(), aspectRatio, whichCamera.getNearClip()); + } + + glEnable(GL_LIGHTING); + glEnable(GL_DEPTH_TEST); + + // draw a red sphere + float sphereRadius = 0.25f; + glColor3f(1,0,0); + glPushMatrix(); + glutSolidSphere( sphereRadius, 15, 15 ); + glPopMatrix(); + + //draw a grid ground plane.... + drawGroundPlaneGrid( 5.0f, 9 ); + + // Draw voxels + if ( showingVoxels ) + { + voxels.render(); + } + + // Render avatars of other agents + AgentList* agentList = AgentList::getInstance(); + agentList->lock(); + for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) { + if (agent->getLinkedData() != NULL && agent->getType() == AGENT_TYPE_AVATAR) { + Avatar *avatar = (Avatar *)agent->getLinkedData(); + avatar->render(0); + } + } + agentList->unlock(); + + // Render the world box + if (!::lookingInMirror && ::statsOn) { render_world_box(); } + + // brad's frustum for debugging + if (::frustumOn) renderViewFrustum(::viewFrustum); + + //Render my own avatar + myAvatar.render(::lookingInMirror); + + glPopMatrix(); +} + +const char* DISTORTION_FRAGMENT_SHADER = + "#version 120\n" + "uniform sampler2D texture;" + "uniform vec2 lensCenter;" + "uniform vec2 screenCenter;" + "uniform vec2 scale;" + "uniform vec2 scaleIn;" + "uniform vec4 hmdWarpParam;" + "vec2 hmdWarp(vec2 in01) {" + " vec2 theta = (in01 - lensCenter) * scaleIn;" + " float rSq = theta.x * theta.x + theta.y * theta.y;" + " vec2 theta1 = theta * (hmdWarpParam.x + hmdWarpParam.y * rSq + " + " hmdWarpParam.z * rSq * rSq + hmdWarpParam.w * rSq * rSq * rSq);" + " return lensCenter + scale * theta1;" + "}" + "void main(void) {" + " vec2 tc = hmdWarp(gl_TexCoord[0].st);" + " vec2 below = step(screenCenter.st + vec2(-0.25, -0.5), tc.st);" + " vec2 above = vec2(1.0, 1.0) - step(screenCenter.st + vec2(0.25, 0.5), tc.st);" + " gl_FragColor = mix(vec4(0.0, 0.0, 0.0, 1.0), texture2D(texture, tc), " + " above.s * above.t * below.s * below.t);" + "}"; + +int textureLocation; +int lensCenterLocation; +int screenCenterLocation; +int scaleLocation; +int scaleInLocation; +int hmdWarpParamLocation; + +// renders both sides into a texture, then renders the texture to the display with distortion +void displayOculus(Camera& whichCamera) { + // render the left eye view to the left side of the screen + glViewport(0, 0, WIDTH/2, HEIGHT); + displaySide(whichCamera); + + // and the right eye to the right side + glViewport(WIDTH/2, 0, WIDTH/2, HEIGHT); + displaySide(whichCamera); + + // restore our normal viewport + glViewport(0, 0, WIDTH, HEIGHT); + + if (::oculusTextureID == 0) { + glGenTextures(1, &::oculusTextureID); + glBindTexture(GL_TEXTURE_2D, ::oculusTextureID); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, WIDTH, HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + GLuint shaderID = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); + glShaderSourceARB(shaderID, 1, &DISTORTION_FRAGMENT_SHADER, 0); + glCompileShaderARB(shaderID); + ::oculusProgramID = glCreateProgramObjectARB(); + glAttachObjectARB(::oculusProgramID, shaderID); + glLinkProgramARB(::oculusProgramID); + textureLocation = glGetUniformLocationARB(::oculusProgramID, "texture"); + lensCenterLocation = glGetUniformLocationARB(::oculusProgramID, "lensCenter"); + screenCenterLocation = glGetUniformLocationARB(::oculusProgramID, "screenCenter"); + scaleLocation = glGetUniformLocationARB(::oculusProgramID, "scale"); + scaleInLocation = glGetUniformLocationARB(::oculusProgramID, "scaleIn"); + hmdWarpParamLocation = glGetUniformLocationARB(::oculusProgramID, "hmdWarpParam"); + + } else { + glBindTexture(GL_TEXTURE_2D, ::oculusTextureID); + } + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, WIDTH, HEIGHT); + + glPopMatrix(); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + gluOrtho2D(0, WIDTH, 0, HEIGHT); + glDisable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + + glEnable(GL_TEXTURE_2D); + glUseProgramObjectARB(::oculusProgramID); + glUniform1fARB(textureLocation, 0); + glUniform2fARB(lensCenterLocation, 0.25, 0.5); + glUniform2fARB(screenCenterLocation, 0.25, 0.5); + glUniform2fARB(scaleLocation, 0.25, 0.5); + glUniform2fARB(scaleInLocation, 4, 2); + glUniform4fARB(hmdWarpParamLocation, 1.0, 0.22, 0.24, 0); + + glColor3f(1, 0, 1); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); + glVertex2f(0, 0); + glTexCoord2f(0.5, 0); + glVertex2f(WIDTH/2, 0); + glTexCoord2f(0.5, 1); + glVertex2f(WIDTH/2, HEIGHT); + glTexCoord2f(0, 1); + glVertex2f(0, HEIGHT); + glEnd(); + + glUniform2fARB(lensCenterLocation, 0.75, 0.5); + glUniform2fARB(screenCenterLocation, 0.75, 0.5); + + glBegin(GL_QUADS); + glTexCoord2f(0.5, 0); + glVertex2f(WIDTH/2, 0); + glTexCoord2f(1, 0); + glVertex2f(WIDTH, 0); + glTexCoord2f(1, 1); + glVertex2f(WIDTH, HEIGHT); + glTexCoord2f(0.5, 1); + glVertex2f(WIDTH/2, HEIGHT); + glEnd(); + + glDisable(GL_TEXTURE_2D); + glUseProgramObjectARB(0); + + glPopMatrix(); +} + +void displayOverlay() { + // Render 2D overlay: I/O level bar graphs and text + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + gluOrtho2D(0, WIDTH, HEIGHT, 0); + glDisable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + + #ifndef _WIN32 + audio.render(WIDTH, HEIGHT); + audioScope.render(); + #endif + + if (displayHeadMouse && !::lookingInMirror && statsOn) { + // Display small target box at center or head mouse target that can also be used to measure LOD + glColor3f(1.0, 1.0, 1.0); + glDisable(GL_LINE_SMOOTH); + const int PIXEL_BOX = 20; + glBegin(GL_LINE_STRIP); + glVertex2f(headMouseX - PIXEL_BOX/2, headMouseY - PIXEL_BOX/2); + glVertex2f(headMouseX + PIXEL_BOX/2, headMouseY - PIXEL_BOX/2); + glVertex2f(headMouseX + PIXEL_BOX/2, headMouseY + PIXEL_BOX/2); + glVertex2f(headMouseX - PIXEL_BOX/2, headMouseY + PIXEL_BOX/2); + glVertex2f(headMouseX - PIXEL_BOX/2, headMouseY - PIXEL_BOX/2); + glEnd(); + glEnable(GL_LINE_SMOOTH); + } + + // Show detected levels from the serial I/O ADC channel sensors + if (displayLevels) serialPort.renderLevels(WIDTH,HEIGHT); + + // Display stats and log text onscreen + glLineWidth(1.0f); + glPointSize(1.0f); + + if (::statsOn) { displayStats(); } + if (::logOn) { logger.render(WIDTH, HEIGHT); } + + // Show menu + if (::menuOn) { + glLineWidth(1.0f); + glPointSize(1.0f); + menu.render(WIDTH,HEIGHT); + } + + // Show chat entry field + if (::chatEntryOn) { + chatEntry.render(WIDTH, HEIGHT); + } + + // Stats at upper right of screen about who domain server is telling us about + glPointSize(1.0f); + char agents[100]; + + AgentList* agentList = AgentList::getInstance(); + int totalAvatars = 0, totalServers = 0; + + for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) { + agent->getType() == AGENT_TYPE_AVATAR ? totalAvatars++ : totalServers++; + } + + sprintf(agents, "Servers: %d, Avatars: %d\n", totalServers, totalAvatars); + drawtext(WIDTH-150,20, 0.10, 0, 1.0, 0, agents, 1, 0, 0); + + if (::paintOn) { + + char paintMessage[100]; + sprintf(paintMessage,"Painting (%.3f,%.3f,%.3f/%.3f/%d,%d,%d)", + ::paintingVoxel.x,::paintingVoxel.y,::paintingVoxel.z,::paintingVoxel.s, + (unsigned int)::paintingVoxel.red,(unsigned int)::paintingVoxel.green,(unsigned int)::paintingVoxel.blue); + drawtext(WIDTH-350,50, 0.10, 0, 1.0, 0, paintMessage, 1, 1, 0); + } + + glPopMatrix(); +} void display(void) { @@ -846,131 +1094,17 @@ void display(void) glRotatef ( whichCamera.getYaw(), 0, 1, 0 ); glTranslatef( -whichCamera.getPosition().x, -whichCamera.getPosition().y, -whichCamera.getPosition().z ); - if (::starsOn) { - // should be the first rendering pass - w/o depth buffer / lighting - - // finally render the starfield - stars.render(whichCamera.getFieldOfView(), aspectRatio, whichCamera.getNearClip()); + if (::oculusOn) { + displayOculus(whichCamera); + + } else { + displaySide(whichCamera); + glPopMatrix(); + + displayOverlay(); } - - glEnable(GL_LIGHTING); - glEnable(GL_DEPTH_TEST); - - // draw a red sphere - float sphereRadius = 0.25f; - glColor3f(1,0,0); - glPushMatrix(); - glutSolidSphere( sphereRadius, 15, 15 ); - glPopMatrix(); - - //draw a grid ground plane.... - drawGroundPlaneGrid( 5.0f, 9 ); - - // Draw voxels - if ( showingVoxels ) - { - voxels.render(); - } - - // Render avatars of other agents - AgentList* agentList = AgentList::getInstance(); - agentList->lock(); - for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) { - if (agent->getLinkedData() != NULL && agent->getType() == AGENT_TYPE_AVATAR) { - Avatar *avatar = (Avatar *)agent->getLinkedData(); - avatar->render(0); - } - } - agentList->unlock(); - - // Render the world box - if (!::lookingInMirror && ::statsOn) { render_world_box(); } - - // brad's frustum for debugging - if (::frustumOn) renderViewFrustum(::viewFrustum); - - //Render my own avatar - myAvatar.render(::lookingInMirror); } - glPopMatrix(); - - // Render 2D overlay: I/O level bar graphs and text - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - gluOrtho2D(0, WIDTH, HEIGHT, 0); - glDisable(GL_DEPTH_TEST); - glDisable(GL_LIGHTING); - - #ifndef _WIN32 - audio.render(WIDTH, HEIGHT); - audioScope.render(); - #endif - - if (displayHeadMouse && !::lookingInMirror && statsOn) { - // Display small target box at center or head mouse target that can also be used to measure LOD - glColor3f(1.0, 1.0, 1.0); - glDisable(GL_LINE_SMOOTH); - const int PIXEL_BOX = 20; - glBegin(GL_LINE_STRIP); - glVertex2f(headMouseX - PIXEL_BOX/2, headMouseY - PIXEL_BOX/2); - glVertex2f(headMouseX + PIXEL_BOX/2, headMouseY - PIXEL_BOX/2); - glVertex2f(headMouseX + PIXEL_BOX/2, headMouseY + PIXEL_BOX/2); - glVertex2f(headMouseX - PIXEL_BOX/2, headMouseY + PIXEL_BOX/2); - glVertex2f(headMouseX - PIXEL_BOX/2, headMouseY - PIXEL_BOX/2); - glEnd(); - glEnable(GL_LINE_SMOOTH); - } - - // Show detected levels from the serial I/O ADC channel sensors - if (displayLevels) serialPort.renderLevels(WIDTH,HEIGHT); - - // Display stats and log text onscreen - glLineWidth(1.0f); - glPointSize(1.0f); - - if (::statsOn) { displayStats(); } - if (::logOn) { logger.render(WIDTH, HEIGHT); } - - // Show menu - if (::menuOn) { - glLineWidth(1.0f); - glPointSize(1.0f); - menu.render(WIDTH,HEIGHT); - } - - // Show chat entry field - if (::chatEntryOn) { - chatEntry.render(WIDTH, HEIGHT); - } - - // Stats at upper right of screen about who domain server is telling us about - glPointSize(1.0f); - char agents[100]; - - AgentList* agentList = AgentList::getInstance(); - int totalAvatars = 0, totalServers = 0; - - for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) { - agent->getType() == AGENT_TYPE_AVATAR ? totalAvatars++ : totalServers++; - } - - sprintf(agents, "Servers: %d, Avatars: %d\n", totalServers, totalAvatars); - drawtext(WIDTH-150,20, 0.10, 0, 1.0, 0, agents, 1, 0, 0); - - if (::paintOn) { - - char paintMessage[100]; - sprintf(paintMessage,"Painting (%.3f,%.3f,%.3f/%.3f/%d,%d,%d)", - ::paintingVoxel.x,::paintingVoxel.y,::paintingVoxel.z,::paintingVoxel.s, - (unsigned int)::paintingVoxel.red,(unsigned int)::paintingVoxel.green,(unsigned int)::paintingVoxel.blue); - drawtext(WIDTH-350,50, 0.10, 0, 1.0, 0, paintMessage, 1, 1, 0); - } - - glPopMatrix(); - - glutSwapBuffers(); frameCount++; @@ -1040,6 +1174,10 @@ int setStars(int state) { return setValue(state, &::starsOn); } +int setOculus(int state) { + return setValue(state, &::oculusOn); +} + int setStats(int state) { return setValue(state, &::statsOn); } @@ -1162,6 +1300,7 @@ void initMenu() { menuColumnRender = menu.addColumn("Render"); menuColumnRender->addRow("Voxels (V)", setVoxels); menuColumnRender->addRow("Stars (*)", setStars); + menuColumnRender->addRow("Oculus (o)", setOculus); // Tools menuColumnTools = menu.addColumn("Tools"); @@ -1353,6 +1492,7 @@ void key(unsigned char k, int x, int y) if (k == 'F') ::frustumOn = !::frustumOn; // toggle view frustum debugging if (k == 'C') ::cameraFrustum = !::cameraFrustum; // toggle which frustum to look at if (k == 'O' || k == 'G') setFrustumOffset(MENU_ROW_PICKED); // toggle view frustum offset debugging + if (k == 'o') ::oculusOn = !::oculusOn; if (k == '[') ::viewFrustumOffsetYaw -= 0.5; if (k == ']') ::viewFrustumOffsetYaw += 0.5; From 94f1e03eb1e09d467bba18dbc5352bc636264b97 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 2 May 2013 13:02:11 -0700 Subject: [PATCH 2/7] More work on Oculus integration; added some notes to explain the source of the magic numbers. --- interface/src/main.cpp | 66 ++++++++++++++++++++++++++++++------------ 1 file changed, 48 insertions(+), 18 deletions(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 13a7768210..8a6af32692 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -177,6 +177,7 @@ bool chatEntryOn = false; // Whether to show the chat entry bool oculusOn = false; // Whether to configure the display for the Oculus Rift GLuint oculusTextureID = 0; // The texture to which we render for Oculus distortion GLuint oculusProgramID = 0; // The GLSL program containing the distortion shader +float oculusDistortionScale = 1.5f; // Controls the Oculus field of view // // Serial USB Variables @@ -743,6 +744,9 @@ void displaySide(Camera& whichCamera) { glPopMatrix(); } +// this shader is an adaptation (HLSL -> GLSL, removed conditional) of the one in the Oculus sample +// code (Samples/OculusRoomTiny/RenderTiny_D3D1X_Device.cpp), which is under the Apache license +// (http://www.apache.org/licenses/LICENSE-2.0) const char* DISTORTION_FRAGMENT_SHADER = "#version 120\n" "uniform sampler2D texture;" @@ -766,6 +770,7 @@ const char* DISTORTION_FRAGMENT_SHADER = " above.s * above.t * below.s * below.t);" "}"; +// the locations of the uniform variables int textureLocation; int lensCenterLocation; int screenCenterLocation; @@ -775,11 +780,27 @@ int hmdWarpParamLocation; // renders both sides into a texture, then renders the texture to the display with distortion void displayOculus(Camera& whichCamera) { + // magic numbers ahoy! in order to avoid pulling in the Oculus utility library that calculates + // the rendering parameters from the hardware stats, i just folded their calculations into + // constants using the stats for the current-model hardware as contained in the SDK file + // LibOVR/Src/Util/Util_Render_Stereo.cpp + + // eye + // render the left eye view to the left side of the screen + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glTranslatef(-0.151976, 0, 0); // -h, see Oculus SDK docs p. 26 + glMatrixMode(GL_MODELVIEW); glViewport(0, 0, WIDTH/2, HEIGHT); displaySide(whichCamera); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); // and the right eye to the right side + glPushMatrix(); + glTranslatef(0.151976, 0, 0); // +h + glMatrixMode(GL_MODELVIEW); glViewport(WIDTH/2, 0, WIDTH/2, HEIGHT); displaySide(whichCamera); @@ -813,19 +834,23 @@ void displayOculus(Camera& whichCamera) { glPopMatrix(); glMatrixMode(GL_PROJECTION); - glPushMatrix(); glLoadIdentity(); gluOrtho2D(0, WIDTH, 0, HEIGHT); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); + // for reference on setting these values, see SDK file Samples/OculusRoomTiny/RenderTiny_Device.cpp + + float scaleFactor = 1.0 / ::oculusDistortionScale; + float aspectRatio = (WIDTH * 0.5) / HEIGHT; + glEnable(GL_TEXTURE_2D); glUseProgramObjectARB(::oculusProgramID); glUniform1fARB(textureLocation, 0); - glUniform2fARB(lensCenterLocation, 0.25, 0.5); + glUniform2fARB(lensCenterLocation, 0.287994, 0.5); // see SDK docs, p. 29 glUniform2fARB(screenCenterLocation, 0.25, 0.5); - glUniform2fARB(scaleLocation, 0.25, 0.5); - glUniform2fARB(scaleInLocation, 4, 2); + glUniform2fARB(scaleLocation, 0.25 * scaleFactor, 0.5 * scaleFactor * aspectRatio); + glUniform2fARB(scaleInLocation, 4, 2 / aspectRatio); glUniform4fARB(hmdWarpParamLocation, 1.0, 0.22, 0.24, 0); glColor3f(1, 0, 1); @@ -840,7 +865,7 @@ void displayOculus(Camera& whichCamera) { glVertex2f(0, HEIGHT); glEnd(); - glUniform2fARB(lensCenterLocation, 0.75, 0.5); + glUniform2fARB(lensCenterLocation, 0.787994, 0.5); glUniform2fARB(screenCenterLocation, 0.75, 0.5); glBegin(GL_QUADS); @@ -1175,7 +1200,12 @@ int setStars(int state) { } int setOculus(int state) { - return setValue(state, &::oculusOn); + bool wasOn = ::oculusOn; + int value = setValue(state, &::oculusOn); + if (::oculusOn != wasOn) { + reshape(WIDTH, HEIGHT); + } + return value; } int setStats(int state) { @@ -1492,7 +1522,7 @@ void key(unsigned char k, int x, int y) if (k == 'F') ::frustumOn = !::frustumOn; // toggle view frustum debugging if (k == 'C') ::cameraFrustum = !::cameraFrustum; // toggle which frustum to look at if (k == 'O' || k == 'G') setFrustumOffset(MENU_ROW_PICKED); // toggle view frustum offset debugging - if (k == 'o') ::oculusOn = !::oculusOn; + if (k == 'o') setOculus(!::oculusOn); if (k == '[') ::viewFrustumOffsetYaw -= 0.5; if (k == ']') ::viewFrustumOffsetYaw += 0.5; @@ -1663,19 +1693,19 @@ void reshape(int width, int height) HEIGHT = height; aspectRatio = ((float)width/(float)height); // based on screen resize - float fov; - float nearClip; - float farClip; - // get the lens details from the current camera - if (::viewFrustumFromOffset) { - fov = ::viewFrustumOffsetCamera.getFieldOfView(); - nearClip = ::viewFrustumOffsetCamera.getNearClip(); - farClip = ::viewFrustumOffsetCamera.getFarClip(); + Camera& camera = ::viewFrustumFromOffset ? (::viewFrustumOffsetCamera) : (::myCamera); + float nearClip = camera.getNearClip(); + float farClip = camera.getFarClip(); + float fov; + + if (::oculusOn) { + // more magic numbers; see Oculus SDK docs, p. 32 + aspectRatio *= 0.5; + camera.setFieldOfView(fov = 2 * atan((0.0468 * ::oculusDistortionScale) / 0.041) * (180 / PI)); + } else { - fov = ::myCamera.getFieldOfView(); - nearClip = ::myCamera.getNearClip(); - farClip = ::myCamera.getFarClip(); + camera.setFieldOfView(fov = 60); } //printLog("reshape() width=%d, height=%d, aspectRatio=%f fov=%f near=%f far=%f \n", From 5de15dd5a4c535a531095b0ef66e2aa4bad19808 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 2 May 2013 14:39:00 -0700 Subject: [PATCH 3/7] Final bits for Oculus support. Works! --- interface/src/main.cpp | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 6fe0bab8ff..628b4ae952 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -102,7 +102,7 @@ int packetsPerSecond = 0; int bytesPerSecond = 0; int bytesCount = 0; -int WIDTH = 1200; // Window size +int WIDTH = 1280; // Window size int HEIGHT = 800; int fullscreen = 0; float aspectRatio = 1.0f; @@ -177,7 +177,7 @@ bool chatEntryOn = false; // Whether to show the chat entry bool oculusOn = false; // Whether to configure the display for the Oculus Rift GLuint oculusTextureID = 0; // The texture to which we render for Oculus distortion GLuint oculusProgramID = 0; // The GLSL program containing the distortion shader -float oculusDistortionScale = 1.5f; // Controls the Oculus field of view +float oculusDistortionScale = 1.25; // Controls the Oculus field of view // // Serial USB Variables @@ -778,20 +778,30 @@ void displayOculus(Camera& whichCamera) { // render the left eye view to the left side of the screen glMatrixMode(GL_PROJECTION); glPushMatrix(); - glTranslatef(-0.151976, 0, 0); // -h, see Oculus SDK docs p. 26 + glLoadIdentity(); + glTranslatef(0.151976, 0, 0); // +h, see Oculus SDK docs p. 26 + gluPerspective(whichCamera.getFieldOfView(), whichCamera.getAspectRatio(), + whichCamera.getNearClip(), whichCamera.getFarClip()); + glTranslatef(0.032, 0, 0); + glMatrixMode(GL_MODELVIEW); glViewport(0, 0, WIDTH/2, HEIGHT); displaySide(whichCamera); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - + // and the right eye to the right side - glPushMatrix(); - glTranslatef(0.151976, 0, 0); // +h + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glTranslatef(-0.151976, 0, 0); // -h + gluPerspective(whichCamera.getFieldOfView(), whichCamera.getAspectRatio(), + whichCamera.getNearClip(), whichCamera.getFarClip()); + glTranslatef(-0.032, 0, 0); + glMatrixMode(GL_MODELVIEW); glViewport(WIDTH/2, 0, WIDTH/2, HEIGHT); displaySide(whichCamera); + glPopMatrix(); + // restore our normal viewport glViewport(0, 0, WIDTH, HEIGHT); @@ -819,8 +829,6 @@ void displayOculus(Camera& whichCamera) { } glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, WIDTH, HEIGHT); - glPopMatrix(); - glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0, WIDTH, 0, HEIGHT); @@ -868,6 +876,7 @@ void displayOculus(Camera& whichCamera) { glEnd(); glDisable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, 0); glUseProgramObjectARB(0); glPopMatrix(); @@ -1691,7 +1700,7 @@ void reshape(int width, int height) if (::oculusOn) { // more magic numbers; see Oculus SDK docs, p. 32 - aspectRatio *= 0.5; + camera.setAspectRatio(aspectRatio *= 0.5); camera.setFieldOfView(fov = 2 * atan((0.0468 * ::oculusDistortionScale) / 0.041) * (180 / PI)); } else { @@ -1808,6 +1817,8 @@ int main(int argc, const char * argv[]) int ip = getLocalAddress(); sprintf(DOMAIN_IP,"%d.%d.%d.%d", (ip & 0xFF), ((ip >> 8) & 0xFF),((ip >> 16) & 0xFF), ((ip >> 24) & 0xFF)); } + + fullscreen = cmdOptionExists(argc, argv, "--fullscreen"); // the callback for our instance of AgentList is attachNewHeadToAgent AgentList::getInstance()->linkedDataCreateCallback = &attachNewHeadToAgent; From 762c635744e4a4ab7245afbe47def2bede01ebe2 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 2 May 2013 14:44:03 -0700 Subject: [PATCH 4/7] Restored constant value added another reference to the SDK docs. --- interface/src/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 628b4ae952..27e6a39354 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -102,7 +102,7 @@ int packetsPerSecond = 0; int bytesPerSecond = 0; int bytesCount = 0; -int WIDTH = 1280; // Window size +int WIDTH = 1200; // Window size int HEIGHT = 800; int fullscreen = 0; float aspectRatio = 1.0f; @@ -782,7 +782,7 @@ void displayOculus(Camera& whichCamera) { glTranslatef(0.151976, 0, 0); // +h, see Oculus SDK docs p. 26 gluPerspective(whichCamera.getFieldOfView(), whichCamera.getAspectRatio(), whichCamera.getNearClip(), whichCamera.getFarClip()); - glTranslatef(0.032, 0, 0); + glTranslatef(0.032, 0, 0); // dip/2, see p. 27 glMatrixMode(GL_MODELVIEW); glViewport(0, 0, WIDTH/2, HEIGHT); From ccded56ecf8a1b34c2dcca70450c32b56063ce30 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 2 May 2013 15:20:29 -0700 Subject: [PATCH 5/7] Use the right type here; Xcode complains about it. --- interface/src/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 27e6a39354..d039866b8c 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -176,7 +176,7 @@ bool chatEntryOn = false; // Whether to show the chat entry bool oculusOn = false; // Whether to configure the display for the Oculus Rift GLuint oculusTextureID = 0; // The texture to which we render for Oculus distortion -GLuint oculusProgramID = 0; // The GLSL program containing the distortion shader +GLhandleARB oculusProgramID = 0; // The GLSL program containing the distortion shader float oculusDistortionScale = 1.25; // Controls the Oculus field of view // @@ -811,7 +811,7 @@ void displayOculus(Camera& whichCamera) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, WIDTH, HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - GLuint shaderID = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); + GLhandleARB shaderID = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); glShaderSourceARB(shaderID, 1, &DISTORTION_FRAGMENT_SHADER, 0); glCompileShaderARB(shaderID); ::oculusProgramID = glCreateProgramObjectARB(); From 8e2c43e983030b1497b930d135345183416f559b Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 2 May 2013 15:54:58 -0700 Subject: [PATCH 6/7] Need to disable blending when we render the distorted screen quad. --- interface/src/main.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index d039866b8c..957b93e453 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -840,6 +840,7 @@ void displayOculus(Camera& whichCamera) { float scaleFactor = 1.0 / ::oculusDistortionScale; float aspectRatio = (WIDTH * 0.5) / HEIGHT; + glDisable(GL_BLEND); glEnable(GL_TEXTURE_2D); glUseProgramObjectARB(::oculusProgramID); glUniform1fARB(textureLocation, 0); @@ -874,7 +875,8 @@ void displayOculus(Camera& whichCamera) { glTexCoord2f(0.5, 1); glVertex2f(WIDTH/2, HEIGHT); glEnd(); - + + glEnable(GL_BLEND); glDisable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); glUseProgramObjectARB(0); From 08350a5d3aa5173905183081a9f3e79fbe916cbe Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 3 May 2013 10:22:10 -0700 Subject: [PATCH 7/7] Rather than a command line parameter, provide a menu option for switching to/from fullscreen mode. --- interface/src/main.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index c602d37823..b0d929ff7e 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -1190,6 +1190,20 @@ int setGyroLook(int state) { return iRet; } +int setFullscreen(int state) { + bool wasFullscreen = ::fullscreen; + int value = setValue(state, &::fullscreen); + if (::fullscreen != wasFullscreen) { + if (::fullscreen) { + glutFullScreen(); + + } else { + glutReshapeWindow(WIDTH, HEIGHT); + } + } + return value; +} + int setVoxels(int state) { return setValue(state, &::showingVoxels); } @@ -1338,6 +1352,7 @@ void initMenu() { menuColumnOptions->addRow("Mirror (h)", setHead); menuColumnOptions->addRow("Noise (n)", setNoise); menuColumnOptions->addRow("Gyro Look", setGyroLook); + menuColumnOptions->addRow("Fullscreen (f)", setFullscreen); menuColumnOptions->addRow("Quit (q)", quitApp); // Render @@ -1538,6 +1553,7 @@ void key(unsigned char k, int x, int y) if (k == 'F') ::frustumOn = !::frustumOn; // toggle view frustum debugging if (k == 'C') ::cameraFrustum = !::cameraFrustum; // toggle which frustum to look at if (k == 'O' || k == 'G') setFrustumOffset(MENU_ROW_PICKED); // toggle view frustum offset debugging + if (k == 'f') setFullscreen(!::fullscreen); if (k == 'o') setOculus(!::oculusOn); if (k == '[') ::viewFrustumOffsetYaw -= 0.5; @@ -1841,8 +1857,6 @@ int main(int argc, const char * argv[]) sprintf(DOMAIN_IP,"%d.%d.%d.%d", (ip & 0xFF), ((ip >> 8) & 0xFF),((ip >> 16) & 0xFF), ((ip >> 24) & 0xFF)); } - fullscreen = cmdOptionExists(argc, argv, "--fullscreen"); - // the callback for our instance of AgentList is attachNewHeadToAgent AgentList::getInstance()->linkedDataCreateCallback = &attachNewHeadToAgent;