diff --git a/raylib/core.c b/raylib/core.c index 1d502c0..931989e 100644 --- a/raylib/core.c +++ b/raylib/core.c @@ -755,11 +755,8 @@ void End2dMode(void) void Begin3dMode(Camera camera) { rlglDraw(); // Draw Buffers (Only OpenGL 3+ and ES2) - - if (IsVrDeviceReady() || IsVrSimulator()) BeginVrDrawing(); - + rlMatrixMode(RL_PROJECTION); // Switch to projection matrix - rlPushMatrix(); // Save previous matrix, which contains the settings for the 2d ortho projection rlLoadIdentity(); // Reset current matrix (PROJECTION) @@ -786,8 +783,6 @@ void End3dMode(void) { rlglDraw(); // Process internal buffers (update + draw) - if (IsVrDeviceReady() || IsVrSimulator()) EndVrDrawing(); - rlMatrixMode(RL_PROJECTION); // Switch to projection matrix rlPopMatrix(); // Restore previous matrix (PROJECTION) from matrix stack diff --git a/raylib/raylib.h b/raylib/raylib.h index b0f03bb..e679e01 100644 --- a/raylib/raylib.h +++ b/raylib/raylib.h @@ -687,6 +687,7 @@ RLAPI Color Fade(Color color, float alpha); // Color fade- RLAPI void SetConfigFlags(char flags); // Setup some window configuration flags RLAPI void ShowLogo(void); // Activates raylib logo at startup (can be done with flags) +//RLAPI void TraceLog(int logType, const char *text, ...); // Trace log messages showing (INFO, WARNING, ERROR, DEBUG) RLAPI bool IsFileDropped(void); // Check if a file have been dropped into window RLAPI char **GetDroppedFiles(int *count); // Retrieve dropped files into window @@ -764,6 +765,7 @@ RLAPI void DrawPixelV(Vector2 position, Color color); RLAPI void DrawLine(int startPosX, int startPosY, int endPosX, int endPosY, Color color); // Draw a line RLAPI void DrawLineV(Vector2 startPos, Vector2 endPos, Color color); // Draw a line (Vector version) RLAPI void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw a line defining thickness +RLAPI void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw a line using cubic-bezier curves in-out RLAPI void DrawCircle(int centerX, int centerY, float radius, Color color); // Draw a color-filled circle RLAPI void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2); // Draw a gradient-filled circle RLAPI void DrawCircleV(Vector2 center, float radius, Color color); // Draw a color-filled circle (Vector version) @@ -943,12 +945,13 @@ RLAPI void EndBlendMode(void); // End // VR experience Functions (Module: rlgl) // NOTE: This functions are useless when using OpenGL 1.1 //------------------------------------------------------------------------------------ -RLAPI void InitVrDevice(int vdDevice); // Init VR device -RLAPI void CloseVrDevice(void); // Close VR device -RLAPI bool IsVrDeviceReady(void); // Detect if VR device is ready -RLAPI bool IsVrSimulator(void); // Detect if VR simulator is running -RLAPI void UpdateVrTracking(Camera *camera); // Update VR tracking (position and orientation) and camera -RLAPI void ToggleVrMode(void); // Enable/Disable VR experience (device or simulator) +RLAPI void InitVrSimulator(int vrDevice); // Init VR simulator for selected device +RLAPI void CloseVrSimulator(void); // Close VR simulator for current device +RLAPI bool IsVrSimulatorReady(void); // Detect if VR device is ready +RLAPI void UpdateVrTracking(Camera *camera); // Update VR tracking (position and orientation) and camera +RLAPI void ToggleVrMode(void); // Enable/Disable VR experience (device or simulator) +RLAPI void BeginVrDrawing(void); // Begin VR simulator stereo rendering +RLAPI void EndVrDrawing(void); // End VR simulator stereo rendering //------------------------------------------------------------------------------------ // Audio Loading and Playing Functions (Module: audio) diff --git a/raylib/rlgl.c b/raylib/rlgl.c index ffc9d74..0099862 100644 --- a/raylib/rlgl.c +++ b/raylib/rlgl.c @@ -37,9 +37,7 @@ * * #define SUPPORT_SHADER_DISTORTION * -* -* #define SUPPORT_OCULUS_RIFT_CV1 / RLGL_OCULUS_SUPPORT -* Enable Oculus Rift CV1 functionality +* #define SUPPORT_VR_SIMULATION * * #define SUPPORT_STEREO_RENDERING * @@ -121,17 +119,6 @@ #include "shader_distortion.h" // Distortion shader to be embedded #endif -//#define RLGL_OCULUS_SUPPORT // Enable Oculus Rift code -#if defined(RLGL_OCULUS_SUPPORT) - #include "external/OculusSDK/LibOVR/Include/OVR_CAPI_GL.h" // Oculus SDK for OpenGL -#endif - -#if defined(RLGL_STANDALONE) - #define OCULUSAPI -#else - #define OCULUSAPI static -#endif - //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- @@ -187,15 +174,15 @@ #endif #if defined(GRAPHICS_API_OPENGL_11) - #define GL_UNSIGNED_SHORT_5_6_5 0x8363 - #define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 - #define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 + #define GL_UNSIGNED_SHORT_5_6_5 0x8363 + #define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 + #define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 #endif #if defined(GRAPHICS_API_OPENGL_ES2) - #define glClearDepth glClearDepthf - #define GL_READ_FRAMEBUFFER GL_FRAMEBUFFER - #define GL_DRAW_FRAMEBUFFER GL_FRAMEBUFFER + #define glClearDepth glClearDepthf + #define GL_READ_FRAMEBUFFER GL_FRAMEBUFFER + #define GL_DRAW_FRAMEBUFFER GL_FRAMEBUFFER #endif // Default vertex attribute names on shader to set location points @@ -267,32 +254,6 @@ typedef struct VrStereoConfig { Matrix eyesViewOffset[2]; // VR stereo rendering eyes view offset matrices } VrStereoConfig; -#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 //---------------------------------------------------------------------------------- @@ -343,24 +304,11 @@ static float maxAnisotropicLevel = 0.0f; // Maximum anisotropy level supp // Extension supported flag: Clamp mirror wrap mode static bool texClampMirrorSupported = false; // Clamp mirror wrap mode supported -#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 - // VR global variables static VrDeviceInfo hmd; // Current VR device info static VrStereoConfig vrConfig; // VR stereo configuration for simulator -static bool vrDeviceReady = false; // VR device ready flag -static bool vrSimulator = false; // VR simulator enabled flag -static bool vrEnabled = false; // VR experience enabled (device or simulator) -static bool vrRendering = true; // VR stereo rendering enabled/disabled flag +static bool vrSimulatorReady = false; // VR simulator ready flag +static bool vrStereoRender = false; // VR stereo rendering enabled/disabled flag // NOTE: This flag is useful to render data over stereo image (i.e. FPS) #if defined(GRAPHICS_API_OPENGL_ES2) @@ -380,7 +328,7 @@ static int blendMode = 0; // Track current blending mode // White texture useful for plain color polys (required by shader) static unsigned int whiteTexture; -// Default framebuffer size (required by Oculus device) +// Default framebuffer size static int screenWidth; // Default framebuffer width static int screenHeight; // Default framebuffer height @@ -397,7 +345,7 @@ static void UnloadDefaultShader(void); // Unload default 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(int eyesCount); // Draw default internal buffers vertex data +static void DrawDefaultBuffers(void); // Draw default internal buffers vertex data static void UnloadDefaultBuffers(void); // Unload default internal buffers vertex data from CPU and GPU // Configure stereo rendering (including distortion shader) with HMD device parameters @@ -407,26 +355,6 @@ static void SetStereoConfig(VrDeviceInfo info); static void SetStereoView(int eye, Matrix matProjection, Matrix matModelView); #endif -#if defined(RLGL_OCULUS_SUPPORT) -#if !defined(RLGL_STANDALONE) -static bool InitOculusDevice(void); // Initialize Oculus device (returns true if success) -static void CloseOculusDevice(void); // Close Oculus device -static void UpdateOculusTracking(Camera *camera); // Update Oculus head position-orientation tracking -static void BeginOculusDrawing(void); // Setup Oculus buffers for drawing -static void EndOculusDrawing(void); // Finish Oculus drawing and blit framebuffer to mirror -#endif - -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); @@ -1352,9 +1280,7 @@ void rlglDraw(void) // NOTE: Default buffers upload and draw UpdateDefaultBuffers(); - - if (vrEnabled && vrRendering) DrawDefaultBuffers(2); - else DrawDefaultBuffers(1); + DrawDefaultBuffers(); // NOTE: Stereo rendering is checked inside #endif } @@ -2018,9 +1944,6 @@ 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 @@ -2153,6 +2076,9 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) if (mesh.indices != NULL) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quads.vboId[3]); } + int eyesCount = 1; + if (vrStereoRender) eyesCount = 2; + for (int eye = 0; eye < eyesCount; eye++) { if (eyesCount == 2) SetStereoView(eye, matProjection, matModelView); @@ -2617,146 +2543,119 @@ void EndBlendMode(void) BeginBlendMode(BLEND_ALPHA); } -// Init VR device (or simulator) -// NOTE: If device is not available, it fallbacks to default device (simulator) +// Init VR simulator for selected device // NOTE: It modifies the global variable: VrDeviceInfo hmd -void InitVrDevice(int vrDevice) +void InitVrSimulator(int vrDevice) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - switch (vrDevice) + if (vrDevice == HMD_OCULUS_RIFT_DK2) { - case HMD_DEFAULT_DEVICE: TraceLog(INFO, "Initializing default VR Device (Oculus Rift CV1)"); - case HMD_OCULUS_RIFT_DK2: - case HMD_OCULUS_RIFT_CV1: - { -#if defined(RLGL_OCULUS_SUPPORT) - vrDeviceReady = InitOculusDevice(); -#else - TraceLog(WARNING, "Oculus Rift not supported by default, recompile raylib with Oculus support"); -#endif - } break; - case HMD_VALVE_HTC_VIVE: - case HMD_SAMSUNG_GEAR_VR: - case HMD_GOOGLE_CARDBOARD: - case HMD_SONY_PLAYSTATION_VR: - case HMD_RAZER_OSVR: - case HMD_FOVE_VR: TraceLog(WARNING, "VR Device not supported"); - default: break; + // Oculus Rift DK2 parameters + hmd.hResolution = 1280; // HMD horizontal resolution in pixels + hmd.vResolution = 800; // HMD vertical resolution in pixels + hmd.hScreenSize = 0.14976f; // HMD horizontal size in meters + hmd.vScreenSize = 0.09356f; // HMD vertical size in meters + hmd.vScreenCenter = 0.04678f; // HMD screen center in meters + hmd.eyeToScreenDistance = 0.041f; // HMD distance between eye and display in meters + hmd.lensSeparationDistance = 0.0635f; // HMD lens separation distance in meters + hmd.interpupillaryDistance = 0.064f; // HMD IPD (distance between pupils) in meters + hmd.distortionK[0] = 1.0f; // HMD lens distortion constant parameter 0 + hmd.distortionK[1] = 0.22f; // HMD lens distortion constant parameter 1 + hmd.distortionK[2] = 0.24f; // HMD lens distortion constant parameter 2 + hmd.distortionK[3] = 0.0f; // HMD lens distortion constant parameter 3 + hmd.chromaAbCorrection[0] = 0.996f; // HMD chromatic aberration correction parameter 0 + hmd.chromaAbCorrection[1] = -0.004f; // HMD chromatic aberration correction parameter 1 + hmd.chromaAbCorrection[2] = 1.014f; // HMD chromatic aberration correction parameter 2 + hmd.chromaAbCorrection[3] = 0.0f; // HMD chromatic aberration correction parameter 3 + + TraceLog(WARNING, "Initializing VR Simulator (Oculus Rift DK2)"); + } + else if ((vrDevice == HMD_DEFAULT_DEVICE) || (vrDevice == HMD_OCULUS_RIFT_CV1)) + { + // Oculus Rift CV1 parameters + // NOTE: CV1 represents a complete HMD redesign compared to previous versions, + // new Fresnel-hybrid-asymmetric lenses have been added and, consequently, + // previous parameters (DK2) and distortion shader (DK2) doesn't work any more. + // I just defined a set of parameters for simulator that approximate to CV1 stereo rendering + // but result is not the same obtained with Oculus PC SDK. + hmd.hResolution = 2160; // HMD horizontal resolution in pixels + hmd.vResolution = 1200; // HMD vertical resolution in pixels + hmd.hScreenSize = 0.133793f; // HMD horizontal size in meters + hmd.vScreenSize = 0.0669f; // HMD vertical size in meters + hmd.vScreenCenter = 0.04678f; // HMD screen center in meters + hmd.eyeToScreenDistance = 0.041f; // HMD distance between eye and display in meters + hmd.lensSeparationDistance = 0.07f; // HMD lens separation distance in meters + hmd.interpupillaryDistance = 0.07f; // HMD IPD (distance between pupils) in meters + hmd.distortionK[0] = 1.0f; // HMD lens distortion constant parameter 0 + hmd.distortionK[1] = 0.22f; // HMD lens distortion constant parameter 1 + hmd.distortionK[2] = 0.24f; // HMD lens distortion constant parameter 2 + hmd.distortionK[3] = 0.0f; // HMD lens distortion constant parameter 3 + hmd.chromaAbCorrection[0] = 0.996f; // HMD chromatic aberration correction parameter 0 + hmd.chromaAbCorrection[1] = -0.004f; // HMD chromatic aberration correction parameter 1 + hmd.chromaAbCorrection[2] = 1.014f; // HMD chromatic aberration correction parameter 2 + hmd.chromaAbCorrection[3] = 0.0f; // HMD chromatic aberration correction parameter 3 + + TraceLog(WARNING, "Initializing VR Simulator (Oculus Rift CV1)"); + } + else + { + TraceLog(WARNING, "VR Simulator doesn't support current device yet,"); + TraceLog(WARNING, "using default VR Simulator parameters"); } - if (!vrDeviceReady) - { - TraceLog(WARNING, "VR Device not found: Initializing VR Simulator (Oculus Rift CV1)"); + // Initialize framebuffer and textures for stereo rendering + // NOTE: screen size should match HMD aspect ratio + vrConfig.stereoFbo = rlglLoadRenderTexture(screenWidth, screenHeight); - if (vrDevice == HMD_OCULUS_RIFT_DK2) - { - // Oculus Rift DK2 parameters - hmd.hResolution = 1280; // HMD horizontal resolution in pixels - hmd.vResolution = 800; // HMD vertical resolution in pixels - hmd.hScreenSize = 0.14976f; // HMD horizontal size in meters - hmd.vScreenSize = 0.09356f; // HMD vertical size in meters - hmd.vScreenCenter = 0.04678f; // HMD screen center in meters - hmd.eyeToScreenDistance = 0.041f; // HMD distance between eye and display in meters - hmd.lensSeparationDistance = 0.0635f; // HMD lens separation distance in meters - hmd.interpupillaryDistance = 0.064f; // HMD IPD (distance between pupils) in meters - hmd.distortionK[0] = 1.0f; // HMD lens distortion constant parameter 0 - hmd.distortionK[1] = 0.22f; // HMD lens distortion constant parameter 1 - hmd.distortionK[2] = 0.24f; // HMD lens distortion constant parameter 2 - hmd.distortionK[3] = 0.0f; // HMD lens distortion constant parameter 3 - hmd.chromaAbCorrection[0] = 0.996f; // HMD chromatic aberration correction parameter 0 - hmd.chromaAbCorrection[1] = -0.004f; // HMD chromatic aberration correction parameter 1 - hmd.chromaAbCorrection[2] = 1.014f; // HMD chromatic aberration correction parameter 2 - hmd.chromaAbCorrection[3] = 0.0f; // HMD chromatic aberration correction parameter 3 - } - else if ((vrDevice == HMD_DEFAULT_DEVICE) || (vrDevice == HMD_OCULUS_RIFT_CV1)) - { - // Oculus Rift CV1 parameters - // NOTE: CV1 represents a complete HMD redesign compared to previous versions, - // new Fresnel-hybrid-asymmetric lenses have been added and, consequently, - // previous parameters (DK2) and distortion shader (DK2) doesn't work any more. - // I just defined a set of parameters for simulator that approximate to CV1 stereo rendering - // but result is not the same obtained with Oculus PC SDK. - hmd.hResolution = 2160; // HMD horizontal resolution in pixels - hmd.vResolution = 1200; // HMD vertical resolution in pixels - hmd.hScreenSize = 0.133793f; // HMD horizontal size in meters - hmd.vScreenSize = 0.0669f; // HMD vertical size in meters - hmd.vScreenCenter = 0.04678f; // HMD screen center in meters - hmd.eyeToScreenDistance = 0.041f; // HMD distance between eye and display in meters - hmd.lensSeparationDistance = 0.07f; // HMD lens separation distance in meters - hmd.interpupillaryDistance = 0.07f; // HMD IPD (distance between pupils) in meters - hmd.distortionK[0] = 1.0f; // HMD lens distortion constant parameter 0 - hmd.distortionK[1] = 0.22f; // HMD lens distortion constant parameter 1 - hmd.distortionK[2] = 0.24f; // HMD lens distortion constant parameter 2 - hmd.distortionK[3] = 0.0f; // HMD lens distortion constant parameter 3 - hmd.chromaAbCorrection[0] = 0.996f; // HMD chromatic aberration correction parameter 0 - hmd.chromaAbCorrection[1] = -0.004f; // HMD chromatic aberration correction parameter 1 - hmd.chromaAbCorrection[2] = 1.014f; // HMD chromatic aberration correction parameter 2 - hmd.chromaAbCorrection[3] = 0.0f; // HMD chromatic aberration correction parameter 3 - } + // Load distortion shader (initialized by default with Oculus Rift CV1 parameters) + vrConfig.distortionShader.id = LoadShaderProgram(vDistortionShaderStr, fDistortionShaderStr); + if (vrConfig.distortionShader.id != 0) LoadDefaultShaderLocations(&vrConfig.distortionShader); - // Initialize framebuffer and textures for stereo rendering - // NOTE: screen size should match HMD aspect ratio - vrConfig.stereoFbo = rlglLoadRenderTexture(screenWidth, screenHeight); + SetStereoConfig(hmd); - // Load distortion shader (initialized by default with Oculus Rift CV1 parameters) - vrConfig.distortionShader.id = LoadShaderProgram(vDistortionShaderStr, fDistortionShaderStr); - if (vrConfig.distortionShader.id != 0) LoadDefaultShaderLocations(&vrConfig.distortionShader); - - SetStereoConfig(hmd); - - vrSimulator = true; - vrEnabled = true; - } + vrSimulatorReady = true; #endif #if defined(GRAPHICS_API_OPENGL_11) - TraceLog(WARNING, "VR device or simulator not supported on OpenGL 1.1"); + TraceLog(WARNING, "VR Simulator not supported on OpenGL 1.1"); #endif } -// Close VR device (or simulator) -void CloseVrDevice(void) +// Close VR simulator for current device +void CloseVrSimulator(void) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) -#if defined(RLGL_OCULUS_SUPPORT) - if (vrDeviceReady) CloseOculusDevice(); - else -#endif + if (vrSimulatorReady) { rlDeleteRenderTextures(vrConfig.stereoFbo); // Unload stereo framebuffer and texture UnloadShader(vrConfig.distortionShader); // Unload distortion shader } #endif - vrDeviceReady = false; -} - -// Detect if VR device is available -bool IsVrDeviceReady(void) -{ - return (vrDeviceReady && vrEnabled); } // Detect if VR simulator is running -bool IsVrSimulator(void) +bool IsVrSimulatorReady(void) { - return (vrSimulator && vrEnabled); + return vrSimulatorReady; } // Enable/Disable VR experience (device or simulator) void ToggleVrMode(void) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - if (vrDeviceReady || vrSimulator) vrEnabled = !vrEnabled; - else vrEnabled = false; + vrSimulatorReady = !vrSimulatorReady; - if (!vrEnabled) + if (!vrSimulatorReady) { + vrStereoRender = false; + // Reset viewport and default projection-modelview matrices rlViewport(0, 0, screenWidth, screenHeight); projection = MatrixOrtho(0, screenWidth, screenHeight, 0, 0.0f, 1.0f); MatrixTranspose(&projection); modelview = MatrixIdentity(); } + else vrStereoRender = true; #endif } @@ -2764,37 +2663,29 @@ void ToggleVrMode(void) // NOTE: Camera (position, target, up) gets update with head tracking information void UpdateVrTracking(Camera *camera) { -#if defined(RLGL_OCULUS_SUPPORT) - if (vrDeviceReady) UpdateOculusTracking(camera); -#endif + // TODO: Simulate 1st person camera system } // Begin Oculus drawing configuration void BeginVrDrawing(void) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) -#if defined(RLGL_OCULUS_SUPPORT) - if (vrDeviceReady) - { - BeginOculusDrawing(); - } - else -#endif + if (vrSimulatorReady) { // Setup framebuffer for stereo rendering rlEnableRenderTexture(vrConfig.stereoFbo.id); + + // 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); + + //glViewport(0, 0, buffer.width, buffer.height); // Useful if rendering to separate framebuffers (every eye) + rlClearScreenBuffers(); // Clear current framebuffer(s) + + vrStereoRender = true; } - - // 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); - - //glViewport(0, 0, buffer.width, buffer.height); // Useful if rendering to separate framebuffers (every eye) - rlClearScreenBuffers(); // Clear current framebuffer(s) - - vrRendering = true; #endif } @@ -2802,18 +2693,13 @@ void BeginVrDrawing(void) void EndVrDrawing(void) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) -#if defined(RLGL_OCULUS_SUPPORT) - if (vrDeviceReady) + if (vrSimulatorReady) { - EndOculusDrawing(); - } - else -#endif - { - // Unbind current framebuffer - rlDisableRenderTexture(); + vrStereoRender = false; // Disable stereo render + + rlDisableRenderTexture(); // Unbind current framebuffer - rlClearScreenBuffers(); // Clear current framebuffer + rlClearScreenBuffers(); // Clear current framebuffer // Set viewport to default framebuffer size (screen size) rlViewport(0, 0, screenWidth, screenHeight); @@ -2855,15 +2741,21 @@ void EndVrDrawing(void) rlDisableTexture(); + // Update and draw render texture fbo with distortion to backbuffer UpdateDefaultBuffers(); - DrawDefaultBuffers(1); - + DrawDefaultBuffers(); + + // Restore defaultShader currentShader = defaultShader; + + // Reset viewport and default projection-modelview matrices + rlViewport(0, 0, screenWidth, screenHeight); + projection = MatrixOrtho(0, screenWidth, screenHeight, 0, 0.0f, 1.0f); + MatrixTranspose(&projection); + modelview = MatrixIdentity(); + + rlDisableDepthTest(); } - - rlDisableDepthTest(); - - vrRendering = false; #endif } @@ -3405,10 +3297,13 @@ static void UpdateDefaultBuffers(void) // Draw default internal buffers vertex data // NOTE: We draw in this order: lines, triangles, quads -static void DrawDefaultBuffers(int eyesCount) +static void DrawDefaultBuffers() { Matrix matProjection = projection; Matrix matModelView = modelview; + + int eyesCount = 1; + if (vrStereoRender) eyesCount = 2; for (int eye = 0; eye < eyesCount; eye++) { @@ -3693,47 +3588,19 @@ static void SetStereoConfig(VrDeviceInfo hmd) // Set internal projection and modelview matrix depending on eyes tracking data static void SetStereoView(int eye, Matrix matProjection, Matrix matModelView) { - if (vrEnabled) - { - Matrix eyeProjection = matProjection; - Matrix eyeModelView = matModelView; + Matrix eyeProjection = matProjection; + Matrix eyeModelView = matModelView; -#if defined(RLGL_OCULUS_SUPPORT) - if (vrDeviceReady) - { - 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); + // Setup viewport and projection/modelview matrices using tracking data + rlViewport(eye*screenWidth/2, 0, screenWidth/2, screenHeight); - Quaternion eyeRenderPose = (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(&eyeRenderPose); - Matrix eyeOrientation = QuaternionToMatrix(eyeRenderPose); - Matrix eyeTranslation = MatrixTranslate(-layer.eyeLayer.RenderPose[eye].Position.x, - -layer.eyeLayer.RenderPose[eye].Position.y, - -layer.eyeLayer.RenderPose[eye].Position.z); + // Apply view offset to modelview matrix + eyeModelView = MatrixMultiply(matModelView, vrConfig.eyesViewOffset[eye]); - Matrix eyeView = MatrixMultiply(eyeTranslation, eyeOrientation); // Matrix containing eye-head movement - eyeModelView = MatrixMultiply(matModelView, eyeView); // Combine internal camera matrix (modelview) wih eye-head movement + eyeProjection = vrConfig.eyesProjection[eye]; - eyeProjection = layer.eyeProjections[eye]; - } - else -#endif - { - // Setup viewport and projection/modelview matrices using tracking data - rlViewport(eye*screenWidth/2, 0, screenWidth/2, screenHeight); - - // Apply view offset to modelview matrix - eyeModelView = MatrixMultiply(matModelView, vrConfig.eyesViewOffset[eye]); - - eyeProjection = vrConfig.eyesProjection[eye]; - } - - SetMatrixModelview(eyeModelView); - SetMatrixProjection(eyeProjection); - } + SetMatrixModelview(eyeModelView); + SetMatrixProjection(eyeProjection); } #endif //defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) @@ -3864,304 +3731,6 @@ static Color *GenNextMipmap(Color *srcData, int srcWidth, int srcHeight) } #endif -#if defined(RLGL_OCULUS_SUPPORT) -// Initialize Oculus device (returns true if success) -OCULUSAPI bool InitOculusDevice(void) -{ - bool oculusReady = false; - - ovrResult result = ovr_Initialize(NULL); - - if (OVR_FAILURE(result)) TraceLog(WARNING, "OVR: Could not initialize Oculus device"); - else - { - result = ovr_Create(&session, &luid); - if (OVR_FAILURE(result)) - { - TraceLog(WARNING, "OVR: Could not create Oculus session"); - ovr_Shutdown(); - } - else - { - 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); - - oculusReady = true; - vrEnabled = true; - } - } - - return oculusReady; -} - -// Close Oculus device (and unload buffers) -OCULUSAPI 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 head position-orientation tracking -OCULUSAPI void UpdateOculusTracking(Camera *camera) -{ - 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]; - - // TODO: Update external camera with eyePoses data (position, orientation) - // NOTE: We can simplify to simple camera if we consider IPD and HMD device configuration again later - // it will be useful for the user to draw, lets say, billboards oriented to camera - - // 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); - //if (sessionStatus.HmdPresent) // HMD is present. - //if (sessionStatus.DisplayLost) // HMD was unplugged or the display driver was manually disabled or encountered a TDR. - //if (sessionStatus.HmdMounted) // HMD is on the user's head. - //if (sessionStatus.IsVisible) // the game or experience has VR focus and is visible in the HMD. -} - -// Setup Oculus buffers for drawing -OCULUSAPI 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 -} - -// Finish Oculus drawing and blit framebuffer to mirror -OCULUSAPI void EndOculusDrawing(void) -{ - // Unbind current framebuffer (Oculus buffer) - 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); -} - -// 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); -#if defined(GRAPHICS_API_OPENGL_33) - // NOTE: glBlitFramebuffer() requires extension: GL_EXT_framebuffer_blit (not available in OpenGL ES 2.0) - glBlitFramebuffer(0, 0, mirror.width, mirror.height, 0, mirror.height, mirror.width, 0, GL_COLOR_BUFFER_BIT, GL_NEAREST); -#endif - 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/raylib/rlgl.h b/raylib/rlgl.h index 41f671e..344da98 100644 --- a/raylib/rlgl.h +++ b/raylib/rlgl.h @@ -399,19 +399,12 @@ void EndBlendMode(void); // End blend void TraceLog(int msgType, const char *text, ...); float *MatrixToFloat(Matrix mat); -void InitVrDevice(int vrDevice); // Init VR device -void CloseVrDevice(void); // Close VR device -bool IsVrDeviceReady(void); // Detect if VR device is ready -bool IsVrSimulator(void); // Detect if VR simulator is running +void InitVrSimulator(int vrDevice); // Init VR simulator for selected device +void CloseVrSimulator(void); // Close VR simulator for current device void UpdateVrTracking(Camera *camera); // Update VR tracking (position and orientation) and camera void ToggleVrMode(void); // Enable/Disable VR experience (device or simulator) - -// Oculus Rift API for direct access the device (no simulator) -bool InitOculusDevice(void); // Initialize Oculus device (returns true if success) -void CloseOculusDevice(void); // Close Oculus device -void UpdateOculusTracking(Camera *camera); // Update Oculus head position-orientation tracking (and camera) -void BeginOculusDrawing(void); // Setup Oculus buffers for drawing -void EndOculusDrawing(void); // Finish Oculus drawing and blit framebuffer to mirror +void BeginVrDrawing(void); // Begin VR stereo rendering +void EndVrDrawing(void); // End VR stereo rendering #endif #ifdef __cplusplus diff --git a/raylib/shaders.go b/raylib/shaders.go index c4928e0..2ba6f6a 100644 --- a/raylib/shaders.go +++ b/raylib/shaders.go @@ -182,27 +182,20 @@ func EndBlendMode() { C.EndBlendMode() } -// InitVrDevice - Init VR device -func InitVrDevice(vdDevice VrDevice) { +// InitVrSimulator - Init VR simulator for selected device +func InitVrSimulator(vdDevice VrDevice) { cvdDevice := (C.int)(vdDevice) - C.InitVrDevice(cvdDevice) + C.InitVrSimulator(cvdDevice) } -// CloseVrDevice - Close VR device -func CloseVrDevice() { - C.CloseVrDevice() +// CloseVrSimulator - Close VR simulator for current device +func CloseVrSimulator() { + C.CloseVrSimulator() } -// IsVrDeviceReady - Detect if VR device is ready -func IsVrDeviceReady() bool { - ret := C.IsVrDeviceReady() - v := bool(int(ret) == 1) - return v -} - -// IsVrSimulator - Detect if VR simulator is running -func IsVrSimulator() bool { - ret := C.IsVrSimulator() +// IsVrSimulatorReady - Detect if VR simulator is ready +func IsVrSimulatorReady() bool { + ret := C.IsVrSimulatorReady() v := bool(int(ret) == 1) return v } @@ -217,3 +210,13 @@ func UpdateVrTracking(camera *Camera) { func ToggleVrMode() { C.ToggleVrMode() } + +// BeginVrDrawing - Begin VR simulator stereo rendering +func BeginVrDrawing() { + C.BeginVrDrawing() +} + +// EndVrDrawing - End VR simulator stereo rendering +func EndVrDrawing() { + C.EndVrDrawing() +} diff --git a/raylib/shapes.c b/raylib/shapes.c index 9cbe1da..5ed633f 100644 --- a/raylib/shapes.c +++ b/raylib/shapes.c @@ -57,7 +57,7 @@ //---------------------------------------------------------------------------------- // Module specific Functions Declaration //---------------------------------------------------------------------------------- -// No private (static) functions in this module (.c file) +static float EaseCubicInOut(float t, float b, float c, float d); // Cubic easing //---------------------------------------------------------------------------------- // Module Functions Definition @@ -106,6 +106,13 @@ void DrawLineV(Vector2 startPos, Vector2 endPos, Color color) // Draw a line defining thickness void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color) { + if (startPos.x > endPos.x) + { + Vector2 tempPos = startPos; + startPos = endPos; + endPos = tempPos; + } + float dx = endPos.x - startPos.x; float dy = endPos.y - startPos.y; @@ -133,6 +140,27 @@ void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color) rlDisableTexture(); } +// Draw line using cubic-bezier curves in-out +void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color) +{ + #define LINE_DIVISIONS 24 // Bezier line divisions + + Vector2 previous = startPos; + Vector2 current; + + for (int i = 1; i <= LINE_DIVISIONS; i++) + { + // Cubic easing in-out + // NOTE: Easing is calcutated only for y position value + current.y = EaseCubicInOut(i, startPos.y, endPos.y - startPos.y, LINE_DIVISIONS); + current.x = previous.x + (endPos.x - startPos.x)/LINE_DIVISIONS; + + DrawLineEx(previous, current, thick, color); + + previous = current; + } +} + // Draw a color-filled circle void DrawCircle(int centerX, int centerY, float radius, Color color) { @@ -590,3 +618,15 @@ Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2) return retRec; } + +//---------------------------------------------------------------------------------- +// Module specific Functions Definition +//---------------------------------------------------------------------------------- + +// Cubic easing in-out +// NOTE: Required for DrawLineBezier() +static float EaseCubicInOut(float t, float b, float c, float d) +{ + if ((t/=d/2) < 1) return (c/2*t*t*t + b); + return (c/2*((t-=2)*t*t + 2) + b); +} \ No newline at end of file diff --git a/raylib/shapes.go b/raylib/shapes.go index d7e3d41..07557dd 100644 --- a/raylib/shapes.go +++ b/raylib/shapes.go @@ -49,6 +49,15 @@ func DrawLineEx(startPos Vector2, endPos Vector2, thick float32, color Color) { C.DrawLineEx(*cstartPos, *cendPos, cthick, *ccolor) } +// DrawLineBezier - Draw a line using cubic-bezier curves in-out +func DrawLineBezier(startPos Vector2, endPos Vector2, thick float32, color Color) { + cstartPos := startPos.cptr() + cendPos := endPos.cptr() + cthick := (C.float)(thick) + ccolor := color.cptr() + C.DrawLineBezier(*cstartPos, *cendPos, cthick, *ccolor) +} + // DrawCircle - Draw a color-filled circle func DrawCircle(centerX int32, centerY int32, radius float32, color Color) { ccenterX := (C.int)(centerX) diff --git a/raylib/utils.go b/raylib/utils.go index 44136a4..c7e901d 100644 --- a/raylib/utils.go +++ b/raylib/utils.go @@ -22,7 +22,7 @@ func SetDebug(enabled bool) { traceDebugMsgs = enabled } -// TraceLog - Trace log +// TraceLog - Trace log messages showing (INFO, WARNING, ERROR, DEBUG) func TraceLog(msgType int, text string, v ...interface{}) { switch msgType { case LogInfo: diff --git a/raylib/utils_android.go b/raylib/utils_android.go index c4a4747..191a1f4 100644 --- a/raylib/utils_android.go +++ b/raylib/utils_android.go @@ -35,7 +35,7 @@ func SetDebug(enabled bool) { traceDebugMsgs = enabled } -// TraceLog - Trace log +// TraceLog - Trace log messages showing (INFO, WARNING, ERROR, DEBUG) func TraceLog(msgType int, text string, v ...interface{}) { switch msgType { case LogInfo: diff --git a/raylib/utils_windows.go b/raylib/utils_windows.go index ca91399..7374074 100644 --- a/raylib/utils_windows.go +++ b/raylib/utils_windows.go @@ -22,7 +22,7 @@ func SetDebug(enabled bool) { traceDebugMsgs = enabled } -// TraceLog - Trace log +// TraceLog - Trace log messages showing (INFO, WARNING, ERROR, DEBUG) func TraceLog(msgType int, text string, v ...interface{}) { switch msgType { case LogInfo: