From 5f4449f0a199ae2f1750eb60f2fcc4dd8c41ab79 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Thu, 9 Jun 2016 20:02:15 +0200 Subject: Removed physac functions from raylib header --- src/raylib.h | 49 ------------------------------------------------- 1 file changed, 49 deletions(-) (limited to 'src/raylib.h') diff --git a/src/raylib.h b/src/raylib.h index 706c4f4a..bfcb9bf5 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -527,40 +527,6 @@ typedef struct GestureEvent { // Camera system modes typedef enum { CAMERA_CUSTOM = 0, CAMERA_FREE, CAMERA_ORBITAL, CAMERA_FIRST_PERSON, CAMERA_THIRD_PERSON } CameraMode; -typedef enum { COLLIDER_CIRCLE, COLLIDER_RECTANGLE } ColliderType; - -typedef struct Transform { - Vector2 position; - float rotation; // Radians (not used) - Vector2 scale; // Just for rectangle physic objects, for circle physic objects use collider radius and keep scale as { 0, 0 } -} Transform; - -typedef struct Rigidbody { - bool enabled; // Acts as kinematic state (collisions are calculated anyway) - float mass; - Vector2 acceleration; - Vector2 velocity; - bool applyGravity; - bool isGrounded; - float friction; // Normalized value - float bounciness; -} Rigidbody; - -typedef struct Collider { - bool enabled; - ColliderType type; - Rectangle bounds; // Used for COLLIDER_RECTANGLE - int radius; // Used for COLLIDER_CIRCLE -} Collider; - -typedef struct PhysicObjectData { - unsigned int id; - Transform transform; - Rigidbody rigidbody; - Collider collider; - bool enabled; -} PhysicObjectData, *PhysicObject; - #ifdef __cplusplus extern "C" { // Prevents name mangling of functions #endif @@ -886,21 +852,6 @@ void EndBlendMode(void); // End blend Light CreateLight(int type, Vector3 position, Color diffuse); // Create a new light, initialize it and add to pool void DestroyLight(Light light); // Destroy a light and take it out of the list -//---------------------------------------------------------------------------------- -// Physics System Functions (Module: physac) -//---------------------------------------------------------------------------------- -void InitPhysics(Vector2 gravity); // Initializes pointers array (just pointers, fixed size) -void UpdatePhysics(); // Update physic objects, calculating physic behaviours and collisions detection -void ClosePhysics(); // Unitialize all physic objects and empty the objects pool - -PhysicObject CreatePhysicObject(Vector2 position, float rotation, Vector2 scale); // Create a new physic object dinamically, initialize it and add to pool -void DestroyPhysicObject(PhysicObject pObj); // Destroy a specific physic object and take it out of the list - -void ApplyForce(PhysicObject pObj, Vector2 force); // Apply directional force to a physic object -void ApplyForceAtPosition(Vector2 position, float force, float radius); // Apply radial force to all physic objects in range - -Rectangle TransformToRectangle(Transform transform); // Convert Transform data type to Rectangle (position and scale) - //------------------------------------------------------------------------------------ // Audio Loading and Playing Functions (Module: audio) //------------------------------------------------------------------------------------ -- cgit v1.2.3 From 47afda2549cdab0429047fcc64540a4ed5d0ede7 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Tue, 14 Jun 2016 11:55:32 +0200 Subject: Removed useless function: GetGestureDetected() Use instead: IsGestureDetected() --- src/gestures.c | 7 ------- src/gestures.h | 7 +++---- src/raylib.h | 7 +++---- 3 files changed, 6 insertions(+), 15 deletions(-) (limited to 'src/raylib.h') diff --git a/src/gestures.c b/src/gestures.c index 90371620..8e6005b3 100644 --- a/src/gestures.c +++ b/src/gestures.c @@ -298,13 +298,6 @@ bool IsGestureDetected(int gesture) else return false; } -// Check gesture type -int GetGestureDetected(void) -{ - // Get current gesture only if enabled - return (enabledGestures & currentGesture); -} - // Get number of touch points int GetTouchPointsCount(void) { diff --git a/src/gestures.h b/src/gestures.h index f2bdaba4..ab5287cc 100644 --- a/src/gestures.h +++ b/src/gestures.h @@ -90,13 +90,12 @@ extern "C" { // Prevents name mangling of functions //---------------------------------------------------------------------------------- // Module Functions Declaration //---------------------------------------------------------------------------------- +void SetGesturesEnabled(unsigned int gestureFlags); // Enable a set of gestures using flags +bool IsGestureDetected(int gesture); // Check if a gesture have been detected void ProcessGestureEvent(GestureEvent event); // Process gesture event and translate it into gestures void UpdateGestures(void); // Update gestures detected (must be called every frame) -bool IsGestureDetected(int gesture); // Check if a gesture have been detected -int GetGestureDetected(void); // Get latest detected gesture -void SetGesturesEnabled(unsigned int gestureFlags); // Enable a set of gestures using flags -int GetTouchPointsCount(void); // Get touch points count +int GetTouchPointsCount(void); // Get touch points count float GetGestureHoldDuration(void); // Get gesture hold time in milliseconds Vector2 GetGestureDragVector(void); // Get gesture drag vector float GetGestureDragAngle(void); // Get gesture drag angle diff --git a/src/raylib.h b/src/raylib.h index bfcb9bf5..343e86f1 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -644,13 +644,12 @@ bool IsButtonReleased(int button); // Detect if an android //------------------------------------------------------------------------------------ // Gestures and Touch Handling Functions (Module: gestures) //------------------------------------------------------------------------------------ +void SetGesturesEnabled(unsigned int gestureFlags); // Enable a set of gestures using flags +bool IsGestureDetected(int gesture); // Check if a gesture have been detected void ProcessGestureEvent(GestureEvent event); // Process gesture event and translate it into gestures void UpdateGestures(void); // Update gestures detected (called automatically in PollInputEvents()) -bool IsGestureDetected(int gesture); // Check if a gesture have been detected -int GetGestureDetected(void); // Get latest detected gesture -void SetGesturesEnabled(unsigned int gestureFlags); // Enable a set of gestures using flags -int GetTouchPointsCount(void); // Get touch points count +int GetTouchPointsCount(void); // Get touch points count float GetGestureHoldDuration(void); // Get gesture hold time in milliseconds Vector2 GetGestureDragVector(void); // Get gesture drag vector float GetGestureDragAngle(void); // Get gesture drag angle -- cgit v1.2.3 From 3d6be7fd8000bf7bd9da0b9ad8764021f86c0d01 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Tue, 14 Jun 2016 12:01:57 +0200 Subject: Added GetGestureDetected() again... Required by gestures example.... --- src/gestures.c | 27 +++++++++++++++++---------- src/gestures.h | 1 + src/raylib.h | 1 + 3 files changed, 19 insertions(+), 10 deletions(-) (limited to 'src/raylib.h') diff --git a/src/gestures.c b/src/gestures.c index 8e6005b3..57b96bd2 100644 --- a/src/gestures.c +++ b/src/gestures.c @@ -111,6 +111,19 @@ static double GetCurrentTime(void); // Module Functions Definition //---------------------------------------------------------------------------------- +// Enable only desired getures to be detected +void SetGesturesEnabled(unsigned int gestureFlags) +{ + enabledGestures = gestureFlags; +} + +// Check if a gesture have been detected +bool IsGestureDetected(int gesture) +{ + if ((enabledGestures & currentGesture) == gesture) return true; + else return false; +} + // Process gesture event and translate it into gestures void ProcessGestureEvent(GestureEvent event) { @@ -291,13 +304,6 @@ void UpdateGestures(void) } } -// Check if a gesture have been detected -bool IsGestureDetected(int gesture) -{ - if ((enabledGestures & currentGesture) == gesture) return true; - else return false; -} - // Get number of touch points int GetTouchPointsCount(void) { @@ -306,10 +312,11 @@ int GetTouchPointsCount(void) return pointCount; } -// Enable only desired getures to be detected -void SetGesturesEnabled(unsigned int gestureFlags) +// Get latest detected gesture +int GetGestureDetected(void) { - enabledGestures = gestureFlags; + // Get current gesture only if enabled + return (enabledGestures & currentGesture); } // Hold time measured in ms diff --git a/src/gestures.h b/src/gestures.h index ab5287cc..912d0b92 100644 --- a/src/gestures.h +++ b/src/gestures.h @@ -96,6 +96,7 @@ void ProcessGestureEvent(GestureEvent event); // Process gesture event void UpdateGestures(void); // Update gestures detected (must be called every frame) int GetTouchPointsCount(void); // Get touch points count +int GetGestureDetected(void); // Get latest detected gesture float GetGestureHoldDuration(void); // Get gesture hold time in milliseconds Vector2 GetGestureDragVector(void); // Get gesture drag vector float GetGestureDragAngle(void); // Get gesture drag angle diff --git a/src/raylib.h b/src/raylib.h index 343e86f1..9120ddc4 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -650,6 +650,7 @@ void ProcessGestureEvent(GestureEvent event); // Process gesture event void UpdateGestures(void); // Update gestures detected (called automatically in PollInputEvents()) int GetTouchPointsCount(void); // Get touch points count +int GetGestureDetected(void); // Get latest detected gesture float GetGestureHoldDuration(void); // Get gesture hold time in milliseconds Vector2 GetGestureDragVector(void); // Get gesture drag vector float GetGestureDragAngle(void); // Get gesture drag angle -- cgit v1.2.3 From 3ce02282063b47bd3e0beb0453d33ef316a371fa Mon Sep 17 00:00:00 2001 From: raysan5 Date: Tue, 14 Jun 2016 17:16:20 +0200 Subject: Move Oculus Rift support to rlgl module --- src/core.c | 386 +--------------------------------------------------------- src/raylib.h | 19 +-- src/rlgl.c | 390 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- src/rlgl.h | 9 ++ 4 files changed, 399 insertions(+), 405 deletions(-) (limited to 'src/raylib.h') diff --git a/src/core.c b/src/core.c index bd49b549..fb71af21 100644 --- a/src/core.c +++ b/src/core.c @@ -9,7 +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) +* Oculus Rift CV1 (with desktop mirror) - View [rlgl] module to enable it * * 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). @@ -54,14 +54,6 @@ #include // String function definitions, memset() #include // 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_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 // GLFW3 library: Windows, OpenGL context and Input management @@ -134,31 +126,7 @@ //---------------------------------------------------------------------------------- // 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 @@ -213,17 +181,6 @@ static uint64_t baseTime; // Base time measure for hi-res timer static bool windowShouldClose = false; // Flag to set window for closing #endif -#if defined(PLATFORM_OCULUS) -// OVR device variables -static ovrSession session; // Oculus session (pointer to ovrHmdStruct) -static ovrHmdDesc hmdDesc; // Oculus device descriptor parameters -static ovrGraphicsLuid luid; // Oculus locally unique identifier for the program (64 bit) -static OculusLayer layer; // Oculus drawing layer (similar to photoshop) -static OculusBuffer buffer; // Oculus internal buffers (texture chain and fbo) -static OculusMirror mirror; // Oculus mirror texture and fbo -static unsigned int frameIndex = 0; // Oculus frames counter, used to discard frames from chain -#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) @@ -233,7 +190,6 @@ 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... @@ -332,19 +288,6 @@ 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 //---------------------------------------------------------------------------------- @@ -393,11 +336,6 @@ 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; @@ -512,64 +450,6 @@ void CloseWindow(void) 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) -{ - // Initialize Oculus device - ovrResult result = ovr_Initialize(NULL); - if (OVR_FAILURE(result)) TraceLog(WARNING, "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: Serial Number: %s", hmdDesc.SerialNumber); - TraceLog(INFO, "OVR: Resolution: %ix%i", hmdDesc.Resolution.w, hmdDesc.Resolution.h); - - // NOTE: Oculus mirror is set to defined screenWidth and screenHeight... - // ...ideally, it should be (hmdDesc.Resolution.w/2, hmdDesc.Resolution.h/2) - - // Initialize Oculus Buffers - layer = InitOculusLayer(session); - buffer = LoadOculusBuffer(session, layer.width, layer.height); - mirror = LoadOculusMirror(session, screenWidth, screenHeight); - 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); // Free Oculus session data - ovr_Shutdown(); // Close Oculus device connection -} - -// 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) { @@ -638,10 +518,6 @@ void BeginDrawing(void) currentTime = GetTime(); // Number of elapsed seconds since InitTimer() was called updateTime = currentTime - previousTime; previousTime = currentTime; - -#if defined(PLATFORM_OCULUS) - SetOculusBuffer(session, buffer); -#endif rlClearScreenBuffers(); // Clear current framebuffers rlLoadIdentity(); // Reset current matrix (MODELVIEW) @@ -654,49 +530,7 @@ void BeginDrawing(void) // End canvas drawing and Swap Buffers (Double Buffering) void EndDrawing(void) { -#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); - - 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 + rlglDraw(); // Draw Buffers (Only OpenGL 3+ and ES2) SwapBuffers(); // Copy back buffer to front buffer PollInputEvents(); // Poll user events @@ -768,7 +602,7 @@ void Begin3dMode(Camera camera) rlLoadIdentity(); // Reset current matrix (MODELVIEW) // Setup Camera view - cameraView = MatrixLookAt(camera.position, camera.target, camera.up); + Matrix cameraView = MatrixLookAt(camera.position, camera.target, camera.up); rlMultMatrixf(MatrixToFloat(cameraView)); // Multiply MODELVIEW matrix by view matrix (camera) rlEnableDepthTest(); // Enable DEPTH_TEST for 3D @@ -1738,9 +1572,7 @@ static void InitDisplay(int width, int height) #endif glfwMakeContextCurrent(window); -#if defined(PLATFORM_OCULUS) - glfwSwapInterval(0); -#endif + glfwSwapInterval(0); // Disable VSync by default #if defined(PLATFORM_DESKTOP) // Load OpenGL 3.3 extensions @@ -2940,214 +2772,6 @@ 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/raylib.h b/src/raylib.h index 9120ddc4..0c9f0280 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -64,7 +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 +//#define RLGL_OCULUS_SUPPORT // Oculus Rift CV1 (complementary to PLATFORM_DESKTOP) // Security check in case no PLATFORM_* defined #if !defined(PLATFORM_DESKTOP) && !defined(PLATFORM_ANDROID) && !defined(PLATFORM_RPI) && !defined(PLATFORM_WEB) @@ -545,12 +545,6 @@ 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) @@ -852,6 +846,17 @@ void EndBlendMode(void); // End blend Light CreateLight(int type, Vector3 position, Color diffuse); // Create a new light, initialize it and add to pool void DestroyLight(Light light); // Destroy a light and take it out of the list +//------------------------------------------------------------------------------------ +// Oculus Rift CV1 Functions (Module: rlgl) +// NOTE: This functions are useless when using OpenGL 1.1 +//------------------------------------------------------------------------------------ +void InitOculusDevice(void); // Init Oculus Rift device +void CloseOculusDevice(void); // Close Oculus Rift device +void UpdateOculusTracking(void); // Update Oculus Rift tracking (position and orientation) +void SetOculusMatrix(int eye); // Set internal projection and modelview matrix depending on eyes tracking data +void BeginOculusDrawing(void); // Begin Oculus drawing configuration +void EndOculusDrawing(void); // End Oculus drawing process (and desktop mirror) + //------------------------------------------------------------------------------------ // Audio Loading and Playing Functions (Module: audio) //------------------------------------------------------------------------------------ diff --git a/src/rlgl.c b/src/rlgl.c index 26961ca9..1e392889 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -72,6 +72,10 @@ #include "standard_shader.h" // Standard shader to embed #endif +#if defined(RLGL_OCULUS_SUPPORT) + #include "external/OculusSDK/LibOVR/Include/OVR_CAPI_GL.h" // Oculus SDK for OpenGL +#endif + //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- @@ -172,6 +176,32 @@ typedef struct { //Guint fboId; } DrawCall; +#if defined(RLGL_OCULUS_SUPPORT) +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 //---------------------------------------------------------------------------------- @@ -221,6 +251,17 @@ static Light lights[MAX_LIGHTS]; // Lights pool static int lightsCount; // Counts current enabled physic objects #endif +#if defined(RLGL_OCULUS_SUPPORT) +// OVR device variables +static ovrSession session; // Oculus session (pointer to ovrHmdStruct) +static ovrHmdDesc hmdDesc; // Oculus device descriptor parameters +static ovrGraphicsLuid luid; // Oculus locally unique identifier for the program (64 bit) +static OculusLayer layer; // Oculus drawing layer (similar to photoshop) +static OculusBuffer buffer; // Oculus internal buffers (texture chain and fbo) +static OculusMirror mirror; // Oculus mirror texture and fbo +static unsigned int frameIndex = 0; // Oculus frames counter, used to discard frames from chain +#endif + // Compressed textures support flags static bool texCompDXTSupported = false; // DDS texture compression support static bool npotSupported = false; // NPOT textures full support @@ -261,6 +302,16 @@ static void SetShaderLights(Shader shader); // Sets shader uniform values for li static char *ReadTextFile(const char *fileName); #endif +#if defined(RLGL_OCULUS_SUPPORT) // Oculus Rift functions +static OculusBuffer LoadOculusBuffer(ovrSession session, int width, int height); // Load Oculus required buffers +static void UnloadOculusBuffer(ovrSession session, OculusBuffer buffer); // Unload texture required buffers +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); // Copy Oculus screen buffer to mirror texture +static OculusLayer InitOculusLayer(ovrSession session); // Init Oculus layer (similar to photoshop) +static Matrix FromOvrMatrix(ovrMatrix4f ovrM); // Convert from Oculus ovrMatrix4f struct to raymath Matrix struct +#endif + #if defined(GRAPHICS_API_OPENGL_11) static int GenerateMipmaps(unsigned char *data, int baseWidth, int baseHeight); static Color *GenNextMipmap(Color *srcData, int srcWidth, int srcHeight); @@ -872,23 +923,6 @@ int rlGetVersion(void) #endif } -// Load OpenGL extensions -// NOTE: External loader function could be passed as a pointer -void rlglLoadExtensions(void *loader) -{ -#if defined(GRAPHICS_API_OPENGL_33) - // NOTE: glad is generated and contains only required OpenGL 3.3 Core extensions - if (!gladLoadGLLoader((GLADloadproc)loader)) 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"); - - // With GLAD, we can check if an extension is supported using the GLAD_GL_xxx booleans - //if (GLAD_GL_ARB_vertex_array_object) // Use GL_ARB_vertex_array_object -#endif -} - //---------------------------------------------------------------------------------- // Module Functions Definition - rlgl Functions //---------------------------------------------------------------------------------- @@ -1170,6 +1204,23 @@ void rlglInitGraphics(int offsetX, int offsetY, int width, int height) TraceLog(INFO, "OpenGL graphic device initialized successfully"); } +// Load OpenGL extensions +// NOTE: External loader function could be passed as a pointer +void rlglLoadExtensions(void *loader) +{ +#if defined(GRAPHICS_API_OPENGL_33) + // NOTE: glad is generated and contains only required OpenGL 3.3 Core extensions + if (!gladLoadGLLoader((GLADloadproc)loader)) 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"); + + // With GLAD, we can check if an extension is supported using the GLAD_GL_xxx booleans + //if (GLAD_GL_ARB_vertex_array_object) // Use GL_ARB_vertex_array_object +#endif +} + // Get world coordinates from screen coordinates Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view) { @@ -2410,6 +2461,130 @@ void DestroyLight(Light light) #endif } +#if defined(RLGL_OCULUS_SUPPORT) +// Init Oculus Rift device +// NOTE: Device initialization should be done before window creation? +void InitOculusDevice(void) +{ + // Initialize Oculus device + ovrResult result = ovr_Initialize(NULL); + if (OVR_FAILURE(result)) TraceLog(WARNING, "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: Serial Number: %s", hmdDesc.SerialNumber); + TraceLog(INFO, "OVR: Resolution: %ix%i", hmdDesc.Resolution.w, hmdDesc.Resolution.h); + + // NOTE: Oculus mirror is set to defined screenWidth and screenHeight... + // ...ideally, it should be (hmdDesc.Resolution.w/2, 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); // NOTE: hardcoded... + layer.eyeLayer.ColorTexture[0] = buffer.textureChain; //SetOculusLayerTexture(eyeLayer, buffer.textureChain); + + // Recenter OVR tracking origin + ovr_RecenterTrackingOrigin(session); +} + +// Close Oculus Rift device +void CloseOculusDevice(void) +{ + UnloadOculusMirror(session, mirror); // Unload Oculus mirror buffer + UnloadOculusBuffer(session, buffer); // Unload Oculus texture buffers + + ovr_Destroy(session); // Free Oculus session data + ovr_Shutdown(); // Close Oculus device connection +} + +// 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]; +} + +void SetOculusMatrix(int 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); + + 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(modelview, eyeView); // Using internal camera modelview matrix + + SetMatrixModelview(modelEyeView); + SetMatrixProjection(layer.eyeProjections[eye]); +} + +void BeginOculusDrawing(void) +{ + 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); // Same as rlClearScreenBuffers() + + // NOTE: If your application is configured to treat the texture as a linear format (e.g. GL_RGBA) + // and performs linear-to-gamma conversion in GLSL or does not care about gamma-correction, then: + // - Require OculusBuffer format to be OVR_FORMAT_R8G8B8A8_UNORM_SRGB + // - Do NOT enable GL_FRAMEBUFFER_SRGB + //glEnable(GL_FRAMEBUFFER_SRGB); +} + +void EndOculusDrawing(void) +{ + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + + 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 + //---------------------------------------------------------------------------------- // Module specific Functions Definition //---------------------------------------------------------------------------------- @@ -3390,6 +3565,187 @@ static Color *GenNextMipmap(Color *srcData, int srcWidth, int srcHeight) } #endif +#if defined(RLGL_OCULUS_SUPPORT) +// 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); +} + +// 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); +} + +// Copy Oculus screen buffer to 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); +} + +// Init Oculus layer (similar to photoshop) +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; +} + +// 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; +} +#endif + #if defined(RLGL_STANDALONE) // Output a trace log message // NOTE: Expected msgType: (0)Info, (1)Error, (2)Warning diff --git a/src/rlgl.h b/src/rlgl.h index 28c50b8f..1e77b771 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -347,6 +347,15 @@ void DestroyLight(Light light); // Destroy a void TraceLog(int msgType, const char *text, ...); #endif +#if defined(RLGL_OCULUS_SUPPORT) +void InitOculusDevice(void); // Init Oculus Rift device +void CloseOculusDevice(void); // Close Oculus Rift device +void UpdateOculusTracking(void); // Update Oculus Rift tracking (position and orientation) +void SetOculusMatrix(int eye); // Set internal projection and modelview matrix depending on eyes tracking data +void BeginOculusDrawing(void); // Begin Oculus drawing configuration +void EndOculusDrawing(void); // End Oculus drawing process (and desktop mirror) +#endif + #ifdef __cplusplus } #endif -- cgit v1.2.3 From 24c9b1f717bd9a6510667907614928188a6b6a6f Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 17 Jun 2016 13:54:45 +0200 Subject: Improving Oculus Rift example... Under design... looking for the easiest and most comprehensive way for the user to use VR... --- examples/core_oculus_rift.c | 40 ++++++++++++++++++++++------------------ src/core.c | 10 ++++++++++ src/raylib.h | 3 ++- src/rlgl.c | 10 +++++----- src/rlgl.h | 2 +- 5 files changed, 40 insertions(+), 25 deletions(-) (limited to 'src/raylib.h') diff --git a/examples/core_oculus_rift.c b/examples/core_oculus_rift.c index 3c9d7840..32e6b1c6 100644 --- a/examples/core_oculus_rift.c +++ b/examples/core_oculus_rift.c @@ -51,27 +51,31 @@ int main() ClearBackground(RAYWHITE); - BeginOculusDrawing(); + Begin3dMode(camera); + //BeginOculusDrawing(camera); // Add it to Begin3dMode() ? - for (int eye = 0; eye < 2; eye++) - { - // TODO: Probably projection and view matrices could be created here... - // ...without the need to create it internally through Begin3dMode() - Begin3dMode(camera); + for (int eye = 0; eye < 2; eye++) + { + // TODO: Probably projection and view matrices could be created here... + // ...without the need to create it internally through Begin3dMode() + //Begin3dMode(camera); + + SetOculusView(eye); + + DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED); + DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, MAROON); + + DrawGrid(10, 1.0f); + + // TODO: Call internal buffers drawing directly (rlglDraw()) and... + // ...reset internal matrices, instead of letting End3dMode() do that + //End3dMode(); - SetOculusMatrix(eye); - - DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED); - DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, MAROON); - - DrawGrid(10, 1.0f); - - // TODO: Call internal buffers drawing directly (rlglDraw()) and... - // ...reset internal matrices, instead of letting End3dMode() do that - End3dMode(); - } + DrawDefaultBuffers(); // Process internal dynamic buffers + } - EndOculusDrawing(); + End3dMode(); + //EndOculusDrawing(); // Add it to End3dMode() ? EndDrawing(); //---------------------------------------------------------------------------------- diff --git a/src/core.c b/src/core.c index 7c2dbcb9..eef81bad 100644 --- a/src/core.c +++ b/src/core.c @@ -606,6 +606,8 @@ void Begin3dMode(Camera camera) rlMultMatrixf(MatrixToFloat(cameraView)); // Multiply MODELVIEW matrix by view matrix (camera) rlEnableDepthTest(); // Enable DEPTH_TEST for 3D + + //if (vrEnabled) BeginVrMode(); } // Ends 3D mode and returns to default 2D orthographic mode @@ -1015,6 +1017,14 @@ Matrix GetCameraMatrix(Camera camera) return MatrixLookAt(camera.position, camera.target, camera.up); } +// Update and draw default buffers vertex data +// NOTE: This data has been stored dynamically during frame on each Draw*() call +void DrawDefaultBuffers(void) +{ + rlglUpdateDefaultBuffers(); // Upload frame vertex data to GPU + rlglDrawDefaultBuffers(); // Draw vertex data into framebuffer +} + //---------------------------------------------------------------------------------- // Module Functions Definition - Input (Keyboard, Mouse, Gamepad) Functions //---------------------------------------------------------------------------------- diff --git a/src/raylib.h b/src/raylib.h index 0c9f0280..ed787892 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -572,6 +572,7 @@ void EndTextureMode(void); // Ends drawing to r Ray GetMouseRay(Vector2 mousePosition, Camera camera); // Returns a ray trace from mouse position Vector2 GetWorldToScreen(Vector3 position, Camera camera); // Returns the screen space position from a 3d world space position Matrix GetCameraMatrix(Camera camera); // Returns camera transform matrix (view matrix) +void DrawDefaultBuffers(void); // Update and draw default buffers vertex data (stored dynamically in frame) void SetTargetFPS(int fps); // Set target FPS (maximum) float GetFPS(void); // Returns current FPS @@ -853,7 +854,7 @@ void DestroyLight(Light light); // Destroy a void InitOculusDevice(void); // Init Oculus Rift device void CloseOculusDevice(void); // Close Oculus Rift device void UpdateOculusTracking(void); // Update Oculus Rift tracking (position and orientation) -void SetOculusMatrix(int eye); // Set internal projection and modelview matrix depending on eyes tracking data +void SetOculusView(int eye); // Set internal projection and modelview matrix depending on eyes tracking data void BeginOculusDrawing(void); // Begin Oculus drawing configuration void EndOculusDrawing(void); // End Oculus drawing process (and desktop mirror) diff --git a/src/rlgl.c b/src/rlgl.c index 6d003869..d68b9109 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -297,8 +297,8 @@ static void UnloadDefaultShader(void); // Unload default shader static void UnloadStandardShader(void); // Unload standard shader static void LoadDefaultBuffers(void); // Load default internal buffers (lines, triangles, quads) -static void UpdateDefaultBuffers(void); // Update default internal buffers (VAOs/VBOs) with vertex data -static void DrawDefaultBuffers(void); // Draw default internal buffers vertex data +void rlglUpdateDefaultBuffers(void); // Update default internal buffers (VAOs/VBOs) with vertex data +void rlglDrawDefaultBuffers(void); // Draw default internal buffers vertex data static void UnloadDefaultBuffers(void); // Unload default internal buffers vertex data from CPU and GPU static void SetShaderLights(Shader shader); // Sets shader uniform values for lights array @@ -2542,7 +2542,7 @@ void UpdateOculusTracking(void) //if (sessionStatus.IsVisible) // the game or experience has VR focus and is visible in the HMD. } -void SetOculusMatrix(int eye) +void SetOculusView(int 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); @@ -3089,7 +3089,7 @@ static void LoadDefaultBuffers(void) // Update default internal buffers (VAOs/VBOs) with vertex array data // NOTE: If there is not vertex data, buffers doesn't need to be updated (vertexCount > 0) // TODO: If no data changed on the CPU arrays --> No need to re-update GPU arrays (change flag required) -static void UpdateDefaultBuffers(void) +void rlglUpdateDefaultBuffers(void) { // Update lines vertex buffers if (lines.vCounter > 0) @@ -3159,7 +3159,7 @@ static void UpdateDefaultBuffers(void) // Draw default internal buffers vertex data // NOTE: We draw in this order: lines, triangles, quads -static void DrawDefaultBuffers(void) +void rlglDrawDefaultBuffers(void) { // Set current shader and upload current MVP matrix if ((lines.vCounter > 0) || (triangles.vCounter > 0) || (quads.vCounter > 0)) diff --git a/src/rlgl.h b/src/rlgl.h index 3322d80c..8904b9ac 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -357,7 +357,7 @@ void TraceLog(int msgType, const char *text, ...); void InitOculusDevice(void); // Init Oculus Rift device void CloseOculusDevice(void); // Close Oculus Rift device void UpdateOculusTracking(void); // Update Oculus Rift tracking (position and orientation) -void SetOculusMatrix(int eye); // Set internal projection and modelview matrix depending on eyes tracking data +void SetOculusView(int eye); // Set internal projection and modelview matrix depending on eyes tracking data void BeginOculusDrawing(void); // Begin Oculus drawing configuration void EndOculusDrawing(void); // End Oculus drawing process (and desktop mirror) #endif -- cgit v1.2.3 From 5f7ac64c44543383b10ec6a56e5ec1db5706276e Mon Sep 17 00:00:00 2001 From: raysan5 Date: Fri, 24 Jun 2016 19:49:36 +0200 Subject: Removed function SetModelTexture() It's more educational to go through new material system, so, I decide to remove this function to avoid students confusion... --- CHANGELOG | 7 ++++--- examples/models_cubicmap.c | 2 +- examples/models_heightmap.c | 2 +- examples/models_obj_loading.c | 2 +- examples/shaders_custom_uniform.c | 2 +- examples/shaders_postprocessing.c | 2 +- games/raylib_demo/raylib_demo.c | 4 ++-- src/models.c | 7 ------- src/raylib.h | 1 - 9 files changed, 11 insertions(+), 18 deletions(-) (limited to 'src/raylib.h') diff --git a/CHANGELOG b/CHANGELOG index 5024dc6e..300c9089 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,20 +1,20 @@ changelog --------- -Current Release: raylib 1.5.0 (23 June 2016) +Current Release: raylib 1.5.0 (xx June 2016) NOTE: Only versions marked as 'Release' are available in installer, updates are only available as source. NOTE: Current Release includes all previous updates. ----------------------------------------------- -Release: raylib 1.5.0 (23 June 2016) +Release: raylib 1.5.0 (xx June 2016) ----------------------------------------------- NOTE: Probably this new version is the biggest boost of the library ever, lots of parts of the library have been redesigned, lots of bugs have been solved and some **AMAZING** new features have been added. HUGE changes: -[core] OCULUS RIFT CV1: Added support for VR witha bunch of Oculus-specific functions to init/close device and Oculus rendering. +[rlgl] OCULUS RIFT CV1: Added support for VR witha bunch of Oculus-specific functions to init/close device and Oculus rendering. [rlgl] MATERIALS SYSTEM: Added support for Materials (.mtl) and multiple material properties: diffuse, specular, normal. [rlgl] LIGHTING SYSTEM: Added support for up to 8 lights of 3 different types: Omni, Directional and Spot [physac] REDESIGNED: Improved performance and simplified usage, physic objects are managed internally @@ -65,6 +65,7 @@ other changes: [models] Updated BoundingBox collision detections [models] Added color parameter to DrawBoundigBox() [models] Removed function: DrawQuad() +[models] Removed function: SetModelTexture() [models] Redesigned DrawPlane() to use RL_TRIANGLES [models] Redesigned DrawRectangleV() to use RL_TRIANGLES [models] Redesign to accomodate new materials system: LoadMaterial() diff --git a/examples/models_cubicmap.c b/examples/models_cubicmap.c index 1ca27dfd..89bc75cf 100644 --- a/examples/models_cubicmap.c +++ b/examples/models_cubicmap.c @@ -29,7 +29,7 @@ int main() // NOTE: By default each cube is mapped to one part of texture atlas Texture2D texture = LoadTexture("resources/cubicmap_atlas.png"); // Load map texture - SetModelTexture(&map, texture); // Bind texture to map model + map.material.texDiffuse = texture; // Set map diffuse texture Vector3 mapPosition = { -16.0f, 0.0f, -8.0f }; // Set model position diff --git a/examples/models_heightmap.c b/examples/models_heightmap.c index c8e5ff35..90e5f5bb 100644 --- a/examples/models_heightmap.c +++ b/examples/models_heightmap.c @@ -26,7 +26,7 @@ int main() Image image = LoadImage("resources/heightmap.png"); // Load heightmap image (RAM) Texture2D texture = LoadTextureFromImage(image); // Convert image to texture (VRAM) Model map = LoadHeightmap(image, (Vector3){ 16, 8, 16 }); // Load heightmap model with defined size - SetModelTexture(&map, texture); // Bind texture to model + map.material.texDiffuse = texture; // Set map diffuse texture Vector3 mapPosition = { -8.0f, 0.0f, -8.0f }; // Set model position (depends on model scaling!) UnloadImage(image); // Unload heightmap image from RAM, already uploaded to VRAM diff --git a/examples/models_obj_loading.c b/examples/models_obj_loading.c index e8dd0adc..a6969f70 100644 --- a/examples/models_obj_loading.c +++ b/examples/models_obj_loading.c @@ -25,7 +25,7 @@ int main() Model dwarf = LoadModel("resources/model/dwarf.obj"); // Load OBJ model Texture2D texture = LoadTexture("resources/model/dwarf_diffuse.png"); // Load model texture - SetModelTexture(&dwarf, texture); // Bind texture to model + dwarf.material.texDiffuse = texture; // Set dwarf model diffuse texture Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position SetTargetFPS(60); // Set our game to run at 60 frames-per-second diff --git a/examples/shaders_custom_uniform.c b/examples/shaders_custom_uniform.c index 516d5087..c4f87259 100644 --- a/examples/shaders_custom_uniform.c +++ b/examples/shaders_custom_uniform.c @@ -34,7 +34,7 @@ int main() Model dwarf = LoadModel("resources/model/dwarf.obj"); // Load OBJ model Texture2D texture = LoadTexture("resources/model/dwarf_diffuse.png"); // Load model texture (diffuse map) - SetModelTexture(&dwarf, texture); // Bind texture to model + dwarf.material.texDiffuse = texture; // Set dwarf model diffuse texture Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position diff --git a/examples/shaders_postprocessing.c b/examples/shaders_postprocessing.c index 5e8b5a80..43d21e08 100644 --- a/examples/shaders_postprocessing.c +++ b/examples/shaders_postprocessing.c @@ -34,7 +34,7 @@ int main() Model dwarf = LoadModel("resources/model/dwarf.obj"); // Load OBJ model Texture2D texture = LoadTexture("resources/model/dwarf_diffuse.png"); // Load model texture (diffuse map) - SetModelTexture(&dwarf, texture); // Bind texture to model + dwarf.material.texDiffuse = texture; // Set dwarf model diffuse texture Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position diff --git a/games/raylib_demo/raylib_demo.c b/games/raylib_demo/raylib_demo.c index 7f6f291a..22213b46 100644 --- a/games/raylib_demo/raylib_demo.c +++ b/games/raylib_demo/raylib_demo.c @@ -202,8 +202,8 @@ int main() camera = (Camera){{ 0.0, 12.0, 15.0 }, { 0.0, 3.0, 0.0 }, { 0.0, 1.0, 0.0 }}; catTexture = LoadTexture("resources/catsham.png"); // Load model texture - cat = LoadModel("resources/cat.obj"); // Load OBJ model - SetModelTexture(&cat, catTexture); + cat = LoadModel("resources/cat.obj"); // Load OBJ model + cat.material.texDiffuse = texture; // Set cat model diffuse texture fxWav = LoadSound("resources/audio/weird.wav"); // Load WAV audio file fxOgg = LoadSound("resources/audio/tanatana.ogg"); // Load OGG audio file diff --git a/src/models.c b/src/models.c index 8deabcb0..a4bcde8f 100644 --- a/src/models.c +++ b/src/models.c @@ -808,13 +808,6 @@ void UnloadMaterial(Material material) rlDeleteTextures(material.texSpecular.id); } -// Link a texture to a model -void SetModelTexture(Model *model, Texture2D texture) -{ - if (texture.id <= 0) model->material.texDiffuse = GetDefaultTexture(); // Use default white texture - else model->material.texDiffuse = texture; -} - // Generate a mesh from heightmap static Mesh GenMeshHeightmap(Image heightmap, Vector3 size) { diff --git a/src/raylib.h b/src/raylib.h index ed787892..641f4c09 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -795,7 +795,6 @@ Model LoadModelFromRES(const char *rresName, int resId); // Load a 3d mod Model LoadHeightmap(Image heightmap, Vector3 size); // Load a heightmap image as a 3d model Model LoadCubicmap(Image cubicmap); // Load a map image as a 3d model (cubes based) void UnloadModel(Model model); // Unload 3d model from memory -void SetModelTexture(Model *model, Texture2D texture); // Link a texture to a model Material LoadMaterial(const char *fileName); // Load material data (from file) Material LoadDefaultMaterial(void); // Load default material (uses default models shader) -- cgit v1.2.3 From 572936ec65c127c7fecc69f025b819ffec20cdc0 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Mon, 27 Jun 2016 18:30:58 +0200 Subject: Added Oculus functions to raylib header --- src/raylib.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/raylib.h') diff --git a/src/raylib.h b/src/raylib.h index 641f4c09..6bacfc67 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -856,6 +856,8 @@ void UpdateOculusTracking(void); // Update Oculus Rift tracking (posi void SetOculusView(int eye); // Set internal projection and modelview matrix depending on eyes tracking data void BeginOculusDrawing(void); // Begin Oculus drawing configuration void EndOculusDrawing(void); // End Oculus drawing process (and desktop mirror) +bool IsOculusReady(void); // Detect if oculus device (or simulator) is ready +void ToggleVR(void); // Enable/Disable VR experience (Oculus device or simulator) //------------------------------------------------------------------------------------ // Audio Loading and Playing Functions (Module: audio) -- cgit v1.2.3 From ee72654b557202a673f042484c83d3020ae618b8 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 4 Jul 2016 01:29:23 +0200 Subject: Redesigned stereo rendering mechanism Now it's easier for the user! Just init Oculus device and get stereo rendering! --- examples/core_oculus_rift.c | 11 +- examples/resources/shaders/glsl330/distortion.fs | 9 +- src/core.c | 18 +- src/raylib.h | 2 - src/rlgl.c | 443 ++++++++++++----------- src/rlgl.h | 4 - 6 files changed, 251 insertions(+), 236 deletions(-) (limited to 'src/raylib.h') diff --git a/examples/core_oculus_rift.c b/examples/core_oculus_rift.c index c073d3d6..131a21c2 100644 --- a/examples/core_oculus_rift.c +++ b/examples/core_oculus_rift.c @@ -50,22 +50,15 @@ int main() // Draw //---------------------------------------------------------------------------------- BeginDrawing(); - + ClearBackground(RAYWHITE); - + Begin3dMode(camera); - for (int eye = 0; eye < 2; eye++) - { - SetOculusView(eye); - DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED); DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, MAROON); DrawGrid(10, 1.0f); - - DrawDefaultBuffers(); // Process internal dynamic buffers - } End3dMode(); diff --git a/examples/resources/shaders/glsl330/distortion.fs b/examples/resources/shaders/glsl330/distortion.fs index 4cd9937f..62856341 100644 --- a/examples/resources/shaders/glsl330/distortion.fs +++ b/examples/resources/shaders/glsl330/distortion.fs @@ -10,12 +10,13 @@ uniform sampler2D texture0; out vec4 finalColor; // NOTE: Add here your custom variables -const vec2 LeftLensCenter = vec2(0.2863248, 0.5); -const vec2 RightLensCenter = vec2(0.7136753, 0.5); +const vec2 LeftLensCenter = vec2(0.288, 0.5); +const vec2 RightLensCenter = vec2(0.712, 0.5); const vec2 LeftScreenCenter = vec2(0.25, 0.5); const vec2 RightScreenCenter = vec2(0.75, 0.5); -const vec2 Scale = vec2(0.25, 0.45); //vec2(0.1469278, 0.2350845); -const vec2 ScaleIn = vec2(4, 2.2222); +uniform vec2 Scale = vec2(0.25, 0.45); //vec2(0.1469278, 0.2350845); +uniform vec2 ScaleIn = vec2(4, 2.2222); + const vec4 HmdWarpParam = vec4(1, 0.22, 0.24, 0); const vec4 ChromaAbParam = vec4(0.996, -0.004, 1.014, 0.0); diff --git a/src/core.c b/src/core.c index 47ce5cea..a8557831 100644 --- a/src/core.c +++ b/src/core.c @@ -520,6 +520,8 @@ void BeginDrawing(void) currentTime = GetTime(); // Number of elapsed seconds since InitTimer() was called updateTime = currentTime - previousTime; previousTime = currentTime; + + if (IsOculusReady()) BeginOculusDrawing(); rlClearScreenBuffers(); // Clear current framebuffers rlLoadIdentity(); // Reset current matrix (MODELVIEW) @@ -533,6 +535,8 @@ void BeginDrawing(void) void EndDrawing(void) { rlglDraw(); // Draw Buffers (Only OpenGL 3+ and ES2) + + if (IsOculusReady()) EndOculusDrawing(); SwapBuffers(); // Copy back buffer to front buffer PollInputEvents(); // Poll user events @@ -608,15 +612,11 @@ void Begin3dMode(Camera camera) rlMultMatrixf(MatrixToFloat(cameraView)); // Multiply MODELVIEW matrix by view matrix (camera) rlEnableDepthTest(); // Enable DEPTH_TEST for 3D - - if (IsOculusReady()) BeginOculusDrawing(); } // Ends 3D mode and returns to default 2D orthographic mode void End3dMode(void) -{ - if (IsOculusReady()) EndOculusDrawing(); - +{ rlglDraw(); // Process internal buffers (update + draw) rlMatrixMode(RL_PROJECTION); // Switch to projection matrix @@ -1021,14 +1021,6 @@ Matrix GetCameraMatrix(Camera camera) return MatrixLookAt(camera.position, camera.target, camera.up); } -// Update and draw default buffers vertex data -// NOTE: This data has been stored dynamically during frame on each Draw*() call -void DrawDefaultBuffers(void) -{ - rlglUpdateDefaultBuffers(); // Upload frame vertex data to GPU - rlglDrawDefaultBuffers(); // Draw vertex data into framebuffer -} - //---------------------------------------------------------------------------------- // Module Functions Definition - Input (Keyboard, Mouse, Gamepad) Functions //---------------------------------------------------------------------------------- diff --git a/src/raylib.h b/src/raylib.h index 6bacfc67..89fc457f 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -572,7 +572,6 @@ void EndTextureMode(void); // Ends drawing to r Ray GetMouseRay(Vector2 mousePosition, Camera camera); // Returns a ray trace from mouse position Vector2 GetWorldToScreen(Vector3 position, Camera camera); // Returns the screen space position from a 3d world space position Matrix GetCameraMatrix(Camera camera); // Returns camera transform matrix (view matrix) -void DrawDefaultBuffers(void); // Update and draw default buffers vertex data (stored dynamically in frame) void SetTargetFPS(int fps); // Set target FPS (maximum) float GetFPS(void); // Returns current FPS @@ -853,7 +852,6 @@ void DestroyLight(Light light); // Destroy a void InitOculusDevice(void); // Init Oculus Rift device void CloseOculusDevice(void); // Close Oculus Rift device void UpdateOculusTracking(void); // Update Oculus Rift tracking (position and orientation) -void SetOculusView(int eye); // Set internal projection and modelview matrix depending on eyes tracking data void BeginOculusDrawing(void); // Begin Oculus drawing configuration void EndOculusDrawing(void); // End Oculus drawing process (and desktop mirror) bool IsOculusReady(void); // Detect if oculus device (or simulator) is ready diff --git a/src/rlgl.c b/src/rlgl.c index d3ffdd8b..57e6b894 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -276,9 +276,10 @@ static unsigned int frameIndex = 0; // Oculus frames counter, used to discar static bool oculusReady = false; // Oculus device ready flag static bool oculusSimulator = false; // Oculus device simulator static bool vrEnabled = false; // VR experience enabled (Oculus device or simulator) +static bool vrControl = true; // VR controlled by user code, instead of internally static RenderTexture2D stereoFbo; -static Shader distortion; +static Shader distortionShader; // Compressed textures support flags static bool texCompDXTSupported = false; // DDS texture compression support @@ -315,10 +316,13 @@ static void UnloadDefaultShader(void); // Unload default shader static void UnloadStandardShader(void); // Unload standard shader static void LoadDefaultBuffers(void); // Load default internal buffers (lines, triangles, quads) -void rlglUpdateDefaultBuffers(void); // Update default internal buffers (VAOs/VBOs) with vertex data -void rlglDrawDefaultBuffers(void); // Draw default internal buffers vertex data +static void UpdateDefaultBuffers(void); // Update default internal buffers (VAOs/VBOs) with vertex data +static void DrawDefaultBuffers(int eyesCount); // Draw default internal buffers vertex data static void UnloadDefaultBuffers(void); // Unload default internal buffers vertex data from CPU and GPU +// Set internal projection and modelview matrix depending on eyes tracking data +static void SetOculusView(int eye, Matrix matProjection, Matrix matModelView); + static void SetShaderLights(Shader shader); // Sets shader uniform values for lights array static char *ReadTextFile(const char *fileName); @@ -1205,15 +1209,14 @@ void rlglClose(void) void rlglDraw(void) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) -/* - for (int i = 0; i < modelsCount; i++) - { - rlglDrawMesh(models[i]->mesh, models[i]->material, models[i]->transform); - } -*/ - // NOTE: Default buffers always drawn at the end - rlglUpdateDefaultBuffers(); - rlglDrawDefaultBuffers(); + // NOTE: In a future version, models could be stored in a stack... + //for (int i = 0; i < modelsCount; i++) rlglDrawMesh(models[i]->mesh, models[i]->material, models[i]->transform); + + // NOTE: Default buffers upload and draw + UpdateDefaultBuffers(); + + if (vrEnabled && vrControl) DrawDefaultBuffers(2); + else DrawDefaultBuffers(1); #endif } @@ -1865,26 +1868,23 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) #endif #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + int eyesCount = 1; + if (vrEnabled) eyesCount = 2; + glUseProgram(material.shader.id); + // Upload to shader material.colDiffuse + float vColorDiffuse[4] = { (float)material.colDiffuse.r/255, (float)material.colDiffuse.g/255, (float)material.colDiffuse.b/255, (float)material.colDiffuse.a/255 }; + glUniform4fv(material.shader.tintColorLoc, 1, vColorDiffuse); + // At this point the modelview matrix just contains the view matrix (camera) // That's because Begin3dMode() sets it an no model-drawing function modifies it, all use rlPushMatrix() and rlPopMatrix() Matrix matView = modelview; // View matrix (camera) Matrix matProjection = projection; // Projection matrix (perspective) - + // Calculate model-view matrix combining matModel and matView Matrix matModelView = MatrixMultiply(transform, matView); // Transform to camera-space coordinates - // Calculate model-view-projection matrix (MVP) - Matrix matMVP = MatrixMultiply(matModelView, matProjection); // Transform to screen-space coordinates - - // Send combined model-view-projection matrix to shader - glUniformMatrix4fv(material.shader.mvpLoc, 1, false, MatrixToFloat(matMVP)); - - // Upload to shader material.colDiffuse - float vColorDiffuse[4] = { (float)material.colDiffuse.r/255, (float)material.colDiffuse.g/255, (float)material.colDiffuse.b/255, (float)material.colDiffuse.a/255 }; - glUniform4fv(material.shader.tintColorLoc, 1, vColorDiffuse); - // Check if using standard shader to get location points // NOTE: standard shader specific locations are got at render time to keep Shader struct as simple as possible (with just default shader locations) if (material.shader.id == standardShader.id) @@ -1989,9 +1989,20 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) if (mesh.indices != NULL) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quads.vboId[3]); } - // Draw call! - if (mesh.indices != NULL) glDrawElements(GL_TRIANGLES, mesh.triangleCount*3, GL_UNSIGNED_SHORT, 0); // Indexed vertices draw - else glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount); + for (int eye = 0; eye < eyesCount; eye++) + { + if (eyesCount == 2) SetOculusView(eye, matProjection, matModelView); + + // Calculate model-view-projection matrix (MVP) + Matrix matMVP = MatrixMultiply(modelview, projection); // Transform to screen-space coordinates + + // Send combined model-view-projection matrix to shader + glUniformMatrix4fv(material.shader.mvpLoc, 1, false, MatrixToFloat(matMVP)); + + // Draw call! + if (mesh.indices != NULL) glDrawElements(GL_TRIANGLES, mesh.triangleCount*3, GL_UNSIGNED_SHORT, 0); // Indexed vertices draw + else glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount); + } if (material.texNormal.id != 0) { @@ -2016,6 +2027,10 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) } glUseProgram(0); // Unbind shader program + + // Restore projection/modelview matrices + projection = matProjection; + modelview = matView; #endif } @@ -2538,7 +2553,7 @@ void InitOculusDevice(void) // Load oculus-distortion shader (oculus parameters setup internally) // TODO: Embed coulus distortion shader (in this function like default shader?) - distortion = LoadShader("resources/shaders/glsl330/base.vs", "resources/shaders/glsl330/distortion.fs"); + distortionShader = LoadShader("resources/shaders/glsl330/base.vs", "resources/shaders/glsl330/distortion.fs"); oculusSimulator = true; vrEnabled = true; @@ -2564,7 +2579,7 @@ void CloseOculusDevice(void) rlDeleteRenderTextures(stereoFbo); // Unload oculus-distortion shader - UnloadShader(distortion); + UnloadShader(distortionShader); } oculusReady = false; @@ -2615,13 +2630,13 @@ void UpdateOculusTracking(void) } // Set internal projection and modelview matrix depending on eyes tracking data -void SetOculusView(int eye) -{ - Matrix eyeProjection; - Matrix eyeModelView; - +static void SetOculusView(int eye, Matrix matProjection, Matrix matModelView) +{ if (vrEnabled) { + Matrix eyeProjection = matProjection; + Matrix eyeModelView = matModelView; + #if defined(RLGL_OCULUS_SUPPORT) if (oculusReady) { @@ -2639,10 +2654,8 @@ void SetOculusView(int eye) -layer.eyeLayer.RenderPose[eye].Position.z); Matrix eyeView = MatrixMultiply(eyeTranslation, eyeOrientation); // Matrix containing eye-head movement - eyeModelView = MatrixMultiply(modelview, eyeView); // Combine internal camera matrix (modelview) wih eye-head movement + eyeModelView = MatrixMultiply(matModelView, eyeView); // Combine internal camera matrix (modelview) wih eye-head movement - // TODO: Find a better way to get camera view matrix (instead of using internal modelview) - eyeProjection = layer.eyeProjections[eye]; } else @@ -2651,28 +2664,43 @@ void SetOculusView(int eye) // Setup viewport and projection/modelview matrices using tracking data rlViewport(eye*screenWidth/2, 0, screenWidth/2, screenHeight); - float hmdIPD = 0.064f; - float hmdHScreenSize = 0.14976f; - float hmdVScreenSize = 0.0936f; - //float hmdVScreenCenter = 0.04675f; - float hmdEyeToScreenDistance = 0.041f; - float hmdLensSeparationDistance = 0.064f; + static float IPD = 0.064f; // InterpupillaryDistance + float HScreenSize = 0.14976f; + float VScreenSize = 0.0936f; // HScreenSize/(1280.0f/800.0f) + float VScreenCenter = 0.04675f; + float EyeToScreenDistance = 0.041f; + float LensSeparationDistance = 0.064f; //0.0635f (DK1) - //NOTE: fovy value hardcoded to 60 degrees (Oculus Rift CV1 vertical FOV is 100 degrees) - //float halfScreenDistance = hmdVScreenSize/2.0f; - //float yfov = 2.0f*atan(halfScreenDistance/hmdEyeToScreenDistance); - - float viewCenter = (float)hmdHScreenSize*0.25f; - float eyeProjectionShift = viewCenter - hmdLensSeparationDistance*0.5f; - float projectionCenterOffset = 4.0f*eyeProjectionShift/(float)hmdHScreenSize; - + // NOTE: fovy value obtained from device parameters (Oculus Rift CV1) + float halfScreenDistance = VScreenSize/2.0f; + float fovy = 2.0f*atan(halfScreenDistance/EyeToScreenDistance)*RAD2DEG; + + float viewCenter = (float)HScreenSize*0.25f; + float eyeProjectionShift = viewCenter - LensSeparationDistance*0.5f; + float projectionCenterOffset = 4.0f*eyeProjectionShift/(float)HScreenSize; +/* + static float scale[2] = { 0.25, 0.45 }; + + if (IsKeyDown(KEY_RIGHT)) scale[0] += 0.01; + else if (IsKeyDown(KEY_LEFT)) scale[0] -= 0.01; + else if (IsKeyDown(KEY_UP)) scale[1] += 0.01; + else if (IsKeyDown(KEY_DOWN)) scale[1] -= 0.01; + SetShaderValue(distortionShader, GetShaderLocation(distortionShader, "Scale"), scale, 2); + + if (IsKeyDown(KEY_N)) IPD += 0.02; + else if (IsKeyDown(KEY_M)) IPD -= 0.02; +*/ // The matrixes for offsetting the projection and view for each eye, to achieve stereo effect Vector3 projectionOffset = { -projectionCenterOffset, 0.0f, 0.0f }; - Vector3 viewOffset = { -hmdIPD/2.0f, 0.0f, 0.0f }; + + // Camera movement might seem more natural if we model the head. + // Our axis of rotation is the base of our head, so we might want to add + // some y (base of head to eye level) and -z (center of head to eye protrusion) to the camera positions. + Vector3 viewOffset = { -IPD/2.0f, 0.075f, 0.045f }; // Negate the left eye versions - if (eye == 1) + if (eye == 0) { projectionOffset.x *= -1.0f; viewOffset.x *= -1.0f; @@ -2680,29 +2708,18 @@ void SetOculusView(int eye) // Adjust the view and projection matrixes // View matrix is translated based on the eye offset - Matrix projCenter = MatrixPerspective(60.0, (double)((float)screenWidth*0.5f)/(double)screenHeight, 0.01, 1000.0); + Matrix projCenter = MatrixPerspective(fovy, (double)((float)screenWidth*0.5f)/(double)screenHeight, 0.01, 1000.0); Matrix projTranslation = MatrixTranslate(projectionOffset.x, projectionOffset.y, projectionOffset.z); Matrix viewTranslation = MatrixTranslate(viewOffset.x, viewOffset.y, viewOffset.z); eyeProjection = MatrixMultiply(projCenter, projTranslation); // projection - eyeModelView = MatrixMultiply(modelview, viewTranslation); // modelview + eyeModelView = MatrixMultiply(matModelView, viewTranslation); // modelview MatrixTranspose(&eyeProjection); - - /* - // NOTE: fovy value hardcoded to 60 degrees (Oculus Rift CV1 vertical FOV is 100 degrees) - eyeProjection = MatrixPerspective(60.0, (double)(screenWidth/2)/(double)screenHeight, 0.01, 1000.0); - MatrixTranspose(&eyeProjection); - - // TODO: Compute eyes IPD and apply to current modelview matrix (camera) - Matrix eyeView = MatrixIdentity(); - - eyeModelView = MatrixMultiply(modelview, eyeView); - */ } - SetMatrixModelview(eyeModelView); + SetMatrixModelview(eyeModelView); // ERROR! We are modifying modelview for next eye!!! SetMatrixProjection(eyeProjection); } } @@ -2738,6 +2755,8 @@ void BeginOculusDrawing(void) //glViewport(0, 0, buffer.width, buffer.height); // Useful if rendering to separate framebuffers (every eye) rlClearScreenBuffers(); // Clear current framebuffer(s) + + vrControl = true; } // End Oculus drawing process (and desktop mirror) @@ -2777,40 +2796,44 @@ void EndOculusDrawing(void) rlLoadIdentity(); // Reset internal modelview matrix // Draw RenderTexture (stereoFbo) using distortion shader - BeginShaderMode(distortion); + currentShader = distortionShader; - rlEnableTexture(stereoFbo.texture.id); + rlEnableTexture(stereoFbo.texture.id); - rlPushMatrix(); - rlBegin(RL_QUADS); - rlColor4ub(255, 255, 255, 255); - rlNormal3f(0.0f, 0.0f, 1.0f); + rlPushMatrix(); + rlBegin(RL_QUADS); + rlColor4ub(255, 255, 255, 255); + rlNormal3f(0.0f, 0.0f, 1.0f); - // Bottom-left corner for texture and quad - rlTexCoord2f(0.0f, 1.0f); - rlVertex2f(0.0f, 0.0f); + // Bottom-left corner for texture and quad + rlTexCoord2f(0.0f, 1.0f); + rlVertex2f(0.0f, 0.0f); - // Bottom-right corner for texture and quad - rlTexCoord2f(0.0f, 0.0f); - rlVertex2f(0.0f, stereoFbo.texture.height); + // Bottom-right corner for texture and quad + rlTexCoord2f(0.0f, 0.0f); + rlVertex2f(0.0f, stereoFbo.texture.height); - // Top-right corner for texture and quad - rlTexCoord2f(1.0f, 0.0f); - rlVertex2f(stereoFbo.texture.width, stereoFbo.texture.height); + // Top-right corner for texture and quad + rlTexCoord2f(1.0f, 0.0f); + rlVertex2f(stereoFbo.texture.width, stereoFbo.texture.height); - // Top-left corner for texture and quad - rlTexCoord2f(1.0f, 1.0f); - rlVertex2f(stereoFbo.texture.width, 0.0f); - rlEnd(); - rlPopMatrix(); + // Top-left corner for texture and quad + rlTexCoord2f(1.0f, 1.0f); + rlVertex2f(stereoFbo.texture.width, 0.0f); + rlEnd(); + rlPopMatrix(); - rlDisableTexture(); - - //rlglDraw(); - EndShaderMode(); + rlDisableTexture(); + + UpdateDefaultBuffers(); + DrawDefaultBuffers(1); + + currentShader = defaultShader; } rlDisableDepthTest(); + + vrControl = false; } //---------------------------------------------------------------------------------- @@ -3303,7 +3326,7 @@ static void LoadDefaultBuffers(void) // Update default internal buffers (VAOs/VBOs) with vertex array data // NOTE: If there is not vertex data, buffers doesn't need to be updated (vertexCount > 0) // TODO: If no data changed on the CPU arrays --> No need to re-update GPU arrays (change flag required) -void rlglUpdateDefaultBuffers(void) +static void UpdateDefaultBuffers(void) { // Update lines vertex buffers if (lines.vCounter > 0) @@ -3373,146 +3396,154 @@ void rlglUpdateDefaultBuffers(void) // Draw default internal buffers vertex data // NOTE: We draw in this order: lines, triangles, quads -void rlglDrawDefaultBuffers(void) +static void DrawDefaultBuffers(int eyesCount) { - // Set current shader and upload current MVP matrix - if ((lines.vCounter > 0) || (triangles.vCounter > 0) || (quads.vCounter > 0)) - { - glUseProgram(currentShader.id); - - // Create modelview-projection matrix - Matrix matMVP = MatrixMultiply(modelview, projection); - - glUniformMatrix4fv(currentShader.mvpLoc, 1, false, MatrixToFloat(matMVP)); - glUniform4f(currentShader.tintColorLoc, 1.0f, 1.0f, 1.0f, 1.0f); - glUniform1i(currentShader.mapTexture0Loc, 0); - - // NOTE: Additional map textures not considered for default buffers drawing - } - - // Draw lines buffers - if (lines.vCounter > 0) + Matrix matProjection = projection; + Matrix matModelView = modelview; + + for (int eye = 0; eye < eyesCount; eye++) { - glBindTexture(GL_TEXTURE_2D, whiteTexture); + if (eyesCount == 2) SetOculusView(eye, matProjection, matModelView); - if (vaoSupported) + // Set current shader and upload current MVP matrix + if ((lines.vCounter > 0) || (triangles.vCounter > 0) || (quads.vCounter > 0)) { - glBindVertexArray(lines.vaoId); + glUseProgram(currentShader.id); + + // Create modelview-projection matrix + Matrix matMVP = MatrixMultiply(modelview, projection); + + glUniformMatrix4fv(currentShader.mvpLoc, 1, false, MatrixToFloat(matMVP)); + glUniform4f(currentShader.tintColorLoc, 1.0f, 1.0f, 1.0f, 1.0f); + glUniform1i(currentShader.mapTexture0Loc, 0); + + // NOTE: Additional map textures not considered for default buffers drawing } - else + + // Draw lines buffers + if (lines.vCounter > 0) { - // Bind vertex attrib: position (shader-location = 0) - glBindBuffer(GL_ARRAY_BUFFER, lines.vboId[0]); - glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(currentShader.vertexLoc); - - // Bind vertex attrib: color (shader-location = 3) - glBindBuffer(GL_ARRAY_BUFFER, lines.vboId[1]); - glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); - glEnableVertexAttribArray(currentShader.colorLoc); - } + glBindTexture(GL_TEXTURE_2D, whiteTexture); - glDrawArrays(GL_LINES, 0, lines.vCounter); - - if (!vaoSupported) glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindTexture(GL_TEXTURE_2D, 0); - } + if (vaoSupported) + { + glBindVertexArray(lines.vaoId); + } + else + { + // Bind vertex attrib: position (shader-location = 0) + glBindBuffer(GL_ARRAY_BUFFER, lines.vboId[0]); + glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(currentShader.vertexLoc); + + // Bind vertex attrib: color (shader-location = 3) + glBindBuffer(GL_ARRAY_BUFFER, lines.vboId[1]); + glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); + glEnableVertexAttribArray(currentShader.colorLoc); + } - // Draw triangles buffers - if (triangles.vCounter > 0) - { - glBindTexture(GL_TEXTURE_2D, whiteTexture); + glDrawArrays(GL_LINES, 0, lines.vCounter); - if (vaoSupported) - { - glBindVertexArray(triangles.vaoId); - } - else - { - // Bind vertex attrib: position (shader-location = 0) - glBindBuffer(GL_ARRAY_BUFFER, triangles.vboId[0]); - glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(currentShader.vertexLoc); - - // Bind vertex attrib: color (shader-location = 3) - glBindBuffer(GL_ARRAY_BUFFER, triangles.vboId[1]); - glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); - glEnableVertexAttribArray(currentShader.colorLoc); + if (!vaoSupported) glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindTexture(GL_TEXTURE_2D, 0); } - glDrawArrays(GL_TRIANGLES, 0, triangles.vCounter); + // Draw triangles buffers + if (triangles.vCounter > 0) + { + glBindTexture(GL_TEXTURE_2D, whiteTexture); - if (!vaoSupported) glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindTexture(GL_TEXTURE_2D, 0); - } + if (vaoSupported) + { + glBindVertexArray(triangles.vaoId); + } + else + { + // Bind vertex attrib: position (shader-location = 0) + glBindBuffer(GL_ARRAY_BUFFER, triangles.vboId[0]); + glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(currentShader.vertexLoc); + + // Bind vertex attrib: color (shader-location = 3) + glBindBuffer(GL_ARRAY_BUFFER, triangles.vboId[1]); + glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); + glEnableVertexAttribArray(currentShader.colorLoc); + } - // Draw quads buffers - if (quads.vCounter > 0) - { - int quadsCount = 0; - int numIndicesToProcess = 0; - int indicesOffset = 0; + glDrawArrays(GL_TRIANGLES, 0, triangles.vCounter); - if (vaoSupported) - { - glBindVertexArray(quads.vaoId); + if (!vaoSupported) glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindTexture(GL_TEXTURE_2D, 0); } - else + + // Draw quads buffers + if (quads.vCounter > 0) { - // Bind vertex attrib: position (shader-location = 0) - glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[0]); - glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(currentShader.vertexLoc); - - // Bind vertex attrib: texcoord (shader-location = 1) - glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[1]); - glVertexAttribPointer(currentShader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(currentShader.texcoordLoc); - - // Bind vertex attrib: color (shader-location = 3) - glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[2]); - glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); - glEnableVertexAttribArray(currentShader.colorLoc); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quads.vboId[3]); - } + int quadsCount = 0; + int numIndicesToProcess = 0; + int indicesOffset = 0; - //TraceLog(DEBUG, "Draws required per frame: %i", drawsCounter); + if (vaoSupported) + { + glBindVertexArray(quads.vaoId); + } + else + { + // Bind vertex attrib: position (shader-location = 0) + glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[0]); + glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(currentShader.vertexLoc); + + // Bind vertex attrib: texcoord (shader-location = 1) + glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[1]); + glVertexAttribPointer(currentShader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(currentShader.texcoordLoc); + + // Bind vertex attrib: color (shader-location = 3) + glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[2]); + glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); + glEnableVertexAttribArray(currentShader.colorLoc); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quads.vboId[3]); + } - for (int i = 0; i < drawsCounter; i++) - { - quadsCount = draws[i].vertexCount/4; - numIndicesToProcess = quadsCount*6; // Get number of Quads * 6 index by Quad + //TraceLog(DEBUG, "Draws required per frame: %i", drawsCounter); - //TraceLog(DEBUG, "Quads to render: %i - Vertex Count: %i", quadsCount, draws[i].vertexCount); + for (int i = 0; i < drawsCounter; i++) + { + quadsCount = draws[i].vertexCount/4; + numIndicesToProcess = quadsCount*6; // Get number of Quads * 6 index by Quad - glBindTexture(GL_TEXTURE_2D, draws[i].textureId); + //TraceLog(DEBUG, "Quads to render: %i - Vertex Count: %i", quadsCount, draws[i].vertexCount); - // NOTE: The final parameter tells the GPU the offset in bytes from the start of the index buffer to the location of the first index to process -#if defined(GRAPHICS_API_OPENGL_33) - glDrawElements(GL_TRIANGLES, numIndicesToProcess, GL_UNSIGNED_INT, (GLvoid *)(sizeof(GLuint)*indicesOffset)); -#elif defined(GRAPHICS_API_OPENGL_ES2) - glDrawElements(GL_TRIANGLES, numIndicesToProcess, GL_UNSIGNED_SHORT, (GLvoid *)(sizeof(GLushort)*indicesOffset)); -#endif - //GLenum err; - //if ((err = glGetError()) != GL_NO_ERROR) TraceLog(INFO, "OpenGL error: %i", (int)err); //GL_INVALID_ENUM! + glBindTexture(GL_TEXTURE_2D, draws[i].textureId); - indicesOffset += draws[i].vertexCount/4*6; - } + // NOTE: The final parameter tells the GPU the offset in bytes from the start of the index buffer to the location of the first index to process + #if defined(GRAPHICS_API_OPENGL_33) + glDrawElements(GL_TRIANGLES, numIndicesToProcess, GL_UNSIGNED_INT, (GLvoid *)(sizeof(GLuint)*indicesOffset)); + #elif defined(GRAPHICS_API_OPENGL_ES2) + glDrawElements(GL_TRIANGLES, numIndicesToProcess, GL_UNSIGNED_SHORT, (GLvoid *)(sizeof(GLushort)*indicesOffset)); + #endif + //GLenum err; + //if ((err = glGetError()) != GL_NO_ERROR) TraceLog(INFO, "OpenGL error: %i", (int)err); //GL_INVALID_ENUM! - if (!vaoSupported) - { - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - } + indicesOffset += draws[i].vertexCount/4*6; + } - glBindTexture(GL_TEXTURE_2D, 0); // Unbind textures - } + if (!vaoSupported) + { + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + } - if (vaoSupported) glBindVertexArray(0); // Unbind VAO + glBindTexture(GL_TEXTURE_2D, 0); // Unbind textures + } - glUseProgram(0); // Unbind shader program + if (vaoSupported) glBindVertexArray(0); // Unbind VAO + glUseProgram(0); // Unbind shader program + } + // Reset draws counter drawsCounter = 1; draws[0].textureId = whiteTexture; @@ -3529,6 +3560,10 @@ void rlglDrawDefaultBuffers(void) // Reset depth for next draw currentDepth = -1.0f; + + // Restore projection/modelview matrices + projection = matProjection; + modelview = matModelView; } // Unload default internal buffers vertex data from CPU and GPU diff --git a/src/rlgl.h b/src/rlgl.h index 675bb74f..f52af6f9 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -303,9 +303,6 @@ void rlglClose(void); // De-init rlgl void rlglDraw(void); // Draw VAO/VBO void rlglLoadExtensions(void *loader); // Load OpenGL extensions -void rlglUpdateDefaultBuffers(void); // Update default internal buffers (VAOs/VBOs) with vertex data -void rlglDrawDefaultBuffers(void); // Draw default internal buffers vertex data - unsigned int rlglLoadTexture(void *data, int width, int height, int textureFormat, int mipmapCount); // Load texture in GPU RenderTexture2D rlglLoadRenderTexture(int width, int height); // Load a texture to be used for rendering (fbo with color and depth attachments) void rlglUpdateTexture(unsigned int id, int width, int height, int format, void *data); // Update GPU texture with new data @@ -358,7 +355,6 @@ void TraceLog(int msgType, const char *text, ...); void InitOculusDevice(void); // Init Oculus Rift device void CloseOculusDevice(void); // Close Oculus Rift device void UpdateOculusTracking(void); // Update Oculus Rift tracking (position and orientation) -void SetOculusView(int eye); // Set internal projection and modelview matrix depending on eyes tracking data void BeginOculusDrawing(void); // Begin Oculus drawing configuration void EndOculusDrawing(void); // End Oculus drawing process (and desktop mirror) bool IsOculusReady(void); // Detect if oculus device (or simulator) is ready -- cgit v1.2.3 From bc80174357392c0a16b74cd4a9e497a1de367760 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 6 Jul 2016 00:54:38 +0200 Subject: VR Functions renaming (for generic HMD device) Stereo rendering has been moved again to Begin3dMode() and End3dMode(), it has some limitations but makes more sense... --- examples/core_oculus_rift.c | 19 ++++++++----------- src/core.c | 8 ++++---- src/raylib.h | 29 +++++++++++++++++++++-------- src/rlgl.c | 45 +++++++++++++++++++++++---------------------- src/rlgl.h | 16 ++++++++-------- 5 files changed, 64 insertions(+), 53 deletions(-) (limited to 'src/raylib.h') diff --git a/examples/core_oculus_rift.c b/examples/core_oculus_rift.c index 734ba8fd..fa70c487 100644 --- a/examples/core_oculus_rift.c +++ b/examples/core_oculus_rift.c @@ -23,7 +23,8 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [core] example - oculus rift"); - InitOculusDevice(); + // NOTE: If device is not available, it fallbacks to default device (simulator) + InitVrDevice(HMD_OCULUS_RIFT_CV1); // Init VR device (Oculus Rift CV1) // Define the camera to look into our 3d world Camera camera; @@ -42,9 +43,9 @@ int main() { // Update //---------------------------------------------------------------------------------- - UpdateOculusTracking(); + UpdateVrTracking(); - if (IsKeyPressed(KEY_SPACE)) ToggleVR(); + if (IsKeyPressed(KEY_SPACE)) ToggleVrMode(); //---------------------------------------------------------------------------------- // Draw @@ -52,20 +53,16 @@ int main() BeginDrawing(); ClearBackground(RAYWHITE); - - if (IsOculusReady()) BeginOculusDrawing(); Begin3dMode(camera); DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED); DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, MAROON); - + DrawGrid(10, 1.0f); - + End3dMode(); - - if (IsOculusReady()) EndOculusDrawing(); - + DrawFPS(10, 10); EndDrawing(); @@ -74,7 +71,7 @@ int main() // De-Initialization //-------------------------------------------------------------------------------------- - CloseOculusDevice(); // Close Oculus Rift device + CloseVrDevice(); // Close VR device CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/src/core.c b/src/core.c index f8a83e25..107fc0a0 100644 --- a/src/core.c +++ b/src/core.c @@ -521,8 +521,6 @@ void BeginDrawing(void) updateTime = currentTime - previousTime; previousTime = currentTime; - //if (IsOculusReady()) BeginOculusDrawing(); - rlClearScreenBuffers(); // Clear current framebuffers rlLoadIdentity(); // Reset current matrix (MODELVIEW) rlMultMatrixf(MatrixToFloat(downscaleView)); // If downscale required, apply it here @@ -535,8 +533,6 @@ void BeginDrawing(void) void EndDrawing(void) { rlglDraw(); // Draw Buffers (Only OpenGL 3+ and ES2) - - //if (IsOculusReady()) EndOculusDrawing(); SwapBuffers(); // Copy back buffer to front buffer PollInputEvents(); // Poll user events @@ -590,6 +586,8 @@ void End2dMode(void) void Begin3dMode(Camera camera) { rlglDraw(); // Draw Buffers (Only OpenGL 3+ and ES2) + + if (IsVrDeviceReady()) BeginVrDrawing(); rlMatrixMode(RL_PROJECTION); // Switch to projection matrix @@ -618,6 +616,8 @@ void Begin3dMode(Camera camera) void End3dMode(void) { rlglDraw(); // Process internal buffers (update + draw) + + if (IsVrDeviceReady()) EndVrDrawing(); rlMatrixMode(RL_PROJECTION); // Switch to projection matrix rlPopMatrix(); // Restore previous matrix (PROJECTION) from matrix stack diff --git a/src/raylib.h b/src/raylib.h index 89fc457f..227f83f2 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -527,6 +527,19 @@ typedef struct GestureEvent { // Camera system modes typedef enum { CAMERA_CUSTOM = 0, CAMERA_FREE, CAMERA_ORBITAL, CAMERA_FIRST_PERSON, CAMERA_THIRD_PERSON } CameraMode; +// Head Mounted Display devices +typedef enum { + HMD_DEFAULT_DEVICE = 0, + HMD_OCULUS_RIFT_DK2, + HMD_OCULUS_RIFT_CV1, + HMD_VALVE_HTC_VIVE, + HMD_SAMSUNG_GEAR_VR, + HMD_GOOGLE_CARDBOARD, + HMD_SONY_PLAYSTATION_VR, + HMD_RAZER_OSVR, + HMD_FOVE_VR, +} HmdDevice; + #ifdef __cplusplus extern "C" { // Prevents name mangling of functions #endif @@ -846,16 +859,16 @@ Light CreateLight(int type, Vector3 position, Color diffuse); // Create a void DestroyLight(Light light); // Destroy a light and take it out of the list //------------------------------------------------------------------------------------ -// Oculus Rift CV1 Functions (Module: rlgl) +// VR experience Functions (Module: rlgl) // NOTE: This functions are useless when using OpenGL 1.1 //------------------------------------------------------------------------------------ -void InitOculusDevice(void); // Init Oculus Rift device -void CloseOculusDevice(void); // Close Oculus Rift device -void UpdateOculusTracking(void); // Update Oculus Rift tracking (position and orientation) -void BeginOculusDrawing(void); // Begin Oculus drawing configuration -void EndOculusDrawing(void); // End Oculus drawing process (and desktop mirror) -bool IsOculusReady(void); // Detect if oculus device (or simulator) is ready -void ToggleVR(void); // Enable/Disable VR experience (Oculus device or simulator) +void InitVrDevice(int hmdDevice); // Init VR device +void CloseVrDevice(void); // Close VR device +void UpdateVrTracking(void); // Update VR tracking (position and orientation) +void BeginVrDrawing(void); // Begin VR drawing configuration +void EndVrDrawing(void); // End VR drawing process (and desktop mirror) +bool IsVrDeviceReady(void); // Detect if VR device (or simulator) is ready +void ToggleVrMode(void); // Enable/Disable VR experience (device or simulator) //------------------------------------------------------------------------------------ // Audio Loading and Playing Functions (Module: audio) diff --git a/src/rlgl.c b/src/rlgl.c index af2d57cb..a71142b0 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -322,7 +322,7 @@ static void DrawDefaultBuffers(int eyesCount); // Draw default internal buffers static void UnloadDefaultBuffers(void); // Unload default internal buffers vertex data from CPU and GPU // Set internal projection and modelview matrix depending on eyes tracking data -static void SetOculusView(int eye, Matrix matProjection, Matrix matModelView); +static void SetStereoView(int eye, Matrix matProjection, Matrix matModelView); static void SetShaderLights(Shader shader); // Sets shader uniform values for lights array @@ -2001,7 +2001,7 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) for (int eye = 0; eye < eyesCount; eye++) { - if (eyesCount == 2) SetOculusView(eye, matProjection, matModelView); + if (eyesCount == 2) SetStereoView(eye, matProjection, matModelView); else modelview = matModelView; // Calculate model-view-projection matrix (MVP) @@ -2504,8 +2504,9 @@ void DestroyLight(Light light) #endif } -// Init Oculus Rift device (or Oculus device simulator) -void InitOculusDevice(void) +// Init VR device (or simulator) +// NOTE: If device is not available, it fallbacks to default device (simulator) +void InitVrDevice(int hmdDevice) { #if defined(RLGL_OCULUS_SUPPORT) // Initialize Oculus device @@ -2557,7 +2558,7 @@ void InitOculusDevice(void) if (!oculusReady) { - TraceLog(WARNING, "VR: Initializing Oculus simulator"); + TraceLog(WARNING, "HMD Device not found: Initializing VR simulator"); // Initialize framebuffer and textures for stereo rendering stereoFbo = rlglLoadRenderTexture(screenWidth, screenHeight); @@ -2571,8 +2572,8 @@ void InitOculusDevice(void) } } -// Close Oculus Rift device (or Oculus device simulator) -void CloseOculusDevice(void) +// Close VR device (or simulator) +void CloseVrDevice(void) { #if defined(RLGL_OCULUS_SUPPORT) if (oculusReady) @@ -2596,20 +2597,20 @@ void CloseOculusDevice(void) oculusReady = false; } -// Detect if oculus device is available -bool IsOculusReady(void) +// Detect if VR device is available +bool IsVrDeviceReady(void) { return (oculusReady || oculusSimulator) && vrEnabled; } -// Enable/Disable VR experience (Oculus device or simulator) -void ToggleVR(void) +// Enable/Disable VR experience (device or simulator) +void ToggleVrMode(void) { vrEnabled = !vrEnabled; } -// Update Oculus Rift tracking (position and orientation) -void UpdateOculusTracking(void) +// Update VR tracking (position and orientation) +void UpdateVrTracking(void) { #if defined(RLGL_OCULUS_SUPPORT) if (oculusReady) @@ -2641,7 +2642,7 @@ void UpdateOculusTracking(void) } // Set internal projection and modelview matrix depending on eyes tracking data -static void SetOculusView(int eye, Matrix matProjection, Matrix matModelView) +static void SetStereoView(int eye, Matrix matProjection, Matrix matModelView) { if (vrEnabled) { @@ -2675,12 +2676,12 @@ static void SetOculusView(int eye, Matrix matProjection, Matrix matModelView) // Setup viewport and projection/modelview matrices using tracking data rlViewport(eye*screenWidth/2, 0, screenWidth/2, screenHeight); - static float IPD = 0.064f; // InterpupillaryDistance + static float IPD = 0.064f; // InterpupillaryDistance float HScreenSize = 0.14976f; - float VScreenSize = 0.0936f; // HScreenSize/(1280.0f/800.0f) - float VScreenCenter = 0.04675f; + float VScreenSize = 0.0936f; // HScreenSize/(1280.0f/800.0f) (DK2) + float VScreenCenter = 0.04675f; // VScreenSize/2 float EyeToScreenDistance = 0.041f; - float LensSeparationDistance = 0.064f; //0.0635f (DK1) + float LensSeparationDistance = 0.064f; //0.0635f (DK1) // NOTE: fovy value obtained from device parameters (Oculus Rift CV1) float halfScreenDistance = VScreenSize/2.0f; @@ -2730,13 +2731,13 @@ static void SetOculusView(int eye, Matrix matProjection, Matrix matModelView) MatrixTranspose(&eyeProjection); } - SetMatrixModelview(eyeModelView); // ERROR! We are modifying modelview for next eye!!! + SetMatrixModelview(eyeModelView); SetMatrixProjection(eyeProjection); } } // Begin Oculus drawing configuration -void BeginOculusDrawing(void) +void BeginVrDrawing(void) { #if defined(RLGL_OCULUS_SUPPORT) if (oculusReady) @@ -2771,7 +2772,7 @@ void BeginOculusDrawing(void) } // End Oculus drawing process (and desktop mirror) -void EndOculusDrawing(void) +void EndVrDrawing(void) { #if defined(RLGL_OCULUS_SUPPORT) if (oculusReady) @@ -3414,7 +3415,7 @@ static void DrawDefaultBuffers(int eyesCount) for (int eye = 0; eye < eyesCount; eye++) { - if (eyesCount == 2) SetOculusView(eye, matProjection, matModelView); + if (eyesCount == 2) SetStereoView(eye, matProjection, matModelView); // Set current shader and upload current MVP matrix if ((lines.vCounter > 0) || (triangles.vCounter > 0) || (quads.vCounter > 0)) diff --git a/src/rlgl.h b/src/rlgl.h index f52af6f9..f984c0c6 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -350,15 +350,15 @@ Light CreateLight(int type, Vector3 position, Color diffuse); // Create a void DestroyLight(Light light); // Destroy a light and take it out of the list void TraceLog(int msgType, const char *text, ...); -#endif -void InitOculusDevice(void); // Init Oculus Rift device -void CloseOculusDevice(void); // Close Oculus Rift device -void UpdateOculusTracking(void); // Update Oculus Rift tracking (position and orientation) -void BeginOculusDrawing(void); // Begin Oculus drawing configuration -void EndOculusDrawing(void); // End Oculus drawing process (and desktop mirror) -bool IsOculusReady(void); // Detect if oculus device (or simulator) is ready -void ToggleVR(void); // Enable/Disable VR experience (Oculus device or simulator) +void InitVrDevice(int hmdDevice); // Init VR device +void CloseVrDevice(void); // Close VR device +void UpdateVrTracking(void); // Update VR tracking (position and orientation) +void BeginVrDrawing(void); // Begin VR drawing configuration +void EndVrDrawing(void); // End VR drawing process (and desktop mirror) +bool IsVrDeviceReady(void); // Detect if VR device (or simulator) is ready +void ToggleVrMode(void); // Enable/Disable VR experience (device or simulator) +#endif #ifdef __cplusplus } -- cgit v1.2.3 From 7cefbd8a947551f6c63dba88117099d6c0f4998b Mon Sep 17 00:00:00 2001 From: raysan5 Date: Wed, 6 Jul 2016 20:33:46 +0200 Subject: Updated lighting system... ...to avoid dynamic conditions on for loop (lightsCount) on standard shader, it seems GLSL 100 doesn't support that feature... on some GPUs like RaspberryPi... --- src/raylib.h | 2 +- src/rlgl.c | 196 +++++++++++++++++++++++++++----------------------- src/rlgl.h | 4 +- src/standard_shader.h | 3 +- 4 files changed, 109 insertions(+), 96 deletions(-) (limited to 'src/raylib.h') diff --git a/src/raylib.h b/src/raylib.h index 227f83f2..1d160492 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -431,8 +431,8 @@ typedef struct Model { // Light type typedef struct LightData { unsigned int id; // Light unique id - int type; // Light type: LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT bool enabled; // Light enabled + int type; // Light type: LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT Vector3 position; // Light position Vector3 target; // Light target: LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target) diff --git a/src/rlgl.c b/src/rlgl.c index 089e2809..aa729824 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -260,7 +260,7 @@ static bool texCompASTCSupported = false; // ASTC texture compression support // Lighting data static Light lights[MAX_LIGHTS]; // Lights pool -static int lightsCount; // Enabled lights counter +static int lightsCount = 0; // Enabled lights counter #endif #if defined(RLGL_OCULUS_SUPPORT) @@ -2454,24 +2454,28 @@ Light CreateLight(int type, Vector3 position, Color diffuse) Light light = NULL; #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - // Allocate dynamic memory - light = (Light)malloc(sizeof(LightData)); - - // Initialize light values with generic values - light->id = lightsCount; - light->type = type; - light->enabled = true; - - light->position = position; - light->target = (Vector3){ 0.0f, 0.0f, 0.0f }; - light->intensity = 1.0f; - light->diffuse = diffuse; - - // Add new light to the array - lights[lightsCount] = light; - - // Increase enabled lights count - lightsCount++; + if (lightsCount < MAX_LIGHTS) + { + // Allocate dynamic memory + light = (Light)malloc(sizeof(LightData)); + + // Initialize light values with generic values + light->id = lightsCount; + light->type = type; + light->enabled = true; + + light->position = position; + light->target = (Vector3){ 0.0f, 0.0f, 0.0f }; + light->intensity = 1.0f; + light->diffuse = diffuse; + + // Add new light to the array + lights[lightsCount] = light; + + // Increase enabled lights count + lightsCount++; + } + else TraceLog(WARNING, "Too many lights, only supported up to %i lights", MAX_LIGHTS); #else // TODO: Support OpenGL 1.1 lighting system TraceLog(WARNING, "Lighting currently not supported on OpenGL 1.1"); @@ -2484,23 +2488,26 @@ Light CreateLight(int type, Vector3 position, Color diffuse) void DestroyLight(Light light) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - // Free dynamic memory allocation - free(lights[light->id]); - - // Remove *obj from the pointers array - for (int i = light->id; i < lightsCount; i++) + if (light != NULL) { - // Resort all the following pointers of the array - if ((i + 1) < lightsCount) + // Free dynamic memory allocation + free(lights[light->id]); + + // Remove *obj from the pointers array + for (int i = light->id; i < lightsCount; i++) { - lights[i] = lights[i + 1]; - lights[i]->id = lights[i + 1]->id; + // Resort all the following pointers of the array + if ((i + 1) < lightsCount) + { + lights[i] = lights[i + 1]; + lights[i]->id = lights[i + 1]->id; + } + else free(lights[i]); } - else free(lights[i]); + + // Decrease enabled physic objects count + lightsCount--; } - - // Decrease enabled physic objects count - lightsCount--; #endif } @@ -3625,72 +3632,79 @@ static void UnloadDefaultBuffers(void) // NOTE: It would be far easier with shader UBOs but are not supported on OpenGL ES 2.0f static void SetShaderLights(Shader shader) { - int locPoint = glGetUniformLocation(shader.id, "lightsCount"); - glUniform1i(locPoint, lightsCount); - + int locPoint = -1; char locName[32] = "lights[x].position\0"; - for (int i = 0; i < lightsCount; i++) + for (int i = 0; i < MAX_LIGHTS; i++) { locName[7] = '0' + i; - - memcpy(&locName[10], "enabled\0", strlen("enabled\0") + 1); - locPoint = GetShaderLocation(shader, locName); - glUniform1i(locPoint, lights[i]->enabled); - - memcpy(&locName[10], "type\0", strlen("type\0") + 1); - locPoint = GetShaderLocation(shader, locName); - glUniform1i(locPoint, lights[i]->type); - - memcpy(&locName[10], "diffuse\0", strlen("diffuse\0") + 2); - locPoint = glGetUniformLocation(shader.id, locName); - glUniform4f(locPoint, (float)lights[i]->diffuse.r/255, (float)lights[i]->diffuse.g/255, (float)lights[i]->diffuse.b/255, (float)lights[i]->diffuse.a/255); - - memcpy(&locName[10], "intensity\0", strlen("intensity\0")); - locPoint = glGetUniformLocation(shader.id, locName); - glUniform1f(locPoint, lights[i]->intensity); - - switch (lights[i]->type) + + if (lights[i] != NULL) // Only upload registered lights data { - case LIGHT_POINT: - { - memcpy(&locName[10], "position\0", strlen("position\0") + 1); - locPoint = GetShaderLocation(shader, locName); - glUniform3f(locPoint, lights[i]->position.x, lights[i]->position.y, lights[i]->position.z); - - memcpy(&locName[10], "radius\0", strlen("radius\0") + 2); - locPoint = GetShaderLocation(shader, locName); - glUniform1f(locPoint, lights[i]->radius); - } break; - case LIGHT_DIRECTIONAL: - { - memcpy(&locName[10], "direction\0", strlen("direction\0") + 2); - locPoint = GetShaderLocation(shader, locName); - Vector3 direction = { lights[i]->target.x - lights[i]->position.x, lights[i]->target.y - lights[i]->position.y, lights[i]->target.z - lights[i]->position.z }; - VectorNormalize(&direction); - glUniform3f(locPoint, direction.x, direction.y, direction.z); - } break; - case LIGHT_SPOT: + memcpy(&locName[10], "enabled\0", strlen("enabled\0") + 1); + locPoint = GetShaderLocation(shader, locName); + glUniform1i(locPoint, lights[i]->enabled); + + memcpy(&locName[10], "type\0", strlen("type\0") + 1); + locPoint = GetShaderLocation(shader, locName); + glUniform1i(locPoint, lights[i]->type); + + memcpy(&locName[10], "diffuse\0", strlen("diffuse\0") + 2); + locPoint = glGetUniformLocation(shader.id, locName); + glUniform4f(locPoint, (float)lights[i]->diffuse.r/255, (float)lights[i]->diffuse.g/255, (float)lights[i]->diffuse.b/255, (float)lights[i]->diffuse.a/255); + + memcpy(&locName[10], "intensity\0", strlen("intensity\0")); + locPoint = glGetUniformLocation(shader.id, locName); + glUniform1f(locPoint, lights[i]->intensity); + + switch (lights[i]->type) { - memcpy(&locName[10], "position\0", strlen("position\0") + 1); - locPoint = GetShaderLocation(shader, locName); - glUniform3f(locPoint, lights[i]->position.x, lights[i]->position.y, lights[i]->position.z); - - memcpy(&locName[10], "direction\0", strlen("direction\0") + 2); - locPoint = GetShaderLocation(shader, locName); - - Vector3 direction = { lights[i]->target.x - lights[i]->position.x, lights[i]->target.y - lights[i]->position.y, lights[i]->target.z - lights[i]->position.z }; - VectorNormalize(&direction); - glUniform3f(locPoint, direction.x, direction.y, direction.z); - - memcpy(&locName[10], "coneAngle\0", strlen("coneAngle\0")); - locPoint = GetShaderLocation(shader, locName); - glUniform1f(locPoint, lights[i]->coneAngle); - } break; - default: break; + case LIGHT_POINT: + { + memcpy(&locName[10], "position\0", strlen("position\0") + 1); + locPoint = GetShaderLocation(shader, locName); + glUniform3f(locPoint, lights[i]->position.x, lights[i]->position.y, lights[i]->position.z); + + memcpy(&locName[10], "radius\0", strlen("radius\0") + 2); + locPoint = GetShaderLocation(shader, locName); + glUniform1f(locPoint, lights[i]->radius); + } break; + case LIGHT_DIRECTIONAL: + { + memcpy(&locName[10], "direction\0", strlen("direction\0") + 2); + locPoint = GetShaderLocation(shader, locName); + Vector3 direction = { lights[i]->target.x - lights[i]->position.x, lights[i]->target.y - lights[i]->position.y, lights[i]->target.z - lights[i]->position.z }; + VectorNormalize(&direction); + glUniform3f(locPoint, direction.x, direction.y, direction.z); + } break; + case LIGHT_SPOT: + { + memcpy(&locName[10], "position\0", strlen("position\0") + 1); + locPoint = GetShaderLocation(shader, locName); + glUniform3f(locPoint, lights[i]->position.x, lights[i]->position.y, lights[i]->position.z); + + memcpy(&locName[10], "direction\0", strlen("direction\0") + 2); + locPoint = GetShaderLocation(shader, locName); + + Vector3 direction = { lights[i]->target.x - lights[i]->position.x, lights[i]->target.y - lights[i]->position.y, lights[i]->target.z - lights[i]->position.z }; + VectorNormalize(&direction); + glUniform3f(locPoint, direction.x, direction.y, direction.z); + + memcpy(&locName[10], "coneAngle\0", strlen("coneAngle\0")); + locPoint = GetShaderLocation(shader, locName); + glUniform1f(locPoint, lights[i]->coneAngle); + } break; + default: break; + } + + // TODO: Pass to the shader any other required data from LightData struct + } + else // Not enabled lights + { + memcpy(&locName[10], "enabled\0", strlen("enabled\0") + 1); + locPoint = GetShaderLocation(shader, locName); + glUniform1i(locPoint, 0); } - - // TODO: Pass to the shader any other required data from LightData struct } } diff --git a/src/rlgl.h b/src/rlgl.h index f984c0c6..9afafc52 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -218,9 +218,9 @@ typedef enum { OPENGL_11 = 1, OPENGL_21, OPENGL_33, OPENGL_ES_20 } GlVersion; // Light type typedef struct LightData { unsigned int id; // Light unique id - int type; // Light type: LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT bool enabled; // Light enabled - + int type; // Light type: LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT + Vector3 position; // Light position Vector3 target; // Light target: LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target) float radius; // Light attenuation radius light intensity reduced with distance (world distance) diff --git a/src/standard_shader.h b/src/standard_shader.h index e1668ae7..deae7fe1 100644 --- a/src/standard_shader.h +++ b/src/standard_shader.h @@ -78,7 +78,6 @@ static const char fStandardShaderStr[] = " float radius; \n" " float coneAngle; }; \n" "const int maxLights = 8; \n" -"uniform int lightsCount; \n" "uniform Light lights[maxLights]; \n" "\n" "vec3 CalcPointLight(Light l, vec3 n, vec3 v, float s) \n" @@ -157,7 +156,7 @@ static const char fStandardShaderStr[] = #elif defined(GRAPHICS_API_OPENGL_33) " if (useSpecular == 1) spec *= normalize(texture(texture2, fragTexCoord).r);\n" #endif -" for (int i = 0; i < lightsCount; i++)\n" +" for (int i = 0; i < maxLights; i++)\n" " {\n" " if (lights[i].enabled == 1)\n" " {\n" -- cgit v1.2.3 From 17331258738229ca087437c31bbfc3c9495fe42e Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 8 Jul 2016 23:17:18 +0200 Subject: Do not expose raw audio context to final user... ...at least, directly, available if using directly audio module... --- src/audio.h | 4 ++-- src/raylib.h | 11 ++--------- 2 files changed, 4 insertions(+), 11 deletions(-) (limited to 'src/raylib.h') diff --git a/src/audio.h b/src/audio.h index fe72d866..3ffe575c 100644 --- a/src/audio.h +++ b/src/audio.h @@ -100,10 +100,10 @@ void PauseMusicStream(int index); // Pause music p void ResumeMusicStream(int index); // Resume playing paused music bool IsMusicPlaying(int index); // Check if music is playing void SetMusicVolume(int index, float volume); // Set volume for music (1.0 is max level) +void SetMusicPitch(int index, float pitch); // Set pitch for a music (1.0 is base level) float GetMusicTimeLength(int index); // Get music time length (in seconds) float GetMusicTimePlayed(int index); // Get current music time played (in seconds) -int GetMusicStreamCount(void); -void SetMusicPitch(int index, float pitch); +int GetMusicStreamCount(void); // Get number of streams loaded // used to output raw audio streams, returns negative numbers on error // if floating point is false the data size is 16bit short, otherwise it is float 32bit diff --git a/src/raylib.h b/src/raylib.h index 1d160492..9225c5ee 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -895,17 +895,10 @@ void PauseMusicStream(int index); // Pause music p void ResumeMusicStream(int index); // Resume playing paused music bool IsMusicPlaying(int index); // Check if music is playing void SetMusicVolume(int index, float volume); // Set volume for music (1.0 is max level) +void SetMusicPitch(int index, float pitch); // Set pitch for a music (1.0 is base level) float GetMusicTimeLength(int index); // Get current music time length (in seconds) float GetMusicTimePlayed(int index); // Get current music time played (in seconds) -int GetMusicStreamCount(void); -void SetMusicPitch(int index, float pitch); - -// used to output raw audio streams, returns negative numbers on error -// if floating point is false the data size is 16bit short, otherwise it is float 32bit -RawAudioContext InitRawAudioContext(int sampleRate, int channels, bool floatingPoint); - -void CloseRawAudioContext(RawAudioContext ctx); -int BufferRawAudioContext(RawAudioContext ctx, void *data, unsigned short numberElements); // returns number of elements buffered +int GetMusicStreamCount(void); // Get number of streams loaded #ifdef __cplusplus } -- cgit v1.2.3 From 7959ccd84dd9eedd7aad10fe8b6bea988f828f40 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Fri, 15 Jul 2016 18:16:34 +0200 Subject: Review some functions, formatting and comments --- src/audio.c | 240 ++++++++++++++++++++++++++++++++--------------------------- src/audio.h | 31 +++++--- src/raylib.h | 2 - 3 files changed, 148 insertions(+), 125 deletions(-) (limited to 'src/raylib.h') diff --git a/src/audio.c b/src/audio.c index 2941b9fb..38fefd12 100644 --- a/src/audio.c +++ b/src/audio.c @@ -2,13 +2,26 @@ * * raylib.audio * -* Basic functions to manage Audio: InitAudioDevice, LoadAudioFiles, PlayAudioFiles +* Basic functions to manage Audio: +* Manage audio device (init/close) +* Load and Unload audio files +* Play/Stop/Pause/Resume loaded audio +* Manage mixing channels +* Manage raw audio context * * Uses external lib: * OpenAL Soft - Audio device management lib (http://kcat.strangesoft.net/openal.html) * stb_vorbis - Ogg audio files loading (http://www.nothings.org/stb_vorbis/) +* jar_xm - XM module file loading +* jar_mod - MOD audio file loading * -* Copyright (c) 2014 Ramon Santamaria (@raysan5) +* Many thanks to Joshua Reisenauer (github: @kd7tck) for the following additions: +* XM audio module support (jar_xm) +* MOD audio module support (jar_mod) +* Mixing channels support +* Raw audio context support +* +* Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event * will the authors be held liable for any damages arising from the use of this software. @@ -68,9 +81,9 @@ //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- -#define MAX_STREAM_BUFFERS 2 // Number of buffers for each alSource -#define MAX_MIX_CHANNELS 4 // Number of OpenAL sources +#define MAX_STREAM_BUFFERS 2 // Number of buffers for each source #define MAX_MUSIC_STREAMS 2 // Number of simultanious music sources +#define MAX_MIX_CHANNELS 4 // Number of mix channels (OpenAL sources) #if defined(PLATFORM_RPI) || defined(PLATFORM_ANDROID) // NOTE: On RPI and Android should be lower to avoid frame-stalls @@ -143,7 +156,7 @@ typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType; // Global Variables Definition //---------------------------------------------------------------------------------- static Music musicStreams[MAX_MUSIC_STREAMS]; // Current music loaded, up to two can play at the same time -static MixChannel *mixChannels[MAX_MIX_CHANNELS]; // What mix channels are currently active +static MixChannel *mixChannels[MAX_MIX_CHANNELS]; // Mix channels currently active (from music streams) static int lastAudioError = 0; // Registers last audio error @@ -157,13 +170,11 @@ static void UnloadWave(Wave wave); // Unload wave data static bool BufferMusicStream(int index, int numBuffers); // Fill music buffers with data static void EmptyMusicStream(int index); // Empty music buffers -static MixChannel *InitMixChannel(unsigned short sampleRate, unsigned char mixChannel, unsigned char channels, bool floatingPoint); // For streaming into mix channels. +static MixChannel *InitMixChannel(unsigned short sampleRate, unsigned char mixChannel, unsigned char channels, bool floatingPoint); static void CloseMixChannel(MixChannel *mixc); // Frees mix channel -static int BufferMixChannel(MixChannel *mixc, void *data, int numberElements); // Pushes more audio data into mixc mix channel, if NULL is passed it pauses -static int FillAlBufferWithSilence(MixChannel *mixc, ALuint buffer); // Fill buffer with zeros, returns number processed -static void ResampleShortToFloat(short *shorts, float *floats, unsigned short len); // Pass two arrays of the same legnth in -static void ResampleByteToFloat(char *chars, float *floats, unsigned short len); // Pass two arrays of same length in -static int IsMusicStreamReadyForBuffering(int index); // Checks if music buffer is ready to be refilled +static int BufferMixChannel(MixChannel *mixc, void *data, int numberElements); // Pushes more audio data into mix channel +//static void ResampleShortToFloat(short *shorts, float *floats, unsigned short len); // Pass two arrays of the same legnth in +//static void ResampleByteToFloat(char *chars, float *floats, unsigned short len); // Pass two arrays of same length in #if defined(AUDIO_STANDALONE) const char *GetExtension(const char *fileName); // Get the extension for a filename @@ -204,7 +215,7 @@ void InitAudioDevice(void) // Close the audio device for all contexts void CloseAudioDevice(void) { - for (int index=0; index= MAX_MIX_CHANNELS) return NULL; @@ -280,7 +291,20 @@ static MixChannel *InitMixChannel(unsigned short sampleRate, unsigned char mixCh alGenBuffers(MAX_STREAM_BUFFERS, mixc->alBuffer); // Fill buffers - for (int i = 0; i < MAX_STREAM_BUFFERS; i++) FillAlBufferWithSilence(mixc, mixc->alBuffer[i]); + for (int i = 0; i < MAX_STREAM_BUFFERS; i++) + { + // Initialize buffer with zeros by default + if (mixc->floatingPoint) + { + float pcm[MUSIC_BUFFER_SIZE_FLOAT] = { 0.0f }; + alBufferData(mixc->alBuffer[i], mixc->alFormat, pcm, MUSIC_BUFFER_SIZE_FLOAT*sizeof(float), mixc->sampleRate); + } + else + { + short pcm[MUSIC_BUFFER_SIZE_SHORT] = { 0 }; + alBufferData(mixc->alBuffer[i], mixc->alFormat, pcm, MUSIC_BUFFER_SIZE_SHORT*sizeof(short), mixc->sampleRate); + } + } alSourceQueueBuffers(mixc->alSource, MAX_STREAM_BUFFERS, mixc->alBuffer); mixc->playing = true; @@ -320,9 +344,9 @@ static void CloseMixChannel(MixChannel *mixc) } } -// Pushes more audio data into mixc mix channel, only one buffer per call +// Pushes more audio data into mix channel, only one buffer per call // Call "BufferMixChannel(mixc, NULL, 0)" if you want to pause the audio. -// @Returns number of samples that where processed. +// Returns number of samples that where processed. static int BufferMixChannel(MixChannel *mixc, void *data, int numberElements) { if (!mixc || (mixChannels[mixc->mixChannel] != mixc)) return 0; // When there is two channels there must be an even number of samples @@ -368,28 +392,11 @@ static int BufferMixChannel(MixChannel *mixc, void *data, int numberElements) return numberElements; } -// fill buffer with zeros, returns number processed -static int FillAlBufferWithSilence(MixChannel *mixc, ALuint buffer) -{ - if (mixc->floatingPoint) - { - float pcm[MUSIC_BUFFER_SIZE_FLOAT] = { 0.0f }; - alBufferData(buffer, mixc->alFormat, pcm, MUSIC_BUFFER_SIZE_FLOAT*sizeof(float), mixc->sampleRate); - - return MUSIC_BUFFER_SIZE_FLOAT; - } - else - { - short pcm[MUSIC_BUFFER_SIZE_SHORT] = { 0 }; - alBufferData(buffer, mixc->alFormat, pcm, MUSIC_BUFFER_SIZE_SHORT*sizeof(short), mixc->sampleRate); - - return MUSIC_BUFFER_SIZE_SHORT; - } -} - +/* +// Convert data from short to float // example usage: -// short sh[3] = {1,2,3};float fl[3]; -// ResampleShortToFloat(sh,fl,3); +// short sh[3] = {1,2,3};float fl[3]; +// ResampleShortToFloat(sh,fl,3); static void ResampleShortToFloat(short *shorts, float *floats, unsigned short len) { for (int i = 0; i < len; i++) @@ -399,9 +406,10 @@ static void ResampleShortToFloat(short *shorts, float *floats, unsigned short le } } +// Convert data from float to short // example usage: -// char ch[3] = {1,2,3};float fl[3]; -// ResampleByteToFloat(ch,fl,3); +// char ch[3] = {1,2,3};float fl[3]; +// ResampleByteToFloat(ch,fl,3); static void ResampleByteToFloat(char *chars, float *floats, unsigned short len) { for (int i = 0; i < len; i++) @@ -410,43 +418,55 @@ static void ResampleByteToFloat(char *chars, float *floats, unsigned short len) else floats[i] = (float)chars[i]/128.0f; } } +*/ -// used to output raw audio streams, returns negative numbers on error, + number represents the mix channel index -// if floating point is false the data size is 16bit short, otherwise it is float 32bit -RawAudioContext InitRawAudioContext(int sampleRate, int channels, bool floatingPoint) +// Initialize raw audio mix channel for audio buffering +// NOTE: Returns mix channel index or -1 if it fails (errors are registered on lastAudioError) +int InitRawMixChannel(int sampleRate, int channels, bool floatingPoint) { int mixIndex; + for (mixIndex = 0; mixIndex < MAX_MIX_CHANNELS; mixIndex++) // find empty mix channel slot { if (mixChannels[mixIndex] == NULL) break; - else if (mixIndex == (MAX_MIX_CHANNELS - 1)) return ERROR_OUT_OF_MIX_CHANNELS; // error + else if (mixIndex == (MAX_MIX_CHANNELS - 1)) + { + lastAudioError = ERROR_OUT_OF_MIX_CHANNELS; + return -1; + } } if (InitMixChannel(sampleRate, mixIndex, channels, floatingPoint)) return mixIndex; - else return ERROR_RAW_CONTEXT_CREATION; // error -} - -void CloseRawAudioContext(RawAudioContext ctx) -{ - if (mixChannels[ctx]) CloseMixChannel(mixChannels[ctx]); + else + { + lastAudioError = ERROR_RAW_CONTEXT_CREATION; + return -1; + } } -// if 0 is returned, the buffers are still full and you need to keep trying with the same data until a + number is returned. -// any + number returned is the number of samples that was processed and passed into buffer. -// data either needs to be array of floats or shorts. -int BufferRawAudioContext(RawAudioContext ctx, void *data, unsigned short numberElements) +// Buffers data directly to raw mix channel +// if 0 is returned, buffers are still full and you need to keep trying with the same data +// otherwise it will return number of samples buffered. +// NOTE: Data could be either be an array of floats or shorts, depending on the created context +int BufferRawAudioContext(int ctx, void *data, unsigned short numberElements) { int numBuffered = 0; if (ctx >= 0) { - MixChannel* mixc = mixChannels[ctx]; + MixChannel *mixc = mixChannels[ctx]; numBuffered = BufferMixChannel(mixc, data, numberElements); } return numBuffered; } +// Closes and frees raw mix channel +void CloseRawAudioContext(int ctx) +{ + if (mixChannels[ctx]) CloseMixChannel(mixChannels[ctx]); +} + //---------------------------------------------------------------------------------- // Module Functions Definition - Sounds loading and playing (.WAV) //---------------------------------------------------------------------------------- @@ -804,7 +824,7 @@ void SetSoundPitch(Sound sound, float pitch) //---------------------------------------------------------------------------------- // Start music playing (open stream) -// returns 0 on success +// returns 0 on success or error code int PlayMusicStream(int index, char *fileName) { int mixIndex; @@ -866,7 +886,7 @@ int PlayMusicStream(int index, char *fileName) musicStreams[index].loop = true; jar_xm_set_max_loop_count(musicStreams[index].xmctx, 0); // infinite number of loops musicStreams[index].totalSamplesLeft = (unsigned int)jar_xm_get_remaining_samples(musicStreams[index].xmctx); - musicStreams[index].totalLengthSeconds = ((float)musicStreams[index].totalSamplesLeft) / 48000.f; + musicStreams[index].totalLengthSeconds = ((float)musicStreams[index].totalSamplesLeft)/48000.0f; musicStreams[index].enabled = true; TraceLog(INFO, "[%s] XM number of samples: %i", fileName, musicStreams[index].totalSamplesLeft); @@ -893,7 +913,7 @@ int PlayMusicStream(int index, char *fileName) musicStreams[index].chipTune = true; musicStreams[index].loop = true; musicStreams[index].totalSamplesLeft = (unsigned int)jar_mod_max_samples(&musicStreams[index].modctx); - musicStreams[index].totalLengthSeconds = ((float)musicStreams[index].totalSamplesLeft) / 48000.f; + musicStreams[index].totalLengthSeconds = ((float)musicStreams[index].totalSamplesLeft)/48000.0f; musicStreams[index].enabled = true; TraceLog(INFO, "[%s] MOD number of samples: %i", fileName, musicStreams[index].totalSamplesLeft); @@ -944,6 +964,51 @@ void StopMusicStream(int index) } } +// Update (re-fill) music buffers if data already processed +void UpdateMusicStream(int index) +{ + ALenum state; + bool active = true; + ALint processed = 0; + + // Determine if music stream is ready to be written + alGetSourcei(musicStreams[index].mixc->alSource, AL_BUFFERS_PROCESSED, &processed); + + if (musicStreams[index].mixc->playing && (index < MAX_MUSIC_STREAMS) && musicStreams[index].enabled && musicStreams[index].mixc && (processed > 0)) + { + active = BufferMusicStream(index, processed); + + if (!active && musicStreams[index].loop) + { + if (musicStreams[index].chipTune) + { + if(musicStreams[index].modctx.mod_loaded) jar_mod_seek_start(&musicStreams[index].modctx); + + musicStreams[index].totalSamplesLeft = musicStreams[index].totalLengthSeconds*48000.0f; + } + else + { + stb_vorbis_seek_start(musicStreams[index].stream); + musicStreams[index].totalSamplesLeft = stb_vorbis_stream_length_in_samples(musicStreams[index].stream)*musicStreams[index].mixc->channels; + } + + // Determine if music stream is ready to be written + alGetSourcei(musicStreams[index].mixc->alSource, AL_BUFFERS_PROCESSED, &processed); + + active = BufferMusicStream(index, processed); + } + + if (alGetError() != AL_NO_ERROR) TraceLog(WARNING, "Error buffering data..."); + + alGetSourcei(musicStreams[index].mixc->alSource, AL_SOURCE_STATE, &state); + + if (state != AL_PLAYING && active) alSourcePlay(musicStreams[index].mixc->alSource); + + if (!active) StopMusicStream(index); + + } +} + //get number of music channels active at this time, this does not mean they are playing int GetMusicStreamCount(void) { @@ -1045,18 +1110,18 @@ float GetMusicTimePlayed(int index) { uint64_t samples; jar_xm_get_position(musicStreams[index].xmctx, NULL, NULL, NULL, &samples); - secondsPlayed = (float)samples / (48000.f * musicStreams[index].mixc->channels); // Not sure if this is the correct value + secondsPlayed = (float)samples/(48000.0f*musicStreams[index].mixc->channels); // Not sure if this is the correct value } else if(musicStreams[index].chipTune && musicStreams[index].modctx.mod_loaded) { long numsamp = jar_mod_current_samples(&musicStreams[index].modctx); - secondsPlayed = (float)numsamp / (48000.f); + secondsPlayed = (float)numsamp/(48000.0f); } else { - int totalSamples = stb_vorbis_stream_length_in_samples(musicStreams[index].stream) * musicStreams[index].mixc->channels; + int totalSamples = stb_vorbis_stream_length_in_samples(musicStreams[index].stream)*musicStreams[index].mixc->channels; int samplesPlayed = totalSamples - musicStreams[index].totalSamplesLeft; - secondsPlayed = (float)samplesPlayed / (musicStreams[index].mixc->sampleRate * musicStreams[index].mixc->channels); + secondsPlayed = (float)samplesPlayed/(musicStreams[index].mixc->sampleRate*musicStreams[index].mixc->channels); } } @@ -1144,53 +1209,6 @@ static void EmptyMusicStream(int index) } } -// Determine if a music stream is ready to be written -static int IsMusicStreamReadyForBuffering(int index) -{ - ALint processed = 0; - alGetSourcei(musicStreams[index].mixc->alSource, AL_BUFFERS_PROCESSED, &processed); - return processed; -} - -// Update (re-fill) music buffers if data already processed -void UpdateMusicStream(int index) -{ - ALenum state; - bool active = true; - int numBuffers = IsMusicStreamReadyForBuffering(index); - - if (musicStreams[index].mixc->playing && (index < MAX_MUSIC_STREAMS) && musicStreams[index].enabled && musicStreams[index].mixc && numBuffers) - { - active = BufferMusicStream(index, numBuffers); - - if (!active && musicStreams[index].loop) - { - if (musicStreams[index].chipTune) - { - if(musicStreams[index].modctx.mod_loaded) jar_mod_seek_start(&musicStreams[index].modctx); - - musicStreams[index].totalSamplesLeft = musicStreams[index].totalLengthSeconds * 48000.f; - } - else - { - stb_vorbis_seek_start(musicStreams[index].stream); - musicStreams[index].totalSamplesLeft = stb_vorbis_stream_length_in_samples(musicStreams[index].stream) * musicStreams[index].mixc->channels; - } - - active = BufferMusicStream(index, IsMusicStreamReadyForBuffering(index)); - } - - if (alGetError() != AL_NO_ERROR) TraceLog(WARNING, "Error buffering data..."); - - alGetSourcei(musicStreams[index].mixc->alSource, AL_SOURCE_STATE, &state); - - if (state != AL_PLAYING && active) alSourcePlay(musicStreams[index].mixc->alSource); - - if (!active) StopMusicStream(index); - - } -} - // Load WAV file into Wave structure static Wave LoadWAV(const char *fileName) { diff --git a/src/audio.h b/src/audio.h index 3ffe575c..f4a82a55 100644 --- a/src/audio.h +++ b/src/audio.h @@ -2,13 +2,26 @@ * * raylib.audio * -* Basic functions to manage Audio: InitAudioDevice, LoadAudioFiles, PlayAudioFiles +* Basic functions to manage Audio: +* Manage audio device (init/close) +* Load and Unload audio files +* Play/Stop/Pause/Resume loaded audio +* Manage mixing channels +* Manage raw audio context * * Uses external lib: * OpenAL Soft - Audio device management lib (http://kcat.strangesoft.net/openal.html) * stb_vorbis - Ogg audio files loading (http://www.nothings.org/stb_vorbis/) +* jar_xm - XM module file loading +* jar_mod - MOD audio file loading * -* Copyright (c) 2015 Ramon Santamaria (@raysan5) +* Many thanks to Joshua Reisenauer (github: @kd7tck) for the following additions: +* XM audio module support (jar_xm) +* MOD audio module support (jar_mod) +* Mixing channels support +* Raw audio context support +* +* Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event * will the authors be held liable for any damages arising from the use of this software. @@ -63,9 +76,6 @@ typedef struct Wave { short channels; } Wave; -typedef int RawAudioContext; - - #ifdef __cplusplus extern "C" { // Prevents name mangling of functions #endif @@ -80,7 +90,7 @@ extern "C" { // Prevents name mangling of functions //---------------------------------------------------------------------------------- void InitAudioDevice(void); // Initialize audio device and context void CloseAudioDevice(void); // Close the audio device and context (and music stream) -bool IsAudioDeviceReady(void); // True if call to InitAudioDevice() was successful and CloseAudioDevice() has not been called yet +bool IsAudioDeviceReady(void); // Check if device has been initialized successfully Sound LoadSound(char *fileName); // Load sound to memory Sound LoadSoundFromWave(Wave wave); // Load sound to memory from wave data @@ -105,12 +115,9 @@ float GetMusicTimeLength(int index); // Get music tim float GetMusicTimePlayed(int index); // Get current music time played (in seconds) int GetMusicStreamCount(void); // Get number of streams loaded -// used to output raw audio streams, returns negative numbers on error -// if floating point is false the data size is 16bit short, otherwise it is float 32bit -RawAudioContext InitRawAudioContext(int sampleRate, int channels, bool floatingPoint); - -void CloseRawAudioContext(RawAudioContext ctx); -int BufferRawAudioContext(RawAudioContext ctx, void *data, unsigned short numberElements); // returns number of elements buffered +int InitRawMixChannel(int sampleRate, int channels, bool floatingPoint); // Initialize raw audio mix channel for audio buffering +int BufferRawMixChannel(int mixc, void *data, unsigned short numberElements); // Buffers data directly to raw mix channel +void CloseRawMixChannel(int mixc); // Closes and frees raw mix channel #ifdef __cplusplus } diff --git a/src/raylib.h b/src/raylib.h index 9225c5ee..e3a17ebb 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -468,8 +468,6 @@ typedef struct Wave { short channels; } Wave; -typedef int RawAudioContext; - // Texture formats // NOTE: Support depends on OpenGL version and platform typedef enum { -- cgit v1.2.3