|
|
@ -0,0 +1,280 @@ |
|
|
|
|
|
|
|
#include <stdio.h> |
|
|
|
#include <stdlib.h> |
|
|
|
#include <string.h> |
|
|
|
|
|
|
|
#include "glad.h" // Extensions loading library |
|
|
|
#include <GLFW/glfw3.h> |
|
|
|
|
|
|
|
#include "OculusSDK/LibOVR/Include/OVR_CAPI_GL.h" // Oculus SDK for OpenGL |
|
|
|
|
|
|
|
#define FAIL(X) printf(X); |
|
|
|
|
|
|
|
typedef struct Vector2 { |
|
|
|
float x; |
|
|
|
float y; |
|
|
|
} Vector2; |
|
|
|
|
|
|
|
typedef struct Matrix { |
|
|
|
float m0, m4, m8, m12; |
|
|
|
float m1, m5, m9, m13; |
|
|
|
float m2, m6, m10, m14; |
|
|
|
float m3, m7, m11, m15; |
|
|
|
} Matrix; |
|
|
|
|
|
|
|
// RiftManagerApp class |
|
|
|
ovrSession session; |
|
|
|
ovrHmdDesc hmdDesc; |
|
|
|
ovrGraphicsLuid luid; |
|
|
|
|
|
|
|
// RiftApp class |
|
|
|
GLuint fbo = 0; |
|
|
|
GLuint depthBuffer = 0; |
|
|
|
ovrTextureSwapChain eyeTexture; |
|
|
|
|
|
|
|
GLuint mirrorFbo = 0; |
|
|
|
ovrMirrorTexture mirrorTexture; |
|
|
|
ovrEyeRenderDesc eyeRenderDescs[2]; |
|
|
|
Matrix eyeProjections[2]; |
|
|
|
|
|
|
|
ovrLayerEyeFov eyeLayer; |
|
|
|
ovrViewScaleDesc viewScaleDesc; |
|
|
|
|
|
|
|
Vector2 renderTargetSize; |
|
|
|
Vector2 mirrorSize; |
|
|
|
|
|
|
|
// GlfwApp class |
|
|
|
GLFWwindow *window = NULL; |
|
|
|
unsigned int frame = 0; |
|
|
|
|
|
|
|
static void ErrorCallback(int error, const char* description) |
|
|
|
{ |
|
|
|
fputs(description, stderr); |
|
|
|
} |
|
|
|
|
|
|
|
static void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) |
|
|
|
{ |
|
|
|
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) |
|
|
|
{ |
|
|
|
glfwSetWindowShouldClose(window, GL_TRUE); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Execute our example class |
|
|
|
int main() |
|
|
|
{ |
|
|
|
if (!OVR_SUCCESS(ovr_Initialize(NULL))) FAIL("Failed to initialize the Oculus SDK\n"); |
|
|
|
|
|
|
|
//result = ExampleApp().run(); // class ExampleApp : public RiftApp : public GlfwApp, public RiftManagerApp |
|
|
|
|
|
|
|
if (!OVR_SUCCESS(ovr_Create(&session, &luid))) FAIL("Unable to create HMD session\n"); |
|
|
|
hmdDesc = ovr_GetHmdDesc(session); |
|
|
|
|
|
|
|
// RiftApp() constructor |
|
|
|
viewScaleDesc.HmdSpaceToWorldScaleInMeters = 1.0f; |
|
|
|
memset(&eyeLayer, 0, sizeof(ovrLayerEyeFov)); |
|
|
|
eyeLayer.Header.Type = ovrLayerType_EyeFov; |
|
|
|
eyeLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft; |
|
|
|
|
|
|
|
//ovr::for_each_eye([&](ovrEyeType eye) |
|
|
|
for (int eye = 0; eye < 2; eye++) |
|
|
|
{ |
|
|
|
eyeRenderDescs[eye] = ovr_GetRenderDesc(session, eye, hmdDesc.DefaultEyeFov[eye]); |
|
|
|
ovrMatrix4f ovrPerspectiveProjection = ovrMatrix4f_Projection(eyeRenderDescs[eye].Fov, 0.01f, 1000.0f, ovrProjection_ClipRangeOpenGL); |
|
|
|
//eyeProjections[eye] = ovr::toGlm(ovrPerspectiveProjection); |
|
|
|
viewScaleDesc.HmdToEyeOffset[eye] = eyeRenderDescs[eye].HmdToEyeOffset; |
|
|
|
|
|
|
|
eyeLayer.Fov[eye] = eyeRenderDescs[eye].Fov; |
|
|
|
ovrSizei eyeSize = ovr_GetFovTextureSize(session, eye, eyeLayer.Fov[eye], 1.0f); |
|
|
|
eyeLayer.Viewport[eye].Size = eyeSize; |
|
|
|
eyeLayer.Viewport[eye].Pos.x = renderTargetSize.x; |
|
|
|
eyeLayer.Viewport[eye].Pos.y = 0; |
|
|
|
|
|
|
|
renderTargetSize.y = renderTargetSize.y; // std::max(renderTargetSize.y, (uint32_t)eyeSize.h); |
|
|
|
renderTargetSize.x += eyeSize.w; |
|
|
|
} |
|
|
|
|
|
|
|
// Make the on screen window 1/4 the resolution of the render target |
|
|
|
mirrorSize = renderTargetSize; |
|
|
|
mirrorSize.x /= 2; |
|
|
|
mirrorSize.y /= 2; |
|
|
|
|
|
|
|
// GLFWApp() constructor |
|
|
|
if (!glfwInit()) FAIL("Failed to initialize GLFW\n"); // Initialize the GLFW system for creating and positioning windows |
|
|
|
glfwSetErrorCallback(ErrorCallback); |
|
|
|
|
|
|
|
////preCreate(); |
|
|
|
glfwWindowHint(GLFW_DEPTH_BITS, 16); |
|
|
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); |
|
|
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); |
|
|
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); |
|
|
|
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE); |
|
|
|
|
|
|
|
//***************window = createRenderingTarget(windowSize, windowPosition); //GLFWwindow *createRenderingTarget(uvec2 & size, ivec2 & pos) = 0; //glfw::createWindow(_mirrorSize); |
|
|
|
/* |
|
|
|
GLFWwindow *createWindow(const uvec2 &size, const ivec2 &position = ivec2(INT_MIN)) |
|
|
|
{ |
|
|
|
GLFWwindow *window = glfwCreateWindow(size.x, size.y, "glfw", NULL, NULL); // size = mirrorSize |
|
|
|
|
|
|
|
if (!window) FAIL("Unable to create rendering window\n"); |
|
|
|
|
|
|
|
if ((position.x > INT_MIN) && (position.y > INT_MIN)) // INT_MIN = -32767 // #define INT_MIN (-2147483647 - 1) |
|
|
|
{ |
|
|
|
glfwSetWindowPos(window, position.x, position.y); |
|
|
|
} |
|
|
|
|
|
|
|
return window; |
|
|
|
} |
|
|
|
*/ |
|
|
|
|
|
|
|
window = glfwCreateWindow(mirrorSize.x, mirrorSize.y, "glfw", NULL, NULL); |
|
|
|
|
|
|
|
if (!window) FAIL("Unable to create OpenGL window\n"); |
|
|
|
|
|
|
|
////postCreate(); |
|
|
|
//glfwSetWindowUserPointer(window, this); //// Useful to hack input callbacks |
|
|
|
glfwSetKeyCallback(window, KeyCallback); |
|
|
|
glfwMakeContextCurrent(window); |
|
|
|
|
|
|
|
// Initialize the OpenGL extensions |
|
|
|
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) FAIL("GLAD failed\n"); |
|
|
|
/* |
|
|
|
glewExperimental = GL_TRUE; |
|
|
|
if (0 != glewInit()) FAIL("Failed to initialize GLEW\n"); |
|
|
|
glGetError(); |
|
|
|
|
|
|
|
if (GLEW_KHR_debug) |
|
|
|
{ |
|
|
|
GLint v; |
|
|
|
glGetIntegerv(GL_CONTEXT_FLAGS, &v); |
|
|
|
if (v & GL_CONTEXT_FLAG_DEBUG_BIT) glDebugMessageCallback(glDebugCallbackHandler, this); |
|
|
|
} |
|
|
|
*/ |
|
|
|
|
|
|
|
////initGl(); |
|
|
|
{ |
|
|
|
// RiftApp::InitGL() -----> |
|
|
|
//GlfwApp::initGl(); // virtual |
|
|
|
|
|
|
|
// Disable the v-sync for buffer swap |
|
|
|
glfwSwapInterval(0); |
|
|
|
|
|
|
|
ovrTextureSwapChainDesc desc = {}; |
|
|
|
desc.Type = ovrTexture_2D; |
|
|
|
desc.ArraySize = 1; |
|
|
|
desc.Width = renderTargetSize.x; |
|
|
|
desc.Height = renderTargetSize.y; |
|
|
|
desc.MipLevels = 1; |
|
|
|
desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB; |
|
|
|
desc.SampleCount = 1; |
|
|
|
desc.StaticImage = ovrFalse; |
|
|
|
|
|
|
|
ovrResult result = ovr_CreateTextureSwapChainGL(session, &desc, &eyeTexture); |
|
|
|
eyeLayer.ColorTexture[0] = eyeTexture; |
|
|
|
|
|
|
|
if (!OVR_SUCCESS(result)) FAIL("Failed to create swap textures"); |
|
|
|
|
|
|
|
int length = 0; |
|
|
|
result = ovr_GetTextureSwapChainLength(session, eyeTexture, &length); |
|
|
|
|
|
|
|
if (!OVR_SUCCESS(result) || !length) FAIL("Unable to count swap chain textures"); |
|
|
|
|
|
|
|
for (int i = 0; i < length; ++i) |
|
|
|
{ |
|
|
|
GLuint chainTexId; |
|
|
|
ovr_GetTextureSwapChainBufferGL(session, eyeTexture, i, &chainTexId); |
|
|
|
glBindTexture(GL_TEXTURE_2D, chainTexId); |
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
|
|
|
} |
|
|
|
|
|
|
|
glBindTexture(GL_TEXTURE_2D, 0); |
|
|
|
|
|
|
|
// Set up the framebuffer object |
|
|
|
glGenFramebuffers(1, &fbo); |
|
|
|
glGenRenderbuffers(1, &depthBuffer); |
|
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); |
|
|
|
glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer); |
|
|
|
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, renderTargetSize.x, renderTargetSize.y); |
|
|
|
glBindRenderbuffer(GL_RENDERBUFFER, 0); |
|
|
|
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer); |
|
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); |
|
|
|
|
|
|
|
ovrMirrorTextureDesc mirrorDesc; |
|
|
|
memset(&mirrorDesc, 0, sizeof(mirrorDesc)); |
|
|
|
mirrorDesc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB; |
|
|
|
mirrorDesc.Width = mirrorSize.x; |
|
|
|
mirrorDesc.Height = mirrorSize.y; |
|
|
|
|
|
|
|
if (!OVR_SUCCESS(ovr_CreateMirrorTextureGL(session, &mirrorDesc, &mirrorTexture))) FAIL("Could not create mirror texture"); |
|
|
|
|
|
|
|
glGenFramebuffers(1, &mirrorFbo); |
|
|
|
|
|
|
|
// RiftApp::InitGL() <------ |
|
|
|
|
|
|
|
glClearColor(0.2f, 0.2f, 0.2f, 0.0f); |
|
|
|
glEnable(GL_DEPTH_TEST); |
|
|
|
ovr_RecenterTrackingOrigin(session); |
|
|
|
|
|
|
|
// TODO: Init cube scene --> cubeScene = std::shared_ptr<ColorCubeScene>(new ColorCubeScene()); |
|
|
|
} |
|
|
|
|
|
|
|
while (!glfwWindowShouldClose(window)) |
|
|
|
{ |
|
|
|
frame++; |
|
|
|
glfwPollEvents(); |
|
|
|
|
|
|
|
//update(); |
|
|
|
|
|
|
|
//draw(); ------> |
|
|
|
ovrPosef eyePoses[2]; |
|
|
|
ovr_GetEyePoses(session, frame, ovrTrue, viewScaleDesc.HmdToEyeOffset, eyePoses, &eyeLayer.SensorSampleTime); |
|
|
|
|
|
|
|
int curIndex; |
|
|
|
ovr_GetTextureSwapChainCurrentIndex(session, eyeTexture, &curIndex); |
|
|
|
GLuint curTexId; |
|
|
|
ovr_GetTextureSwapChainBufferGL(session, eyeTexture, curIndex, &curTexId); |
|
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); |
|
|
|
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, curTexId, 0); |
|
|
|
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
|
|
|
|
|
|
|
for (int eye = 0; eye < 2; eye++) |
|
|
|
{ |
|
|
|
glViewport(eyeLayer.Viewport[eye].Pos.x, eyeLayer.Viewport[eye].Pos.y, |
|
|
|
eyeLayer.Viewport[eye].Size.w, eyeLayer.Viewport[eye].Size.h); |
|
|
|
eyeLayer.RenderPose[eye] = eyePoses[eye]; |
|
|
|
|
|
|
|
//renderScene(_eyeProjections[eye], ovr::toGlm(eyePoses[eye])); --> cubeScene->render(projection, glm::inverse(headPose)); |
|
|
|
} |
|
|
|
|
|
|
|
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); |
|
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); |
|
|
|
ovr_CommitTextureSwapChain(session, eyeTexture); |
|
|
|
ovrLayerHeader *headerList = &eyeLayer.Header; |
|
|
|
|
|
|
|
ovr_SubmitFrame(session, frame, &viewScaleDesc, &headerList, 1); |
|
|
|
|
|
|
|
GLuint mirrorTextureId; |
|
|
|
ovr_GetMirrorTextureBufferGL(session, mirrorTexture, &mirrorTextureId); |
|
|
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, mirrorFbo); |
|
|
|
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mirrorTextureId, 0); |
|
|
|
glBlitFramebuffer(0, 0, mirrorSize.x, mirrorSize.y, 0, mirrorSize.y, mirrorSize.x, 0, GL_COLOR_BUFFER_BIT, GL_NEAREST); |
|
|
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); |
|
|
|
//draw() <------------- |
|
|
|
|
|
|
|
glfwSwapBuffers(window); //finishFrame(); |
|
|
|
} |
|
|
|
|
|
|
|
//shutdownGl(); // Delete scene: cubeScene.reset(); |
|
|
|
|
|
|
|
glfwDestroyWindow(window); |
|
|
|
glfwTerminate(); |
|
|
|
|
|
|
|
ovr_Destroy(session); |
|
|
|
ovr_Shutdown(); |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |