Skip to main content
Up and Coming
May 23, 2014

Simple, one page, OpenGL example (Oculus SDK 0.3.2 Preview)

Hi,

Didn't take too long to modify the earlier example (thread) to work with the new 0.3.2 release.
I think the OGL.Window field in ovrGLConfig is just a leftover because you can pass NULL without any consequences. Luckily, at least, the OGL.WglContext and OGL.GdiDC fields are gone making it easier to do the OSX/Linux port. I'll will try the OSX version this afternoon.

EDIT: Still a bit of OpenGL state restoration to do after ovrHmd_EndFrame() if you want your own vertex arrays to work: GL_ELEMENT_ARRAY_BUFFER and GL_ARRAY_BUFFER.
EDIT: Modified so it should work on Linux (thanks yombo and rjoyce). I don't have a Linux machine so please check. Next up OSX!
EDIT: OSX "support" (big word, just some preprocessor defines). GLFW will create a 2.X context, at least on my machine, so the deprecated functions will work. If not let me know.

Thanks,
Daniel


// GLFWOculusRiftTest
// (c) cThrough 2014 (Daniel Dekkers)
// Version 2014052305 Based on OculusSDK 3.0.2 Preview
// Windows, Linux and OSX

#include <GL/glew.h>
#if defined(_WIN32)
#include <Windows.h>
#define GLFW_EXPOSE_NATIVE_WIN32
#define GLFW_EXPOSE_NATIVE_WGL
#elif defined(__linux__)
#include <X11/X.h>
#include <X11/extensions/Xrandr.h>
#define GLFW_EXPOSE_NATIVE_X11
#define GLFW_EXPOSE_NATIVE_GLX
#endif
#include <GLFW/glfw3.h>
#if !defined(__APPLE__)
#include <GLFW/glfw3native.h>
#endif
#include <OVR.h>
#include <OVR_CAPI.h>
#include <OVR_CAPI_GL.h>

const bool l_FullScreen = false;
const bool l_MultiSampling = false;
const bool l_Spin = true;

ovrHmd l_Hmd;
ovrHmdDesc l_HmdDesc;
ovrFovPort l_EyeFov[2];
ovrGLConfig l_Cfg;
ovrEyeRenderDesc l_EyeRenderDesc[2];

GLfloat l_VAPoints[] =
{
0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
-0.5f,-0.5f, 0.5f,
0.5f,-0.5f, 0.5f,
-0.5f,-0.5f,-0.5f,
-0.5f, 0.5f,-0.5f,
0.5f, 0.5f,-0.5f,
0.5f,-0.5f,-0.5f,
0.5f, 0.5f, 0.5f,
0.5f, 0.5f,-0.5f,
-0.5f, 0.5f,-0.5f,
-0.5f, 0.5f, 0.5f,
-0.5f,-0.5f,-0.5f,
0.5f,-0.5f,-0.5f,
0.5f,-0.5f, 0.5f,
-0.5f,-0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
0.5f,-0.5f, 0.5f,
0.5f,-0.5f,-0.5f,
0.5f, 0.5f,-0.5f,
-0.5f,-0.5f,-0.5f,
-0.5f,-0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
-0.5f, 0.5f,-0.5f
};

GLfloat l_VANormals[] =
{
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f,-1.0f,
0.0f, 0.0f,-1.0f,
0.0f, 0.0f,-1.0f,
0.0f, 0.0f,-1.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f,-1.0f, 0.0f,
0.0f,-1.0f, 0.0f,
0.0f,-1.0f, 0.0f,
0.0f,-1.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f
};

GLuint l_VAIndici[] =
{
0, 1, 2, 3,
4, 5, 6, 7,
8, 9, 10, 11,
12, 13, 14, 15,
16, 17, 18, 19,
20, 21, 22, 23
};

// =============================================================================

static void ErrorCallback(int p_Error, const char* p_Description)
{
fputs(p_Description, stderr);
}

// =============================================================================

static void KeyCallback(GLFWwindow* p_Window, int p_Key, int p_Scancode, int p_Action, int p_Mods)
{
if (p_Key == GLFW_KEY_ESCAPE && p_Action == GLFW_PRESS)
glfwSetWindowShouldClose(p_Window, GL_TRUE);
}

// =============================================================================

static void WindowSizeCallback(GLFWwindow* p_Window, int p_Width, int p_Height)
{
l_Cfg.OGL.Header.RTSize.w = p_Width;
l_Cfg.OGL.Header.RTSize.h = p_Height;

int l_DistortionCaps = ovrDistortionCap_Chromatic | ovrDistortionCap_TimeWarp;
ovrHmd_ConfigureRendering(l_Hmd, &l_Cfg.Config, l_DistortionCaps, l_EyeFov, l_EyeRenderDesc);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glUseProgram(0);
}

// ============================================================================

void RenderCubeVertexArrays(void)
{
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, l_VAPoints);

glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, 0, l_VANormals);

glDrawElements(GL_QUADS, 6*4, GL_UNSIGNED_INT, l_VAIndici);

glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
}

// ============================================================================

void RenderCubeFixedFunction(void)
{
// Obsolete, remains as a fall back for the vertex arrays version...
glBegin(GL_QUADS);
glNormal3f( 0.0f, 0.0f, 1.0f);
glVertex3f( 0.5f, 0.5f, 0.5f);
glVertex3f(-0.5f, 0.5f, 0.5f);
glVertex3f(-0.5f,-0.5f, 0.5f);
glVertex3f( 0.5f,-0.5f, 0.5f);

glNormal3f( 0.0f, 0.0f,-1.0f);
glVertex3f(-0.5f,-0.5f,-0.5f);
glVertex3f(-0.5f, 0.5f,-0.5f);
glVertex3f( 0.5f, 0.5f,-0.5f);
glVertex3f( 0.5f,-0.5f,-0.5f);

glNormal3f( 0.0f, 1.0f, 0.0f);
glVertex3f( 0.5f, 0.5f, 0.5f);
glVertex3f( 0.5f, 0.5f,-0.5f);
glVertex3f(-0.5f, 0.5f,-0.5f);
glVertex3f(-0.5f, 0.5f, 0.5f);

glNormal3f( 0.0f,-1.0f, 0.0f);
glVertex3f(-0.5f,-0.5f,-0.5f);
glVertex3f( 0.5f,-0.5f,-0.5f);
glVertex3f( 0.5f,-0.5f, 0.5f);
glVertex3f(-0.5f,-0.5f, 0.5f);

glNormal3f( 1.0f, 0.0f, 0.0f);
glVertex3f( 0.5f, 0.5f, 0.5f);
glVertex3f( 0.5f,-0.5f, 0.5f);
glVertex3f( 0.5f,-0.5f,-0.5f);
glVertex3f( 0.5f, 0.5f,-0.5f);

glNormal3f(-1.0f, 0.0f, 0.0f);
glVertex3f(-0.5f,-0.5f,-0.5f);
glVertex3f(-0.5f,-0.5f, 0.5f);
glVertex3f(-0.5f, 0.5f, 0.5f);
glVertex3f(-0.5f, 0.5f,-0.5f);
glEnd();
}

// ============================================================================

static void SetOpenGLState(void)
{
// Some state...
glEnable(GL_CULL_FACE);
glEnable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
if (l_MultiSampling) glEnable(GL_MULTISAMPLE);

// Some (stationary) lights...
GLfloat l_Light0Position[] = { 5.0f, 6.0f, 3.0f, 0.0f };
GLfloat l_Light0Diffuse[] = { 1.0f, 0.8f, 0.6f, 1.0f };
glLightfv(GL_LIGHT0, GL_POSITION, l_Light0Position);
glLightfv(GL_LIGHT0, GL_DIFFUSE, l_Light0Diffuse);
glEnable(GL_LIGHT0);

GLfloat l_Light1Position[] = { -5.0f, -6.0f, 5.0f, 0.0f };
GLfloat l_Light1Diffuse[] = { 0.6f, 0.8f, 1.0f, 1.0f };
glLightfv(GL_LIGHT1, GL_POSITION, l_Light1Position);
glLightfv(GL_LIGHT1, GL_DIFFUSE, l_Light1Diffuse);
glEnable(GL_LIGHT1);

// Material...
GLfloat l_MaterialSpecular[] = { 0.3f, 0.3f, 0.3f, 1.0f };
GLfloat l_MaterialShininess[] = { 10.0f };
glMaterialfv(GL_FRONT, GL_SPECULAR, l_MaterialSpecular);
glMaterialfv(GL_FRONT, GL_SHININESS, l_MaterialShininess);
}

// =============================================================================

int main(void)
{
// Initialize LibOVR...
ovr_Initialize();

l_Hmd = ovrHmd_Create(0);
if (!l_Hmd) l_Hmd = ovrHmd_CreateDebug(ovrHmd_DK1);

ovrHmd_GetDesc(l_Hmd, &l_HmdDesc);

// Start the sensor which provides the Rift’s pose and motion.
ovrHmd_StartSensor(l_Hmd, ovrSensorCap_Orientation | ovrSensorCap_YawCorrection | ovrSensorCap_Position, ovrSensorCap_Orientation);

GLFWwindow* l_Window;

glfwSetErrorCallback(ErrorCallback);

if (!glfwInit()) exit(EXIT_FAILURE);

if (l_MultiSampling) glfwWindowHint(GLFW_SAMPLES, 4); else glfwWindowHint(GLFW_SAMPLES, 0);

ovrSizei l_ClientSize;
if (l_FullScreen)
{
l_ClientSize.w = l_HmdDesc.Resolution.w; // 1280 for DK1...
l_ClientSize.h = l_HmdDesc.Resolution.h; // 800 for DK1...
// Create a fullscreen window with the Oculus Rift resolution...
l_Window = glfwCreateWindow(l_ClientSize.w, l_ClientSize.h, "GLFW Oculus Rift Test", glfwGetPrimaryMonitor(), NULL);
}
else
{
l_ClientSize.w = 640;
l_ClientSize.h = 480;
l_Window = glfwCreateWindow(l_ClientSize.w, l_ClientSize.h, "GLFW Oculus Rift Test", NULL, NULL);
}

if (!l_Window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}

// Make the context current for this window...
glfwMakeContextCurrent(l_Window);

// Don't forget to initialize Glew, turn glewExperimental on to avoid problem fetching function pointers...
glewExperimental = GL_TRUE;
GLenum l_Result = glewInit();
if (l_Result!=GLEW_OK)
{
printf("glewInit() error.\n");
exit(EXIT_FAILURE);
}

// Print some info about the OpenGL context...
int l_Major = glfwGetWindowAttrib(l_Window, GLFW_CONTEXT_VERSION_MAJOR);
int l_Minor = glfwGetWindowAttrib(l_Window, GLFW_CONTEXT_VERSION_MINOR);
int l_Profile = glfwGetWindowAttrib(l_Window, GLFW_OPENGL_PROFILE);
printf("OpenGL: %d.%d ", l_Major, l_Minor);
if (l_Major>=3) // Profiles introduced in OpenGL 3.0...
{
if (l_Profile==GLFW_OPENGL_COMPAT_PROFILE) printf("GLFW_OPENGL_COMPAT_PROFILE\n"); else printf("GLFW_OPENGL_CORE_PROFILE\n");
}
printf("Vendor: %s\n", (char*)glGetString(GL_VENDOR));
printf("Renderer: %s\n", (char*)glGetString(GL_RENDERER));

// Create some lights, materials, etc...
SetOpenGLState();

// We will do some offscreen rendering, setup FBO...
ovrSizei l_TextureSizeLeft = ovrHmd_GetFovTextureSize(l_Hmd, ovrEye_Left, l_HmdDesc.DefaultEyeFov[0], 1.0f);
ovrSizei l_TextureSizeRight = ovrHmd_GetFovTextureSize(l_Hmd, ovrEye_Right, l_HmdDesc.DefaultEyeFov[1], 1.0f);
ovrSizei l_TextureSize;
l_TextureSize.w = l_TextureSizeLeft.w + l_TextureSizeRight.w;
l_TextureSize.h = (l_TextureSizeLeft.h>l_TextureSizeRight.h ? l_TextureSizeLeft.h : l_TextureSizeRight.h);

// Create FBO...
GLuint l_FBOId;
glGenFramebuffers(1, &l_FBOId);
glBindFramebuffer(GL_FRAMEBUFFER, l_FBOId);

// The texture we're going to render to...
GLuint l_TextureId;
glGenTextures(1, &l_TextureId);
// "Bind" the newly created texture : all future texture functions will modify this texture...
glBindTexture(GL_TEXTURE_2D, l_TextureId);
// Give an empty image to OpenGL (the last "0")
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, l_TextureSize.w, l_TextureSize.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
// Linear filtering...
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

// Create Depth Buffer...
GLuint l_DepthBufferId;
glGenRenderbuffers(1, &l_DepthBufferId);
glBindRenderbuffer(GL_RENDERBUFFER, l_DepthBufferId);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, l_TextureSize.w, l_TextureSize.h);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, l_DepthBufferId);

// Set the texture as our colour attachment #0...
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, l_TextureId, 0);

// Set the list of draw buffers...
GLenum l_GLDrawBuffers[1] = { GL_COLOR_ATTACHMENT0 };
glDrawBuffers(1, l_GLDrawBuffers); // "1" is the size of DrawBuffers

// Check if everything is OK...
GLenum l_Check = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
if (l_Check!=GL_FRAMEBUFFER_COMPLETE)
{
printf("There is a problem with the FBO.\n");
exit(EXIT_FAILURE);
}

// Unbind...
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);

// Oculus Rift eye configurations...
l_EyeFov[0] = l_HmdDesc.DefaultEyeFov[0];
l_EyeFov[1] = l_HmdDesc.DefaultEyeFov[1];

l_Cfg.OGL.Header.API = ovrRenderAPI_OpenGL;
l_Cfg.OGL.Header.Multisample = (l_MultiSampling ? 1 : 0);
l_Cfg.OGL.Header.RTSize.w = l_ClientSize.w;
l_Cfg.OGL.Header.RTSize.h = l_ClientSize.h;
#if defined(_WIN32)
l_Cfg.OGL.Window = glfwGetWin32Window(l_Window);
#elif defined(__linux__)
l_Cfg.OGL.Win = glfwGetX11Window(l_Window);
l_Cfg.OGL.Disp = glfwGetX11Display();
#endif

int l_DistortionCaps = ovrDistortionCap_Chromatic | ovrDistortionCap_TimeWarp;
ovrHmd_ConfigureRendering(l_Hmd, &l_Cfg.Config, l_DistortionCaps, l_EyeFov, l_EyeRenderDesc);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glUseProgram(0);

ovrGLTexture l_EyeTexture[2];
l_EyeTexture[0].OGL.Header.API = ovrRenderAPI_OpenGL;
l_EyeTexture[0].OGL.Header.TextureSize.w = l_TextureSize.w;
l_EyeTexture[0].OGL.Header.TextureSize.h = l_TextureSize.h;
l_EyeTexture[0].OGL.Header.RenderViewport.Pos.x = 0;
l_EyeTexture[0].OGL.Header.RenderViewport.Pos.y = 0;
l_EyeTexture[0].OGL.Header.RenderViewport.Size.w = l_TextureSize.w/2;
l_EyeTexture[0].OGL.Header.RenderViewport.Size.h = l_TextureSize.h;
l_EyeTexture[0].OGL.TexId = l_TextureId;

// Right eye the same, except for the x-position in the texture...
l_EyeTexture[1] = l_EyeTexture[0];
l_EyeTexture[1].OGL.Header.RenderViewport.Pos.x = (l_TextureSize.w+1)/2;

glfwSetKeyCallback(l_Window, KeyCallback);
glfwSetWindowSizeCallback(l_Window, WindowSizeCallback);

GLfloat l_SpinX;
GLfloat l_SpinY;

while (!glfwWindowShouldClose(l_Window))
{
if (l_Spin)
{
l_SpinX = (GLfloat) fmod(glfwGetTime()*17.0, 360.0);
l_SpinY = (GLfloat) fmod(glfwGetTime()*23.0, 360.0);
}
else
{
l_SpinX = 30.0f;
l_SpinY = 40.0f;
}

ovrFrameTiming m_HmdFrameTiming = ovrHmd_BeginFrame(l_Hmd, 0);

// Bind the FBO...
glBindFramebuffer(GL_FRAMEBUFFER, l_FBOId);
// Clear...
glClearColor(0.2f, 0.3f, 0.4f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

for (int l_EyeIndex=0; l_EyeIndex<ovrEye_Count; l_EyeIndex++)
{
ovrEyeType l_Eye = l_HmdDesc.EyeRenderOrder[l_EyeIndex];
ovrPosef l_EyePose = ovrHmd_BeginEyeRender(l_Hmd, l_Eye);

glViewport(l_EyeTexture[l_Eye].OGL.Header.RenderViewport.Pos.x,
l_EyeTexture[l_Eye].OGL.Header.RenderViewport.Pos.y,
l_EyeTexture[l_Eye].OGL.Header.RenderViewport.Size.w,
l_EyeTexture[l_Eye].OGL.Header.RenderViewport.Size.h
);

// Get Projection and ModelView matrici from the device...
OVR::Matrix4f l_ProjectionMatrix = ovrMatrix4f_Projection(
l_EyeRenderDesc[l_Eye].Fov, 0.3f, 100.0f, true);
OVR::Quatf l_Orientation = OVR::Quatf(l_EyePose.Orientation);
OVR::Matrix4f l_ModelViewMatrix = OVR::Matrix4f(l_Orientation.Inverted());

// Pass matrici on to OpenGL...
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMultMatrixf(&(l_ProjectionMatrix.Transposed().M[0][0]));
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// Translate for specific eye based on IPD...
glTranslatef(l_EyeRenderDesc[l_Eye].ViewAdjust.x,
l_EyeRenderDesc[l_Eye].ViewAdjust.y,
l_EyeRenderDesc[l_Eye].ViewAdjust.z);
// Multiply with orientation retrieved from sensor...
glMultMatrixf(&(l_ModelViewMatrix.Transposed().M[0][0]));
// Move back a bit to show scene in front of us...
glTranslatef(0.0f, 0.0f, -2.0f);
// Make the cube spin...
glRotatef(l_SpinX, 1.0f, 0.0f, 0.0f);
glRotatef(l_SpinY, 0.0f, 1.0f, 0.0f);

// Render...
// RenderCubeFixedFunction();
RenderCubeVertexArrays();

ovrHmd_EndEyeRender(l_Hmd, l_Eye, l_EyePose, &l_EyeTexture[l_Eye].Texture);
}

// Unbind the FBO, back to normal drawing...
glBindFramebuffer(GL_FRAMEBUFFER, 0);

ovrHmd_EndFrame(l_Hmd);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glUseProgram(0);

glfwPollEvents();
}

glfwDestroyWindow(l_Window);

glfwTerminate();

ovrHmd_Destroy(l_Hmd);
ovr_Shutdown();

exit(EXIT_SUCCESS);
}

    51 replies

    Up and Coming
    June 17, 2014
    Hi, I have a question about the Matrix part.
    Why do you do:

    glMultMatrixf(&(l_ProjectionMatrix.Transposed().M[0][0]));
    ...
    glMultMatrixf(&(l_ModelViewMatrix.Transposed().M[0][0]));


    when this is equivalent (no transpose):

    glMultMatrixf(&(l_ProjectionMatrix.M[0][0]));
    ...
    glMultMatrixf(&(l_ModelViewMatrix.M[0][0]));
    DoZo1971Author
    Up and Coming
    June 19, 2014
    @mosesr:
    OculusSDK wants glext.h, it's included in the "3rdParty" directory. Just including the correct directory should work.
    This is my (CMake) fragment setting up the Oculus Rift lib and include directories:

    # ==============================================================================
    # = Oculus Rift
    # ==============================================================================

    MESSAGE(STATUS "--- Oculus Rift ---")

    IF(WIN32) # 32 and 64 bit windows...
    SET(MYOCULUSRIFT_ROOT "C:/OculusSDK0.3.2" CACHE FILEPATH "Root path for Oculus Rift SDK")
    SET(MYOCULUSRIFT_INCLUDE_PATHS
    ${MYOCULUSRIFT_ROOT}/LibOVR/Include
    ${MYOCULUSRIFT_ROOT}/LibOVR/Src
    ${MYOCULUSRIFT_ROOT}/3rdParty/glext
    CACHE FILEPATH "Root paths for Oculus Rift includes")
    INCLUDE_DIRECTORIES(${MYOCULUSRIFT_INCLUDE_PATHS})
    IF(CMAKE_SIZEOF_VOID_P EQUAL 8) # 64-bit target...
    SET(MYOCULUSRIFT_LIBRARY_DEBUG "${MYOCULUSRIFT_ROOT}/LibOVR/Lib/x64/libovr64d.lib" CACHE FILEPATH "Root path for Oculus Rift Debug library")
    SET(MYOCULUSRIFT_LIBRARY_RELEASE "${MYOCULUSRIFT_ROOT}/LibOVR/Lib/x64/libovr64.lib" CACHE FILEPATH "Root path for Oculus Rift Release library")
    ELSE()
    SET(MYOCULUSRIFT_LIBRARY_DEBUG "${MYOCULUSRIFT_ROOT}/LibOVR/Lib/Win32/VS2012/libovrd.lib" CACHE FILEPATH "Root path for Oculus Rift Debug library")
    SET(MYOCULUSRIFT_LIBRARY_RELEASE "${MYOCULUSRIFT_ROOT}/LibOVR/Lib/Win32/VS2012/libovr.lib" CACHE FILEPATH "Root path for Oculus Rift Release library")
    ENDIF()
    ELSEIF(APPLE)
    SET(MYOCULUSRIFT_ROOT "/Users/danieldekkers/OculusSDK0.3.2" CACHE FILEPATH "Root path for Oculus Rift SDK")
    SET(MYOCULUSRIFT_INCLUDE_PATHS
    ${MYOCULUSRIFT_ROOT}/LibOVR/Include
    ${MYOCULUSRIFT_ROOT}/LibOVR/Src
    ${MYOCULUSRIFT_ROOT}/3rdParty/glext
    CACHE FILEPATH "Root paths for Oculus Rift includes")
    INCLUDE_DIRECTORIES(${MYOCULUSRIFT_INCLUDE_PATHS})
    IF(CMAKE_SIZEOF_VOID_P EQUAL 8) # 64-bit target...
    SET(MYOCULUSRIFT_LIBRARY_DEBUG "${MYOCULUSRIFT_ROOT}/LibOVR/Lib/MacOS/Debug/libovr.a" CACHE FILEPATH "Root path for Oculus Rift Debug library")
    SET(MYOCULUSRIFT_LIBRARY_RELEASE "${MYOCULUSRIFT_ROOT}/LibOVR/Lib/MacOS/Release/libovr.a" CACHE FILEPATH "Root path for Oculus Rift Release library")
    ELSE()
    MESSAGE(STATUS "No 32 bit OSX Oculus Rift SDK")
    ENDIF()
    ELSEIF(UNIX)
    # @TODO
    ENDIF()

    IF(EXISTS ${MYOCULUSRIFT_ROOT})
    MESSAGE(STATUS "Oculus Rift root path found: " ${MYOCULUSRIFT_ROOT})
    ELSE(EXISTS ${MYOCULUSRIFT_ROOT})
    MESSAGE("Oculus Rift root path not found...")
    ENDIF(EXISTS ${MYOCULUSRIFT_ROOT})

    IF(EXISTS ${MYOCULUSRIFT_LIBRARY_DEBUG})
    MESSAGE(STATUS "Oculus Rift debug library found: " ${MYOCULUSRIFT_LIBRARY_DEBUG})
    ELSE(EXISTS ${MYOCULUSRIFT_LIBRARY_DEBUG})
    MESSAGE("Oculus Rift debug library not found...")
    ENDIF(EXISTS ${MYOCULUSRIFT_LIBRARY_DEBUG})

    IF(EXISTS ${MYOCULUSRIFT_LIBRARY_RELEASE})
    MESSAGE(STATUS "Oculus Rift release library found: " ${MYOCULUSRIFT_LIBRARY_RELEASE})
    ELSE(EXISTS ${MYOCULUSRIFT_LIBRARY_RELEASE})
    MESSAGE("Oculus Rift release library not found...")
    ENDIF(EXISTS ${MYOCULUSRIFT_LIBRARY_RELEASE})


    @philigaultier
    I didn't think about it too much, just copied from the documentation or an example, don't remember. Are you sure it's equivalent, that would be strange... I assumed it was due to the way OculusSDK stored its matrici (column major/row major). I'll check.
    Inspiring
    June 19, 2014
    "philigaultier" wrote:
    Hi, I have a question about the Matrix part.
    Why do you do:

    glMultMatrixf(&(l_ProjectionMatrix.Transposed().M[0][0]));
    ...
    glMultMatrixf(&(l_ModelViewMatrix.Transposed().M[0][0]));


    when this is equivalent (no transpose):

    glMultMatrixf(&(l_ProjectionMatrix.M[0][0]));
    ...
    glMultMatrixf(&(l_ModelViewMatrix.M[0][0]));



    Those two blocks are not equivalent. The Transposed() method returns a copied matrix with the rows and columns switched. Whether you use clolumn-major or row-major matrices is a matter of preference, but OpenGL requires that the matrices used in it's gl*Matrix methods be laid out in the opposite convention as the Oculus SDK lays out theirs.
    Brad Davis - Developer for High Fidelity Co-author of Oculus Rift in Action
    DoZo1971Author
    Up and Coming
    June 21, 2014
    Yes. The Transposed() does matter. Actually for the Projection Matrix you can see it quite clearly. For the Model View matrix it is more subtle but that is because the IPD translation doesn't let the matrix deviate from identity too much at that point in the calculation. But remember, like jherico mentioned, it has no geometrical meaning. It is just the way the elements of the matrix are stored.
    Up and Coming
    June 24, 2014
    Yeah, I tried to remove the
    .Transposed()
    part and it looked really weird. It's just that from a mathematical point of view, if you transpose a matrix, an element on its diagonal stays unchanged, for example M[0][0].
    What did I miss here?

    EDIT: Ok, M[0][0] tells OpenGL to take the whole matrix as a single dimensional array, and doesn't just return a single float.
    Now it makes sense :)
    Inspiring
    June 24, 2014
    "philigaultier" wrote:
    Yeah, I tried to remove the
    .Transposed()
    part and it looked really weird. It's just that from a mathematical point of view, if you transpose a matrix, an element on its diagonal stays unchanged, for example M[0][0].
    What did I miss here?


    That the diagonals aren't the only important part of the matrix? Transposing a matrix isn't a mathematical operation. It's an organizational one. Both the application code and the 3D rendering API have to agree on how to interpret the individual elements of the matrix. More specifically, both Direct3D and OpenGL specify how they expect the matrix to be laid out, and it's up to the application developer to conform to that.

    The Oculus SDK supports both Direct3D and OpenGL, but these two rendering APIs disagree on how the matrix should be laid out (in fact, Direct3D is almost pointlessly contrary to the conventions of OpenGL, whether it's handedness, matrix layout, or texture coordinate systems, whenever Direct3D had a choice between doing it the same as OpenGL or differently, they chose the latter... the fuckers). The Oculus SDK tends to favor the Direct3D API in most cases, meaning that to use the SDK provided matrices with OpenGL, they need to be transposed. That's all there is to it.

    Here's a good blog post on the topic of matrices and their layout in memory. In particular this image seems fairly illuminating:

    Brad Davis - Developer for High Fidelity Co-author of Oculus Rift in Action
    Up and Coming
    June 24, 2014
    Thank you, yeah I figured it out, it's just that my mind wrongly put parenthensis where there were none:


    glMultMatrixf(
    & ( l_ProjectionMatrix.Transposed() )
    .M[0][0]
    );

    (hope the indentation helps)
    And i thought that we were multiplying the Identity matrix with a float (the first element of the projection Matrix)

    which is totally not the case.

    Thanks!
    DoZo1971Author
    Up and Coming
    June 24, 2014
    About the handedness:
    Checkout MIT prof Walter Lewin on the subject, funny, it's at 29:00:

    DoZo1971Author
    Up and Coming
    June 24, 2014
    By the way, annoying typo in the topic of this thread. 3.0.2 -> 0.3.2
    Can I change that in some way? Or someone?
    Inspiring
    June 24, 2014
    @DoZo1971: That's a good one.

    I changed the topic title (you just need to edit the first post).
    AMD Ryzen 7 1800X | MSI X370 Titanium | G.Skill 16GB DDR4 3200 | EVGA SuperNOVA 1000 | Corsair Hydro H110i Gigabyte RX Vega 64 x2 | Samsung 960 Evo M.2 500GB | Seagate FireCuda SSHD 2TB | Phanteks ENTHOO EVOLV