diff options
| author | Joshua Reisenauer <kd7tck@msn.com> | 2016-06-03 14:01:04 -0700 |
|---|---|---|
| committer | Joshua Reisenauer <kd7tck@msn.com> | 2016-06-03 14:01:04 -0700 |
| commit | e3b248545353720090f28a6c4e8a8c8a34bb1269 (patch) | |
| tree | 59e40c6862a88affa8bcdba4979c6a8956581ac1 /src | |
| parent | 96fa716525e22f9f75575f2dc1b431c58567d8a1 (diff) | |
| parent | 60232810d83c7ea3a52491f0b20444003be53358 (diff) | |
| download | raylib-e3b248545353720090f28a6c4e8a8c8a34bb1269.tar.gz raylib-e3b248545353720090f28a6c4e8a8c8a34bb1269.zip | |
Merge remote-tracking branch 'refs/remotes/raysan5/develop' into develop
Diffstat (limited to 'src')
| -rw-r--r-- | src/core.c | 482 | ||||
| -rw-r--r-- | src/gestures.c | 8 | ||||
| -rw-r--r-- | src/raygui.c | 3 | ||||
| -rw-r--r-- | src/raylib.h | 17 |
4 files changed, 474 insertions, 36 deletions
@@ -9,6 +9,7 @@ * PLATFORM_ANDROID - Only OpenGL ES 2.0 devices * PLATFORM_RPI - Rapsberry Pi (tested on Raspbian) * PLATFORM_WEB - Emscripten, HTML5 +* PLATFORM_OCULUS - Oculus Rift CV1 (with desktop mirror) * * On PLATFORM_DESKTOP, the external lib GLFW3 (www.glfw.com) is used to manage graphic * device, OpenGL context and input on multiple operating systems (Windows, Linux, OSX). @@ -53,10 +54,18 @@ #include <string.h> // String function definitions, memset() #include <errno.h> // Macros for reporting and retrieving error conditions through error codes +#if defined(PLATFORM_OCULUS) + #define PLATFORM_DESKTOP // Enable PLATFORM_DESKTOP code-base +#endif + #if defined(PLATFORM_DESKTOP) #include "glad.h" // GLAD library: Manage OpenGL headers and extensions #endif +#if defined(PLATFORM_OCULUS) + #include "../examples/oculus_glfw_sample/OculusSDK/LibOVR/Include/OVR_CAPI_GL.h" // Oculus SDK for OpenGL +#endif + #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) //#define GLFW_INCLUDE_NONE // Disable the standard OpenGL header inclusion on GLFW3 #include <GLFW/glfw3.h> // GLFW3 library: Windows, OpenGL context and Input management @@ -129,7 +138,31 @@ //---------------------------------------------------------------------------------- // Types and Structures Definition //---------------------------------------------------------------------------------- -// ... +#if defined(PLATFORM_OCULUS) +typedef struct OculusBuffer { + ovrTextureSwapChain textureChain; + GLuint depthId; + GLuint fboId; + int width; + int height; +} OculusBuffer; + +typedef struct OculusMirror { + ovrMirrorTexture texture; + GLuint fboId; + int width; + int height; +} OculusMirror; + +typedef struct OculusLayer { + ovrViewScaleDesc viewScaleDesc; + ovrLayerEyeFov eyeLayer; // layer 0 + //ovrLayerQuad quadLayer; // TODO: layer 1: '2D' quad for GUI + Matrix eyeProjections[2]; + int width; + int height; +} OculusLayer; +#endif //---------------------------------------------------------------------------------- // Global Variables Definition @@ -137,7 +170,9 @@ #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) static GLFWwindow *window; // Native window (graphic device) static bool windowMinimized = false; -#elif defined(PLATFORM_ANDROID) +#endif + +#if defined(PLATFORM_ANDROID) static struct android_app *app; // Android activity static struct android_poll_source *source; // Android events polling source static int ident, events; // Android ALooper_pollAll() variables @@ -149,7 +184,9 @@ static bool contextRebindRequired = false; // Used to know context rebind r static int previousButtonState[128] = { 1 }; // Required to check if button pressed/released once static int currentButtonState[128] = { 1 }; // Required to check if button pressed/released once -#elif defined(PLATFORM_RPI) +#endif + +#if defined(PLATFORM_RPI) static EGL_DISPMANX_WINDOW_T nativeWindow; // Native window (graphic device) // Keyboard input variables @@ -180,6 +217,17 @@ static uint64_t baseTime; // Base time measure for hi-res time static bool windowShouldClose = false; // Flag to set window for closing #endif +#if defined(PLATFORM_OCULUS) +// OVR device variables +static ovrSession session; +static ovrHmdDesc hmdDesc; +static ovrGraphicsLuid luid; +static OculusLayer layer; +static OculusBuffer buffer; +static OculusMirror mirror; +static unsigned int frameIndex = 0; +#endif + static unsigned int displayWidth, displayHeight; // Display width and height (monitor, device-screen, LCD, ...) static int screenWidth, screenHeight; // Screen width and height (used render area) static int renderWidth, renderHeight; // Framebuffer width and height (render area) @@ -189,6 +237,7 @@ static int renderOffsetX = 0; // Offset X from render area (must b static int renderOffsetY = 0; // Offset Y from render area (must be divided by 2) static bool fullscreen = false; // Fullscreen mode (useful only for PLATFORM_DESKTOP) static Matrix downscaleView; // Matrix to downscale view (in case screen size bigger than display size) +static Matrix cameraView; // Store camera view matrix (required for Oculus Rift) #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB) static const char *windowTitle; // Window text title... @@ -287,6 +336,19 @@ static void InitGamepad(void); // Init raw gamepad inpu static void *GamepadThread(void *arg); // Mouse reading thread #endif +#if defined(PLATFORM_OCULUS) +// Oculus Rift functions +static Matrix FromOvrMatrix(ovrMatrix4f ovrM); +static OculusBuffer LoadOculusBuffer(ovrSession session, int width, int height); +static void UnloadOculusBuffer(ovrSession session, OculusBuffer buffer); +static void SetOculusBuffer(ovrSession session, OculusBuffer buffer); +static void UnsetOculusBuffer(OculusBuffer buffer); +static OculusMirror LoadOculusMirror(ovrSession session, int width, int height); // Load Oculus mirror buffers +static void UnloadOculusMirror(ovrSession session, OculusMirror mirror); // Unload Oculus mirror buffers +static void BlitOculusMirror(ovrSession session, OculusMirror mirror); +static OculusLayer InitOculusLayer(ovrSession session); +#endif + //---------------------------------------------------------------------------------- // Module Functions Definition - Window and OpenGL Context Functions //---------------------------------------------------------------------------------- @@ -335,6 +397,11 @@ void InitWindow(int width, int height, const char *title) //emscripten_set_gamepaddisconnected_callback(NULL, 1, EmscriptenInputCallback); #endif +#if defined(PLATFORM_OCULUS) + // Recenter OVR tracking origin + ovr_RecenterTrackingOrigin(session); +#endif + mousePosition.x = (float)screenWidth/2.0f; mousePosition.y = (float)screenHeight/2.0f; @@ -345,8 +412,9 @@ void InitWindow(int width, int height, const char *title) LogoAnimation(); } } +#endif -#elif defined(PLATFORM_ANDROID) +#if defined(PLATFORM_ANDROID) // Android activity initialization void InitWindow(int width, int height, struct android_app *state) { @@ -420,7 +488,9 @@ void CloseWindow(void) #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) glfwDestroyWindow(window); glfwTerminate(); -#elif defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) +#endif + +#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) // Close surface, context and display if (display != EGL_NO_DISPLAY) { @@ -443,9 +513,71 @@ void CloseWindow(void) } #endif +#if defined(PLATFORM_OCULUS) + ovr_Destroy(session); // Must be called after glfwTerminate() + ovr_Shutdown(); +#endif + TraceLog(INFO, "Window closed successfully"); } +#if defined(PLATFORM_OCULUS) +// Init Oculus Rift device +// NOTE: Device initialization should be done before window creation? +void InitOculusDevice(void) +{ + ovrResult result = ovr_Initialize(NULL); + if (OVR_FAILURE(result)) TraceLog(ERROR, "OVR: Could not initialize Oculus device"); + + result = ovr_Create(&session, &luid); + if (OVR_FAILURE(result)) + { + TraceLog(WARNING, "OVR: Could not create Oculus session"); + ovr_Shutdown(); + } + + hmdDesc = ovr_GetHmdDesc(session); + + TraceLog(INFO, "OVR: Product Name: %s", hmdDesc.ProductName); + TraceLog(INFO, "OVR: Manufacturer: %s", hmdDesc.Manufacturer); + TraceLog(INFO, "OVR: Product ID: %i", hmdDesc.ProductId); + TraceLog(INFO, "OVR: Product Type: %i", hmdDesc.Type); + TraceLog(INFO, "OVR: Serian Number: %s", hmdDesc.SerialNumber); + TraceLog(INFO, "OVR: Resolution: %ix%i", hmdDesc.Resolution.w, hmdDesc.Resolution.h); + + screenWidth = hmdDesc.Resolution.w/2; + screenHeight = hmdDesc.Resolution.h/2; + + // Initialize Oculus Buffers + layer = InitOculusLayer(session); + buffer = LoadOculusBuffer(session, layer.width, layer.height); + mirror = LoadOculusMirror(session, hmdDesc.Resolution.w/2, hmdDesc.Resolution.h/2); + layer.eyeLayer.ColorTexture[0] = buffer.textureChain; //SetOculusLayerTexture(eyeLayer, buffer.textureChain); +} + +// Close Oculus Rift device +void CloseOculusDevice(void) +{ + UnloadOculusMirror(session, mirror); // Unload Oculus mirror buffer + UnloadOculusBuffer(session, buffer); // Unload Oculus texture buffers + + ovr_Destroy(session); // Must be called after glfwTerminate() --> REALLY??? + ovr_Shutdown(); +} + +// Update Oculus Rift tracking (position and orientation) +void UpdateOculusTracking(void) +{ + frameIndex++; + + ovrPosef eyePoses[2]; + ovr_GetEyePoses(session, frameIndex, ovrTrue, layer.viewScaleDesc.HmdToEyeOffset, eyePoses, &layer.eyeLayer.SensorSampleTime); + + layer.eyeLayer.RenderPose[0] = eyePoses[0]; + layer.eyeLayer.RenderPose[1] = eyePoses[1]; +} +#endif + // Detect if KEY_ESCAPE pressed or Close icon pressed bool WindowShouldClose(void) { @@ -454,7 +586,9 @@ bool WindowShouldClose(void) while (windowMinimized) glfwPollEvents(); return (glfwWindowShouldClose(window)); -#elif defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) +#endif + +#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) return windowShouldClose; #endif } @@ -480,7 +614,9 @@ void ToggleFullscreen(void) glfwDestroyWindow(window); // Destroy the current window (we will recreate it!) InitWindow(screenWidth, screenHeight, windowTitle); -#elif defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) +#endif + +#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) TraceLog(WARNING, "Could not toggle to windowed mode"); #endif } @@ -510,6 +646,18 @@ void BeginDrawing(void) currentTime = GetTime(); // Number of elapsed seconds since InitTimer() was called updateTime = currentTime - previousTime; previousTime = currentTime; + +#if defined(PLATFORM_OCULUS) + frameIndex++; + + ovrPosef eyePoses[2]; + ovr_GetEyePoses(session, frameIndex, ovrTrue, layer.viewScaleDesc.HmdToEyeOffset, eyePoses, &layer.eyeLayer.SensorSampleTime); + + layer.eyeLayer.RenderPose[0] = eyePoses[0]; + layer.eyeLayer.RenderPose[1] = eyePoses[1]; + + SetOculusBuffer(session, buffer); +#endif rlClearScreenBuffers(); // Clear current framebuffers rlLoadIdentity(); // Reset current matrix (MODELVIEW) @@ -522,10 +670,51 @@ void BeginDrawing(void) // End canvas drawing and Swap Buffers (Double Buffering) void EndDrawing(void) { - rlglDraw(); // Draw Buffers (Only OpenGL 3+ and ES2) +#if defined(PLATFORM_OCULUS) + for (int eye = 0; eye < 2; eye++) + { + rlViewport(layer.eyeLayer.Viewport[eye].Pos.x, layer.eyeLayer.Viewport[eye].Pos.y, layer.eyeLayer.Viewport[eye].Size.w, layer.eyeLayer.Viewport[eye].Size.h); - SwapBuffers(); // Copy back buffer to front buffer + Quaternion eyeRPose = (Quaternion){ layer.eyeLayer.RenderPose[eye].Orientation.x, + layer.eyeLayer.RenderPose[eye].Orientation.y, + layer.eyeLayer.RenderPose[eye].Orientation.z, + layer.eyeLayer.RenderPose[eye].Orientation.w }; + QuaternionInvert(&eyeRPose); + Matrix eyeOrientation = QuaternionToMatrix(eyeRPose); + Matrix eyeTranslation = MatrixTranslate(-layer.eyeLayer.RenderPose[eye].Position.x, + -layer.eyeLayer.RenderPose[eye].Position.y, + -layer.eyeLayer.RenderPose[eye].Position.z); + + Matrix eyeView = MatrixMultiply(eyeTranslation, eyeOrientation); + Matrix modelEyeView = MatrixMultiply(cameraView, eyeView); // Using internal camera modelview matrix + SetMatrixModelview(modelEyeView); + SetMatrixProjection(layer.eyeProjections[eye]); +#endif + + rlglDraw(); // Draw Buffers (Only OpenGL 3+ and ES2) + +#if defined(PLATFORM_OCULUS) + } + + UnsetOculusBuffer(buffer); + + ovr_CommitTextureSwapChain(session, buffer.textureChain); + + ovrLayerHeader *layers = &layer.eyeLayer.Header; + ovr_SubmitFrame(session, frameIndex, &layer.viewScaleDesc, &layers, 1); + + // Blit mirror texture to back buffer + BlitOculusMirror(session, mirror); + + // Get session status information + ovrSessionStatus sessionStatus; + ovr_GetSessionStatus(session, &sessionStatus); + if (sessionStatus.ShouldQuit) TraceLog(WARNING, "OVR: Session should quit..."); + if (sessionStatus.ShouldRecenter) ovr_RecenterTrackingOrigin(session); +#endif + + SwapBuffers(); // Copy back buffer to front buffer PollInputEvents(); // Poll user events // Frame time control system @@ -595,8 +784,8 @@ void Begin3dMode(Camera camera) rlLoadIdentity(); // Reset current matrix (MODELVIEW) // Setup Camera view - Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up); - rlMultMatrixf(MatrixToFloat(matView)); // Multiply MODELVIEW matrix by view matrix (camera) + cameraView = MatrixLookAt(camera.position, camera.target, camera.up); + rlMultMatrixf(MatrixToFloat(cameraView)); // Multiply MODELVIEW matrix by view matrix (camera) rlEnableDepthTest(); // Enable DEPTH_TEST for 3D } @@ -1437,6 +1626,30 @@ static void InitDisplay(int width, int height) // Downscale matrix is required in case desired screen area is bigger than display area downscaleView = MatrixIdentity(); +#if defined(PLATFORM_OCULUS) + ovrResult result = ovr_Initialize(NULL); + if (OVR_FAILURE(result)) TraceLog(ERROR, "OVR: Could not initialize Oculus device"); + + result = ovr_Create(&session, &luid); + if (OVR_FAILURE(result)) + { + TraceLog(WARNING, "OVR: Could not create Oculus session"); + ovr_Shutdown(); + } + + hmdDesc = ovr_GetHmdDesc(session); + + TraceLog(INFO, "OVR: Product Name: %s", hmdDesc.ProductName); + TraceLog(INFO, "OVR: Manufacturer: %s", hmdDesc.Manufacturer); + TraceLog(INFO, "OVR: Product ID: %i", hmdDesc.ProductId); + TraceLog(INFO, "OVR: Product Type: %i", hmdDesc.Type); + TraceLog(INFO, "OVR: Serian Number: %s", hmdDesc.SerialNumber); + TraceLog(INFO, "OVR: Resolution: %ix%i", hmdDesc.Resolution.w, hmdDesc.Resolution.h); + + screenWidth = hmdDesc.Resolution.w/2; + screenHeight = hmdDesc.Resolution.h/2; +#endif + #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) glfwSetErrorCallback(ErrorCallback); @@ -1565,14 +1778,17 @@ static void InitDisplay(int width, int height) #endif glfwMakeContextCurrent(window); +#if defined(PLATFORM_OCULUS) + glfwSwapInterval(0); +#endif #if defined(PLATFORM_DESKTOP) - // Extensions initialization for OpenGL 3.3 + // Load OpenGL 3.3 extensions using GLAD if (rlGetVersion() == OPENGL_33) { - // NOTE: glad is generated and contains only required OpenGL version and Core extensions - //if (!gladLoadGL()) TraceLog(ERROR, "Failed to initialize glad\n"); - if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) TraceLog(ERROR, "Failed to initialize glad\n"); // No GLFW3 in this module... + // NOTE: glad is generated and contains only required OpenGL 3.3 Core extensions + if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) TraceLog(WARNING, "GLAD: Cannot load OpenGL extensions"); + else TraceLog(INFO, "GLAD: OpenGL extensions loaded successfully"); if (GLAD_GL_VERSION_3_3) TraceLog(INFO, "OpenGL 3.3 Core profile supported"); else TraceLog(ERROR, "OpenGL 3.3 Core profile not supported"); @@ -1746,13 +1962,16 @@ static void InitDisplay(int width, int height) static void InitGraphics(void) { rlglInit(); // Init rlgl - + rlglInitGraphics(renderOffsetX, renderOffsetY, renderWidth, renderHeight); // Init graphics (OpenGL stuff) + #if defined(PLATFORM_OCULUS) - //rlglInitOculus(); // Init rlgl for Oculus Rift (required textures) + // Initialize Oculus Buffers + layer = InitOculusLayer(session); + buffer = LoadOculusBuffer(session, layer.width, layer.height); + mirror = LoadOculusMirror(session, hmdDesc.Resolution.w/2, hmdDesc.Resolution.h/2); + layer.eyeLayer.ColorTexture[0] = buffer.textureChain; //SetOculusLayerTexture(eyeLayer, buffer.textureChain); #endif - rlglInitGraphics(renderOffsetX, renderOffsetY, renderWidth, renderHeight); // Init graphics (OpenGL stuff) - ClearBackground(RAYWHITE); // Default background color for raylib games :P #if defined(PLATFORM_ANDROID) @@ -1860,7 +2079,9 @@ static double GetTime(void) { #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) return glfwGetTime(); -#elif defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) +#endif + +#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); uint64_t time = (uint64_t)ts.tv_sec*1000000000LLU + (uint64_t)ts.tv_nsec; @@ -1928,8 +2149,9 @@ static void PollInputEvents(void) currentMouseWheelY = 0; glfwPollEvents(); // Register keyboard/mouse events... and window events! -#elif defined(PLATFORM_ANDROID) +#endif +#if defined(PLATFORM_ANDROID) // Register previous keys states for (int i = 0; i < 128; i++) previousButtonState[i] = currentButtonState[i]; @@ -1948,8 +2170,9 @@ static void PollInputEvents(void) //ANativeActivity_finish(app->activity); } } -#elif defined(PLATFORM_RPI) +#endif +#if defined(PLATFORM_RPI) // NOTE: Mouse input events polling is done asynchonously in another pthread - MouseThread() // NOTE: Keyboard reading could be done using input_event(s) reading or just read from stdin, @@ -1957,7 +2180,6 @@ static void PollInputEvents(void) ProcessKeyboard(); // NOTE: Gamepad (Joystick) input events polling is done asynchonously in another pthread - GamepadThread() - #endif } @@ -1966,7 +2188,9 @@ static void SwapBuffers(void) { #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) glfwSwapBuffers(window); -#elif defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) +#endif + +#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) eglSwapBuffers(display, surface); #endif } @@ -2450,7 +2674,7 @@ static EM_BOOL EmscriptenInputCallback(int eventType, const EmscriptenTouchEvent gestureEvent.position[1].y /= (float)GetScreenHeight(); // Gesture data is sent to gestures system for processing - ProcessGestureEvent(gestureEvent); // Process obtained gestures data + ProcessGestureEvent(gestureEvent); return 1; } @@ -2774,6 +2998,214 @@ static void *GamepadThread(void *arg) } #endif + +#if defined(PLATFORM_OCULUS) +// Convert from Oculus ovrMatrix4f struct to raymath Matrix struct +static Matrix FromOvrMatrix(ovrMatrix4f ovrmat) +{ + Matrix rmat; + + rmat.m0 = ovrmat.M[0][0]; + rmat.m1 = ovrmat.M[1][0]; + rmat.m2 = ovrmat.M[2][0]; + rmat.m3 = ovrmat.M[3][0]; + rmat.m4 = ovrmat.M[0][1]; + rmat.m5 = ovrmat.M[1][1]; + rmat.m6 = ovrmat.M[2][1]; + rmat.m7 = ovrmat.M[3][1]; + rmat.m8 = ovrmat.M[0][2]; + rmat.m9 = ovrmat.M[1][2]; + rmat.m10 = ovrmat.M[2][2]; + rmat.m11 = ovrmat.M[3][2]; + rmat.m12 = ovrmat.M[0][3]; + rmat.m13 = ovrmat.M[1][3]; + rmat.m14 = ovrmat.M[2][3]; + rmat.m15 = ovrmat.M[3][3]; + + MatrixTranspose(&rmat); + + return rmat; +} + +// Load Oculus required buffers: texture-swap-chain, fbo, texture-depth +static OculusBuffer LoadOculusBuffer(ovrSession session, int width, int height) +{ + OculusBuffer buffer; + buffer.width = width; + buffer.height = height; + + // Create OVR texture chain + ovrTextureSwapChainDesc desc = {}; + desc.Type = ovrTexture_2D; + desc.ArraySize = 1; + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB; // Requires glEnable(GL_FRAMEBUFFER_SRGB); + desc.SampleCount = 1; + desc.StaticImage = ovrFalse; + + ovrResult result = ovr_CreateTextureSwapChainGL(session, &desc, &buffer.textureChain); + + if (!OVR_SUCCESS(result)) TraceLog(WARNING, "OVR: Failed to create swap textures buffer"); + + int textureCount = 0; + ovr_GetTextureSwapChainLength(session, buffer.textureChain, &textureCount); + + if (!OVR_SUCCESS(result) || !textureCount) TraceLog(WARNING, "OVR: Unable to count swap chain textures"); + + for (int i = 0; i < textureCount; ++i) + { + GLuint chainTexId; + ovr_GetTextureSwapChainBufferGL(session, buffer.textureChain, 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); + + /* + // Setup framebuffer object (using depth texture) + glGenFramebuffers(1, &buffer.fboId); + glGenTextures(1, &buffer.depthId); + glBindTexture(GL_TEXTURE_2D, buffer.depthId); + 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); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, buffer.width, buffer.height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); + */ + + // Setup framebuffer object (using depth renderbuffer) + glGenFramebuffers(1, &buffer.fboId); + glGenRenderbuffers(1, &buffer.depthId); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, buffer.fboId); + glBindRenderbuffer(GL_RENDERBUFFER, buffer.depthId); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, buffer.width, buffer.height); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, buffer.depthId); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + + return buffer; +} + +// Unload texture required buffers +static void UnloadOculusBuffer(ovrSession session, OculusBuffer buffer) +{ + if (buffer.textureChain) + { + ovr_DestroyTextureSwapChain(session, buffer.textureChain); + buffer.textureChain = NULL; + } + + if (buffer.depthId != 0) glDeleteTextures(1, &buffer.depthId); + if (buffer.fboId != 0) glDeleteFramebuffers(1, &buffer.fboId); +} + +// Set current Oculus buffer +static void SetOculusBuffer(ovrSession session, OculusBuffer buffer) +{ + GLuint currentTexId; + int currentIndex; + + ovr_GetTextureSwapChainCurrentIndex(session, buffer.textureChain, ¤tIndex); + ovr_GetTextureSwapChainBufferGL(session, buffer.textureChain, currentIndex, ¤tTexId); + + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, buffer.fboId); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, currentTexId, 0); + //glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, buffer.depthId, 0); // Already binded + + //glViewport(0, 0, buffer.width, buffer.height); // Useful if rendering to separate framebuffers (every eye) + //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // Required if OculusBuffer format is OVR_FORMAT_R8G8B8A8_UNORM_SRGB + glEnable(GL_FRAMEBUFFER_SRGB); +} + +// Unset Oculus buffer +static void UnsetOculusBuffer(OculusBuffer buffer) +{ + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); +} + +// Load Oculus mirror buffers +static OculusMirror LoadOculusMirror(ovrSession session, int width, int height) +{ + OculusMirror mirror; + mirror.width = width; + mirror.height = height; + + ovrMirrorTextureDesc mirrorDesc; + memset(&mirrorDesc, 0, sizeof(mirrorDesc)); + mirrorDesc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB; + mirrorDesc.Width = mirror.width; + mirrorDesc.Height = mirror.height; + + if (!OVR_SUCCESS(ovr_CreateMirrorTextureGL(session, &mirrorDesc, &mirror.texture))) TraceLog(WARNING, "Could not create mirror texture"); + + glGenFramebuffers(1, &mirror.fboId); + + return mirror; +} + +// Unload Oculus mirror buffers +static void UnloadOculusMirror(ovrSession session, OculusMirror mirror) +{ + if (mirror.fboId != 0) glDeleteFramebuffers(1, &mirror.fboId); + if (mirror.texture) ovr_DestroyMirrorTexture(session, mirror.texture); +} + +static void BlitOculusMirror(ovrSession session, OculusMirror mirror) +{ + GLuint mirrorTextureId; + + ovr_GetMirrorTextureBufferGL(session, mirror.texture, &mirrorTextureId); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, mirror.fboId); + glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mirrorTextureId, 0); + glBlitFramebuffer(0, 0, mirror.width, mirror.height, 0, mirror.height, mirror.width, 0, GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); +} + +// Requires: session, hmdDesc +static OculusLayer InitOculusLayer(ovrSession session) +{ + OculusLayer layer = { 0 }; + + layer.viewScaleDesc.HmdSpaceToWorldScaleInMeters = 1.0f; + + memset(&layer.eyeLayer, 0, sizeof(ovrLayerEyeFov)); + layer.eyeLayer.Header.Type = ovrLayerType_EyeFov; + layer.eyeLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft; + + ovrEyeRenderDesc eyeRenderDescs[2]; + + 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, 10000.0f, ovrProjection_None); //ovrProjection_ClipRangeOpenGL); + layer.eyeProjections[eye] = FromOvrMatrix(ovrPerspectiveProjection); // NOTE: struct ovrMatrix4f { float M[4][4] } --> struct Matrix + + layer.viewScaleDesc.HmdToEyeOffset[eye] = eyeRenderDescs[eye].HmdToEyeOffset; + layer.eyeLayer.Fov[eye] = eyeRenderDescs[eye].Fov; + + ovrSizei eyeSize = ovr_GetFovTextureSize(session, eye, layer.eyeLayer.Fov[eye], 1.0f); + layer.eyeLayer.Viewport[eye].Size = eyeSize; + layer.eyeLayer.Viewport[eye].Pos.x = layer.width; + layer.eyeLayer.Viewport[eye].Pos.y = 0; + + layer.height = eyeSize.h; //std::max(renderTargetSize.y, (uint32_t)eyeSize.h); + layer.width += eyeSize.w; + } + + return layer; +} +#endif + // Plays raylib logo appearing animation static void LogoAnimation(void) { diff --git a/src/gestures.c b/src/gestures.c index d3b85d12..90371620 100644 --- a/src/gestures.c +++ b/src/gestures.c @@ -46,12 +46,12 @@ //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- -#define FORCE_TO_SWIPE 0.0005f // Measured in normalized pixels / time -#define MINIMUM_DRAG 0.015f // Measured in normalized pixels [0..1] -#define MINIMUM_PINCH 0.005f // Measured in normalized pixels [0..1] +#define FORCE_TO_SWIPE 0.0005f // Measured in normalized screen units/time +#define MINIMUM_DRAG 0.015f // Measured in normalized screen units (0.0f to 1.0f) +#define MINIMUM_PINCH 0.005f // Measured in normalized screen units (0.0f to 1.0f) #define TAP_TIMEOUT 300 // Time in milliseconds #define PINCH_TIMEOUT 300 // Time in milliseconds -#define DOUBLETAP_RANGE 0.03f +#define DOUBLETAP_RANGE 0.03f // Measured in normalized screen units (0.0f to 1.0f) //---------------------------------------------------------------------------------- // Types and Structures Definition diff --git a/src/raygui.c b/src/raygui.c index eaf15224..5064f123 100644 --- a/src/raygui.c +++ b/src/raygui.c @@ -177,7 +177,7 @@ static bool CheckCollisionPointRec(Vector2 point, Rectangle rec); // Check if p static const char *FormatText(const char *text, ...); // Formatting of text with variables to 'embed' // NOTE: raygui depend on some raylib input and drawing functions -// TODO: Set your own functions +// TODO: Replace by your own functions static Vector2 GetMousePosition() { return (Vector2){ 0.0f, 0.0f }; } static int IsMouseButtonDown(int button) { return 0; } static int IsMouseButtonPressed(int button) { return 0; } @@ -191,7 +191,6 @@ static int MeasureText(const char *text, int fontSize) { return 0; } static void DrawText(const char *text, int posX, int posY, int fontSize, Color color) { } static void DrawRectangleRec(Rectangle rec, Color color) { } static void DrawRectangle(int posX, int posY, int width, int height, Color color) { DrawRectangleRec((Rectangle){ posX, posY, width, height }, color); } - #endif //---------------------------------------------------------------------------------- diff --git a/src/raylib.h b/src/raylib.h index efd96a67..706c4f4a 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -64,6 +64,7 @@ //#define PLATFORM_ANDROID // Android device //#define PLATFORM_RPI // Raspberry Pi //#define PLATFORM_WEB // HTML5 (emscripten, asm.js) +//#define PLATFORM_OCULUS // Oculus Rift CV1 // Security check in case no PLATFORM_* defined #if !defined(PLATFORM_DESKTOP) && !defined(PLATFORM_ANDROID) && !defined(PLATFORM_RPI) && !defined(PLATFORM_WEB) @@ -71,7 +72,7 @@ #endif #if defined(PLATFORM_ANDROID) - typedef struct android_app; // Define android_app struct (android_native_app_glue.h) + typedef struct android_app; // Define android_app struct (android_native_app_glue.h) #endif //---------------------------------------------------------------------------------- @@ -448,14 +449,14 @@ typedef enum { LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT } LightType; // Ray type (useful for raycast) typedef struct Ray { - Vector3 position; - Vector3 direction; + Vector3 position; // Ray position (origin) + Vector3 direction; // Ray direction } Ray; // Sound source type typedef struct Sound { - unsigned int source; - unsigned int buffer; + unsigned int source; // Sound audio source id + unsigned int buffer; // Sound audio buffer id } Sound; // Wave type, defines audio wave data @@ -578,6 +579,12 @@ void InitWindow(int width, int height, struct android_app *state); // Init Andr void InitWindow(int width, int height, const char *title); // Initialize Window and OpenGL Graphics #endif +#if defined(PLATFORM_OCULUS) +void InitOculusDevice(void); // Init Oculus Rift device +void CloseOculusDevice(void); // Close Oculus Rift device +void UpdateOculusTracking(void); // Update Oculus Rift tracking (position and orientation) +#endif + void CloseWindow(void); // Close Window and Terminate Context bool WindowShouldClose(void); // Detect if KEY_ESCAPE pressed or Close icon pressed bool IsWindowMinimized(void); // Detect if window has been minimized (or lost focus) |
