From 47afda2549cdab0429047fcc64540a4ed5d0ede7 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Tue, 14 Jun 2016 11:55:32 +0200 Subject: [PATCH 01/11] 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(-) diff --git a/src/gestures.c b/src/gestures.c index 903716209..8e6005b3e 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 f2bdaba47..ab5287ccf 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 bfcb9bf56..343e86f1c 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 From 3d6be7fd8000bf7bd9da0b9ad8764021f86c0d01 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Tue, 14 Jun 2016 12:01:57 +0200 Subject: [PATCH 02/11] 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(-) diff --git a/src/gestures.c b/src/gestures.c index 8e6005b3e..57b96bd26 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 ab5287ccf..912d0b926 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 343e86f1c..9120ddc4b 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 From 3a5fc0c32042714efde93c72903d2cd89c4cff50 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Tue, 14 Jun 2016 12:12:02 +0200 Subject: [PATCH 03/11] Move global data to implementation --- src/raygui.h | 208 ++++++++++++++++++++++++++------------------------- 1 file changed, 107 insertions(+), 101 deletions(-) diff --git a/src/raygui.h b/src/raygui.h index 74f131d58..42cf264b2 100644 --- a/src/raygui.h +++ b/src/raygui.h @@ -242,106 +242,7 @@ typedef enum GuiProperty { //---------------------------------------------------------------------------------- // Global Variables Definition //---------------------------------------------------------------------------------- -static const char *guiPropertyName[] = { - "GLOBAL_BASE_COLOR", - "GLOBAL_BORDER_COLOR", - "GLOBAL_TEXT_COLOR", - "GLOBAL_TEXT_FONTSIZE", - "GLOBAL_BORDER_WIDTH", - "BACKGROUND_COLOR", - "LABEL_BORDER_WIDTH", - "LABEL_TEXT_COLOR", - "LABEL_TEXT_PADDING", - "BUTTON_BORDER_WIDTH", - "BUTTON_TEXT_PADDING", - "BUTTON_DEFAULT_BORDER_COLOR", - "BUTTON_DEFAULT_INSIDE_COLOR", - "BUTTON_DEFAULT_TEXT_COLOR", - "BUTTON_HOVER_BORDER_COLOR", - "BUTTON_HOVER_INSIDE_COLOR", - "BUTTON_HOVER_TEXT_COLOR", - "BUTTON_PRESSED_BORDER_COLOR", - "BUTTON_PRESSED_INSIDE_COLOR", - "BUTTON_PRESSED_TEXT_COLOR", - "TOGGLE_TEXT_PADDING", - "TOGGLE_BORDER_WIDTH", - "TOGGLE_DEFAULT_BORDER_COLOR", - "TOGGLE_DEFAULT_INSIDE_COLOR", - "TOGGLE_DEFAULT_TEXT_COLOR", - "TOGGLE_HOVER_BORDER_COLOR", - "TOGGLE_HOVER_INSIDE_COLOR", - "TOGGLE_HOVER_TEXT_COLOR", - "TOGGLE_PRESSED_BORDER_COLOR", - "TOGGLE_PRESSED_INSIDE_COLOR", - "TOGGLE_PRESSED_TEXT_COLOR", - "TOGGLE_ACTIVE_BORDER_COLOR", - "TOGGLE_ACTIVE_INSIDE_COLOR", - "TOGGLE_ACTIVE_TEXT_COLOR", - "TOGGLEGROUP_PADDING", - "SLIDER_BORDER_WIDTH", - "SLIDER_BUTTON_BORDER_WIDTH", - "SLIDER_BORDER_COLOR", - "SLIDER_INSIDE_COLOR", - "SLIDER_DEFAULT_COLOR", - "SLIDER_HOVER_COLOR", - "SLIDER_ACTIVE_COLOR", - "SLIDERBAR_BORDER_COLOR", - "SLIDERBAR_INSIDE_COLOR", - "SLIDERBAR_DEFAULT_COLOR", - "SLIDERBAR_HOVER_COLOR", - "SLIDERBAR_ACTIVE_COLOR", - "SLIDERBAR_ZERO_LINE_COLOR", - "PROGRESSBAR_BORDER_COLOR", - "PROGRESSBAR_INSIDE_COLOR", - "PROGRESSBAR_PROGRESS_COLOR", - "PROGRESSBAR_BORDER_WIDTH", - "SPINNER_LABEL_BORDER_COLOR", - "SPINNER_LABEL_INSIDE_COLOR", - "SPINNER_DEFAULT_BUTTON_BORDER_COLOR", - "SPINNER_DEFAULT_BUTTON_INSIDE_COLOR", - "SPINNER_DEFAULT_SYMBOL_COLOR", - "SPINNER_DEFAULT_TEXT_COLOR", - "SPINNER_HOVER_BUTTON_BORDER_COLOR", - "SPINNER_HOVER_BUTTON_INSIDE_COLOR", - "SPINNER_HOVER_SYMBOL_COLOR", - "SPINNER_HOVER_TEXT_COLOR", - "SPINNER_PRESSED_BUTTON_BORDER_COLOR", - "SPINNER_PRESSED_BUTTON_INSIDE_COLOR", - "SPINNER_PRESSED_SYMBOL_COLOR", - "SPINNER_PRESSED_TEXT_COLOR", - "COMBOBOX_PADDING", - "COMBOBOX_BUTTON_WIDTH", - "COMBOBOX_BUTTON_HEIGHT", - "COMBOBOX_BORDER_WIDTH", - "COMBOBOX_DEFAULT_BORDER_COLOR", - "COMBOBOX_DEFAULT_INSIDE_COLOR", - "COMBOBOX_DEFAULT_TEXT_COLOR", - "COMBOBOX_DEFAULT_LIST_TEXT_COLOR", - "COMBOBOX_HOVER_BORDER_COLOR", - "COMBOBOX_HOVER_INSIDE_COLOR", - "COMBOBOX_HOVER_TEXT_COLOR", - "COMBOBOX_HOVER_LIST_TEXT_COLOR", - "COMBOBOX_PRESSED_BORDER_COLOR", - "COMBOBOX_PRESSED_INSIDE_COLOR", - "COMBOBOX_PRESSED_TEXT_COLOR", - "COMBOBOX_PRESSED_LIST_BORDER_COLOR", - "COMBOBOX_PRESSED_LIST_INSIDE_COLOR", - "COMBOBOX_PRESSED_LIST_TEXT_COLOR", - "CHECKBOX_DEFAULT_BORDER_COLOR", - "CHECKBOX_DEFAULT_INSIDE_COLOR", - "CHECKBOX_HOVER_BORDER_COLOR", - "CHECKBOX_HOVER_INSIDE_COLOR", - "CHECKBOX_CLICK_BORDER_COLOR", - "CHECKBOX_CLICK_INSIDE_COLOR", - "CHECKBOX_STATUS_ACTIVE_COLOR", - "CHECKBOX_INSIDE_WIDTH", - "TEXTBOX_BORDER_WIDTH", - "TEXTBOX_BORDER_COLOR", - "TEXTBOX_INSIDE_COLOR", - "TEXTBOX_TEXT_COLOR", - "TEXTBOX_LINE_COLOR", - "TEXTBOX_TEXT_FONTSIZE" -}; +// ... //---------------------------------------------------------------------------------- // Module Functions Declaration @@ -517,6 +418,108 @@ static int style[NUM_PROPERTIES] = { 10 // TEXTBOX_TEXT_FONTSIZE }; +// GUI property names (to read/write style text files) +static const char *guiPropertyName[] = { + "GLOBAL_BASE_COLOR", + "GLOBAL_BORDER_COLOR", + "GLOBAL_TEXT_COLOR", + "GLOBAL_TEXT_FONTSIZE", + "GLOBAL_BORDER_WIDTH", + "BACKGROUND_COLOR", + "LABEL_BORDER_WIDTH", + "LABEL_TEXT_COLOR", + "LABEL_TEXT_PADDING", + "BUTTON_BORDER_WIDTH", + "BUTTON_TEXT_PADDING", + "BUTTON_DEFAULT_BORDER_COLOR", + "BUTTON_DEFAULT_INSIDE_COLOR", + "BUTTON_DEFAULT_TEXT_COLOR", + "BUTTON_HOVER_BORDER_COLOR", + "BUTTON_HOVER_INSIDE_COLOR", + "BUTTON_HOVER_TEXT_COLOR", + "BUTTON_PRESSED_BORDER_COLOR", + "BUTTON_PRESSED_INSIDE_COLOR", + "BUTTON_PRESSED_TEXT_COLOR", + "TOGGLE_TEXT_PADDING", + "TOGGLE_BORDER_WIDTH", + "TOGGLE_DEFAULT_BORDER_COLOR", + "TOGGLE_DEFAULT_INSIDE_COLOR", + "TOGGLE_DEFAULT_TEXT_COLOR", + "TOGGLE_HOVER_BORDER_COLOR", + "TOGGLE_HOVER_INSIDE_COLOR", + "TOGGLE_HOVER_TEXT_COLOR", + "TOGGLE_PRESSED_BORDER_COLOR", + "TOGGLE_PRESSED_INSIDE_COLOR", + "TOGGLE_PRESSED_TEXT_COLOR", + "TOGGLE_ACTIVE_BORDER_COLOR", + "TOGGLE_ACTIVE_INSIDE_COLOR", + "TOGGLE_ACTIVE_TEXT_COLOR", + "TOGGLEGROUP_PADDING", + "SLIDER_BORDER_WIDTH", + "SLIDER_BUTTON_BORDER_WIDTH", + "SLIDER_BORDER_COLOR", + "SLIDER_INSIDE_COLOR", + "SLIDER_DEFAULT_COLOR", + "SLIDER_HOVER_COLOR", + "SLIDER_ACTIVE_COLOR", + "SLIDERBAR_BORDER_COLOR", + "SLIDERBAR_INSIDE_COLOR", + "SLIDERBAR_DEFAULT_COLOR", + "SLIDERBAR_HOVER_COLOR", + "SLIDERBAR_ACTIVE_COLOR", + "SLIDERBAR_ZERO_LINE_COLOR", + "PROGRESSBAR_BORDER_COLOR", + "PROGRESSBAR_INSIDE_COLOR", + "PROGRESSBAR_PROGRESS_COLOR", + "PROGRESSBAR_BORDER_WIDTH", + "SPINNER_LABEL_BORDER_COLOR", + "SPINNER_LABEL_INSIDE_COLOR", + "SPINNER_DEFAULT_BUTTON_BORDER_COLOR", + "SPINNER_DEFAULT_BUTTON_INSIDE_COLOR", + "SPINNER_DEFAULT_SYMBOL_COLOR", + "SPINNER_DEFAULT_TEXT_COLOR", + "SPINNER_HOVER_BUTTON_BORDER_COLOR", + "SPINNER_HOVER_BUTTON_INSIDE_COLOR", + "SPINNER_HOVER_SYMBOL_COLOR", + "SPINNER_HOVER_TEXT_COLOR", + "SPINNER_PRESSED_BUTTON_BORDER_COLOR", + "SPINNER_PRESSED_BUTTON_INSIDE_COLOR", + "SPINNER_PRESSED_SYMBOL_COLOR", + "SPINNER_PRESSED_TEXT_COLOR", + "COMBOBOX_PADDING", + "COMBOBOX_BUTTON_WIDTH", + "COMBOBOX_BUTTON_HEIGHT", + "COMBOBOX_BORDER_WIDTH", + "COMBOBOX_DEFAULT_BORDER_COLOR", + "COMBOBOX_DEFAULT_INSIDE_COLOR", + "COMBOBOX_DEFAULT_TEXT_COLOR", + "COMBOBOX_DEFAULT_LIST_TEXT_COLOR", + "COMBOBOX_HOVER_BORDER_COLOR", + "COMBOBOX_HOVER_INSIDE_COLOR", + "COMBOBOX_HOVER_TEXT_COLOR", + "COMBOBOX_HOVER_LIST_TEXT_COLOR", + "COMBOBOX_PRESSED_BORDER_COLOR", + "COMBOBOX_PRESSED_INSIDE_COLOR", + "COMBOBOX_PRESSED_TEXT_COLOR", + "COMBOBOX_PRESSED_LIST_BORDER_COLOR", + "COMBOBOX_PRESSED_LIST_INSIDE_COLOR", + "COMBOBOX_PRESSED_LIST_TEXT_COLOR", + "CHECKBOX_DEFAULT_BORDER_COLOR", + "CHECKBOX_DEFAULT_INSIDE_COLOR", + "CHECKBOX_HOVER_BORDER_COLOR", + "CHECKBOX_HOVER_INSIDE_COLOR", + "CHECKBOX_CLICK_BORDER_COLOR", + "CHECKBOX_CLICK_INSIDE_COLOR", + "CHECKBOX_STATUS_ACTIVE_COLOR", + "CHECKBOX_INSIDE_WIDTH", + "TEXTBOX_BORDER_WIDTH", + "TEXTBOX_BORDER_COLOR", + "TEXTBOX_INSIDE_COLOR", + "TEXTBOX_TEXT_COLOR", + "TEXTBOX_LINE_COLOR", + "TEXTBOX_TEXT_FONTSIZE" +}; + //---------------------------------------------------------------------------------- // Module specific Functions Declaration //---------------------------------------------------------------------------------- @@ -529,7 +532,9 @@ static bool CheckCollisionPointRec(Vector2 point, Rectangle rec); // Check if p static const char *FormatText(const char *text, ...); // Formatting of text with variables to 'embed' // NOTE: raygui depend on some raylib input and drawing functions -// TODO: Replace by your own functions +// TODO: To use raygui as standalone library, those functions must be overwrite by custom ones + +// Input management functions static Vector2 GetMousePosition() { return (Vector2){ 0.0f, 0.0f }; } static int IsMouseButtonDown(int button) { return 0; } static int IsMouseButtonPressed(int button) { return 0; } @@ -539,6 +544,7 @@ static int IsMouseButtonUp(int button) { return 0; } static int GetKeyPressed(void) { return 0; } // NOTE: Only used by GuiTextBox() static int IsKeyDown(int key) { return 0; } // NOTE: Only used by GuiSpinner() +// Drawing related functions static int MeasureText(const char *text, int fontSize) { return 0; } static void DrawText(const char *text, int posX, int posY, int fontSize, Color color) { } static void DrawRectangleRec(Rectangle rec, Color color) { } From c25b4cdc69999c851594f7644ce89556be039c70 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Tue, 14 Jun 2016 15:42:04 +0200 Subject: [PATCH 04/11] Move OpenGL extensions loading to rlgl --- src/core.c | 20 +++----------------- src/rlgl.c | 21 ++++++++++++++++++++- src/rlgl.h | 3 ++- 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/src/core.c b/src/core.c index 122453e35..bd49b5494 100644 --- a/src/core.c +++ b/src/core.c @@ -58,10 +58,6 @@ #define PLATFORM_DESKTOP // Enable PLATFORM_DESKTOP code-base #endif -#if defined(PLATFORM_DESKTOP) - #include "external/glad.h" // GLAD library: Manage OpenGL headers and extensions -#endif - #if defined(PLATFORM_OCULUS) #include "../examples/oculus_glfw_sample/OculusSDK/LibOVR/Include/OVR_CAPI_GL.h" // Oculus SDK for OpenGL #endif @@ -1747,19 +1743,9 @@ static void InitDisplay(int width, int height) #endif #if defined(PLATFORM_DESKTOP) - // Load OpenGL 3.3 extensions using GLAD - if (rlGetVersion() == OPENGL_33) - { - // NOTE: glad is generated and contains only required OpenGL 3.3 Core extensions - if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) TraceLog(WARNING, "GLAD: Cannot load OpenGL extensions"); - else TraceLog(INFO, "GLAD: OpenGL extensions loaded successfully"); - - if (GLAD_GL_VERSION_3_3) TraceLog(INFO, "OpenGL 3.3 Core profile supported"); - else TraceLog(ERROR, "OpenGL 3.3 Core profile not supported"); - - // 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 - } + // Load OpenGL 3.3 extensions + // NOTE: GLFW loader function is passed as parameter + rlglLoadExtensions(glfwGetProcAddress); #endif // Enables GPU v-sync, so frames are not limited to screen refresh rate (60Hz -> 60 FPS) diff --git a/src/rlgl.c b/src/rlgl.c index e69ff983d..26961ca9e 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -872,6 +872,23 @@ 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 //---------------------------------------------------------------------------------- @@ -1184,11 +1201,13 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int textureForma GLuint id = 0; // Check texture format support by OpenGL 1.1 (compressed textures not supported) - if ((rlGetVersion() == OPENGL_11) && (textureFormat >= 8)) +#if defined(GRAPHICS_API_OPENGL_11) + if (textureFormat >= 8) { TraceLog(WARNING, "OpenGL 1.1 does not support GPU compressed texture formats"); return id; } +#endif if ((!texCompDXTSupported) && ((textureFormat == COMPRESSED_DXT1_RGB) || (textureFormat == COMPRESSED_DXT1_RGBA) || (textureFormat == COMPRESSED_DXT3_RGBA) || (textureFormat == COMPRESSED_DXT5_RGBA))) diff --git a/src/rlgl.h b/src/rlgl.h index 9c25f7104..28c50b8f2 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -48,7 +48,7 @@ // Choose opengl version here or just define it at compile time: -DGRAPHICS_API_OPENGL_33 //#define GRAPHICS_API_OPENGL_11 // Only available on PLATFORM_DESKTOP -//#define GRAPHICS_API_OPENGL_33 // Only available on PLATFORM_DESKTOP +//#define GRAPHICS_API_OPENGL_33 // Only available on PLATFORM_DESKTOP or PLATFORM_OCULUS //#define GRAPHICS_API_OPENGL_ES2 // Only available on PLATFORM_ANDROID or PLATFORM_RPI or PLATFORM_WEB // Security check in case no GRAPHICS_API_OPENGL_* defined @@ -296,6 +296,7 @@ void rlglInit(void); // Initialize rlgl (shaders, VAO void rlglClose(void); // De-init rlgl void rlglDraw(void); // Draw VAO/VBO void rlglInitGraphics(int offsetX, int offsetY, int width, int height); // Initialize Graphics (OpenGL stuff) +void rlglLoadExtensions(void *loader); // Load OpenGL extensions 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) From 0d0f306fc2f6bed7526df2044263698753811d0a Mon Sep 17 00:00:00 2001 From: raysan5 Date: Tue, 14 Jun 2016 17:15:00 +0200 Subject: [PATCH 05/11] Add Oculus SDK LibOVR library to external deps. --- .../LibOVR/Include/Extras/OVR_CAPI_Util.h | 196 + .../LibOVR/Include/Extras/OVR_Math.h | 3785 +++++++++++++++++ .../Include/Extras/OVR_StereoProjection.h | 70 + .../OculusSDK/LibOVR/Include/OVR_CAPI.h | 2116 +++++++++ .../OculusSDK/LibOVR/Include/OVR_CAPI_Audio.h | 76 + .../OculusSDK/LibOVR/Include/OVR_CAPI_D3D.h | 155 + .../OculusSDK/LibOVR/Include/OVR_CAPI_GL.h | 99 + .../OculusSDK/LibOVR/Include/OVR_CAPI_Keys.h | 53 + .../OculusSDK/LibOVR/Include/OVR_ErrorCode.h | 209 + .../OculusSDK/LibOVR/Include/OVR_Version.h | 60 + 10 files changed, 6819 insertions(+) create mode 100644 src/external/OculusSDK/LibOVR/Include/Extras/OVR_CAPI_Util.h create mode 100644 src/external/OculusSDK/LibOVR/Include/Extras/OVR_Math.h create mode 100644 src/external/OculusSDK/LibOVR/Include/Extras/OVR_StereoProjection.h create mode 100644 src/external/OculusSDK/LibOVR/Include/OVR_CAPI.h create mode 100644 src/external/OculusSDK/LibOVR/Include/OVR_CAPI_Audio.h create mode 100644 src/external/OculusSDK/LibOVR/Include/OVR_CAPI_D3D.h create mode 100644 src/external/OculusSDK/LibOVR/Include/OVR_CAPI_GL.h create mode 100644 src/external/OculusSDK/LibOVR/Include/OVR_CAPI_Keys.h create mode 100644 src/external/OculusSDK/LibOVR/Include/OVR_ErrorCode.h create mode 100644 src/external/OculusSDK/LibOVR/Include/OVR_Version.h diff --git a/src/external/OculusSDK/LibOVR/Include/Extras/OVR_CAPI_Util.h b/src/external/OculusSDK/LibOVR/Include/Extras/OVR_CAPI_Util.h new file mode 100644 index 000000000..552f3b125 --- /dev/null +++ b/src/external/OculusSDK/LibOVR/Include/Extras/OVR_CAPI_Util.h @@ -0,0 +1,196 @@ +/********************************************************************************//** +\file OVR_CAPI_Util.h +\brief This header provides LibOVR utility function declarations +\copyright Copyright 2015-2016 Oculus VR, LLC All Rights reserved. +*************************************************************************************/ + +#ifndef OVR_CAPI_Util_h +#define OVR_CAPI_Util_h + + +#include "../OVR_CAPI.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/// Enumerates modifications to the projection matrix based on the application's needs. +/// +/// \see ovrMatrix4f_Projection +/// +typedef enum ovrProjectionModifier_ +{ + /// Use for generating a default projection matrix that is: + /// * Right-handed. + /// * Near depth values stored in the depth buffer are smaller than far depth values. + /// * Both near and far are explicitly defined. + /// * With a clipping range that is (0 to w). + ovrProjection_None = 0x00, + + /// Enable if using left-handed transformations in your application. + ovrProjection_LeftHanded = 0x01, + + /// After the projection transform is applied, far values stored in the depth buffer will be less than closer depth values. + /// NOTE: Enable only if the application is using a floating-point depth buffer for proper precision. + ovrProjection_FarLessThanNear = 0x02, + + /// When this flag is used, the zfar value pushed into ovrMatrix4f_Projection() will be ignored + /// NOTE: Enable only if ovrProjection_FarLessThanNear is also enabled where the far clipping plane will be pushed to infinity. + ovrProjection_FarClipAtInfinity = 0x04, + + /// Enable if the application is rendering with OpenGL and expects a projection matrix with a clipping range of (-w to w). + /// Ignore this flag if your application already handles the conversion from D3D range (0 to w) to OpenGL. + ovrProjection_ClipRangeOpenGL = 0x08, +} ovrProjectionModifier; + + +/// Return values for ovr_Detect. +/// +/// \see ovr_Detect +/// +typedef struct OVR_ALIGNAS(8) ovrDetectResult_ +{ + /// Is ovrFalse when the Oculus Service is not running. + /// This means that the Oculus Service is either uninstalled or stopped. + /// IsOculusHMDConnected will be ovrFalse in this case. + /// Is ovrTrue when the Oculus Service is running. + /// This means that the Oculus Service is installed and running. + /// IsOculusHMDConnected will reflect the state of the HMD. + ovrBool IsOculusServiceRunning; + + /// Is ovrFalse when an Oculus HMD is not detected. + /// If the Oculus Service is not running, this will be ovrFalse. + /// Is ovrTrue when an Oculus HMD is detected. + /// This implies that the Oculus Service is also installed and running. + ovrBool IsOculusHMDConnected; + + OVR_UNUSED_STRUCT_PAD(pad0, 6) ///< \internal struct padding + +} ovrDetectResult; + +OVR_STATIC_ASSERT(sizeof(ovrDetectResult) == 8, "ovrDetectResult size mismatch"); + + +/// Detects Oculus Runtime and Device Status +/// +/// Checks for Oculus Runtime and Oculus HMD device status without loading the LibOVRRT +/// shared library. This may be called before ovr_Initialize() to help decide whether or +/// not to initialize LibOVR. +/// +/// \param[in] timeoutMilliseconds Specifies a timeout to wait for HMD to be attached or 0 to poll. +/// +/// \return Returns an ovrDetectResult object indicating the result of detection. +/// +/// \see ovrDetectResult +/// +OVR_PUBLIC_FUNCTION(ovrDetectResult) ovr_Detect(int timeoutMilliseconds); + +// On the Windows platform, +#ifdef _WIN32 + /// This is the Windows Named Event name that is used to check for HMD connected state. + #define OVR_HMD_CONNECTED_EVENT_NAME L"OculusHMDConnected" +#endif // _WIN32 + + +/// Used to generate projection from ovrEyeDesc::Fov. +/// +/// \param[in] fov Specifies the ovrFovPort to use. +/// \param[in] znear Distance to near Z limit. +/// \param[in] zfar Distance to far Z limit. +/// \param[in] projectionModFlags A combination of the ovrProjectionModifier flags. +/// +/// \return Returns the calculated projection matrix. +/// +/// \see ovrProjectionModifier +/// +OVR_PUBLIC_FUNCTION(ovrMatrix4f) ovrMatrix4f_Projection(ovrFovPort fov, float znear, float zfar, unsigned int projectionModFlags); + + +/// Extracts the required data from the result of ovrMatrix4f_Projection. +/// +/// \param[in] projection Specifies the project matrix from which to extract ovrTimewarpProjectionDesc. +/// \param[in] projectionModFlags A combination of the ovrProjectionModifier flags. +/// \return Returns the extracted ovrTimewarpProjectionDesc. +/// \see ovrTimewarpProjectionDesc +/// +OVR_PUBLIC_FUNCTION(ovrTimewarpProjectionDesc) ovrTimewarpProjectionDesc_FromProjection(ovrMatrix4f projection, unsigned int projectionModFlags); + + +/// Generates an orthographic sub-projection. +/// +/// Used for 2D rendering, Y is down. +/// +/// \param[in] projection The perspective matrix that the orthographic matrix is derived from. +/// \param[in] orthoScale Equal to 1.0f / pixelsPerTanAngleAtCenter. +/// \param[in] orthoDistance Equal to the distance from the camera in meters, such as 0.8m. +/// \param[in] HmdToEyeOffsetX Specifies the offset of the eye from the center. +/// +/// \return Returns the calculated projection matrix. +/// +OVR_PUBLIC_FUNCTION(ovrMatrix4f) ovrMatrix4f_OrthoSubProjection(ovrMatrix4f projection, ovrVector2f orthoScale, + float orthoDistance, float HmdToEyeOffsetX); + + + +/// Computes offset eye poses based on headPose returned by ovrTrackingState. +/// +/// \param[in] headPose Indicates the HMD position and orientation to use for the calculation. +/// \param[in] hmdToEyeOffset Can be ovrEyeRenderDesc.HmdToEyeOffset returned from +/// ovr_GetRenderDesc. For monoscopic rendering, use a vector that is the average +/// of the two vectors for both eyes. +/// \param[out] outEyePoses If outEyePoses are used for rendering, they should be passed to +/// ovr_SubmitFrame in ovrLayerEyeFov::RenderPose or ovrLayerEyeFovDepth::RenderPose. +/// +OVR_PUBLIC_FUNCTION(void) ovr_CalcEyePoses(ovrPosef headPose, + const ovrVector3f hmdToEyeOffset[2], + ovrPosef outEyePoses[2]); + + +/// Returns the predicted head pose in outHmdTrackingState and offset eye poses in outEyePoses. +/// +/// This is a thread-safe function where caller should increment frameIndex with every frame +/// and pass that index where applicable to functions called on the rendering thread. +/// Assuming outEyePoses are used for rendering, it should be passed as a part of ovrLayerEyeFov. +/// The caller does not need to worry about applying HmdToEyeOffset to the returned outEyePoses variables. +/// +/// \param[in] hmd Specifies an ovrSession previously returned by ovr_Create. +/// \param[in] frameIndex Specifies the targeted frame index, or 0 to refer to one frame after +/// the last time ovr_SubmitFrame was called. +/// \param[in] latencyMarker Specifies that this call is the point in time where +/// the "App-to-Mid-Photon" latency timer starts from. If a given ovrLayer +/// provides "SensorSampleTimestamp", that will override the value stored here. +/// \param[in] hmdToEyeOffset Can be ovrEyeRenderDesc.HmdToEyeOffset returned from +/// ovr_GetRenderDesc. For monoscopic rendering, use a vector that is the average +/// of the two vectors for both eyes. +/// \param[out] outEyePoses The predicted eye poses. +/// \param[out] outSensorSampleTime The time when this function was called. May be NULL, in which case it is ignored. +/// +OVR_PUBLIC_FUNCTION(void) ovr_GetEyePoses(ovrSession session, long long frameIndex, ovrBool latencyMarker, + const ovrVector3f hmdToEyeOffset[2], + ovrPosef outEyePoses[2], + double* outSensorSampleTime); + + + +/// Tracking poses provided by the SDK come in a right-handed coordinate system. If an application +/// is passing in ovrProjection_LeftHanded into ovrMatrix4f_Projection, then it should also use +/// this function to flip the HMD tracking poses to be left-handed. +/// +/// While this utility function is intended to convert a left-handed ovrPosef into a right-handed +/// coordinate system, it will also work for converting right-handed to left-handed since the +/// flip operation is the same for both cases. +/// +/// \param[in] inPose that is right-handed +/// \param[out] outPose that is requested to be left-handed (can be the same pointer to inPose) +/// +OVR_PUBLIC_FUNCTION(void) ovrPosef_FlipHandedness(const ovrPosef* inPose, ovrPosef* outPose); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif // Header include guard diff --git a/src/external/OculusSDK/LibOVR/Include/Extras/OVR_Math.h b/src/external/OculusSDK/LibOVR/Include/Extras/OVR_Math.h new file mode 100644 index 000000000..c182ed5b4 --- /dev/null +++ b/src/external/OculusSDK/LibOVR/Include/Extras/OVR_Math.h @@ -0,0 +1,3785 @@ +/********************************************************************************//** +\file OVR_Math.h +\brief Implementation of 3D primitives such as vectors, matrices. +\copyright Copyright 2014-2016 Oculus VR, LLC All Rights reserved. +*************************************************************************************/ + +#ifndef OVR_Math_h +#define OVR_Math_h + + +// This file is intended to be independent of the rest of LibOVR and LibOVRKernel and thus +// has no #include dependencies on either. + +#include +#include +#include +#include +#include +#include +#include "../OVR_CAPI.h" // Currently required due to a dependence on the ovrFovPort_ declaration. + +#if defined(_MSC_VER) + #pragma warning(push) + #pragma warning(disable: 4127) // conditional expression is constant +#endif + + +#if defined(_MSC_VER) + #define OVRMath_sprintf sprintf_s +#else + #define OVRMath_sprintf snprintf +#endif + + +//------------------------------------------------------------------------------------- +// ***** OVR_MATH_ASSERT +// +// Independent debug break implementation for OVR_Math.h. + +#if !defined(OVR_MATH_DEBUG_BREAK) + #if defined(_DEBUG) + #if defined(_MSC_VER) + #define OVR_MATH_DEBUG_BREAK __debugbreak() + #else + #define OVR_MATH_DEBUG_BREAK __builtin_trap() + #endif + #else + #define OVR_MATH_DEBUG_BREAK ((void)0) + #endif +#endif + + +//------------------------------------------------------------------------------------- +// ***** OVR_MATH_ASSERT +// +// Independent OVR_MATH_ASSERT implementation for OVR_Math.h. + +#if !defined(OVR_MATH_ASSERT) + #if defined(_DEBUG) + #define OVR_MATH_ASSERT(p) if (!(p)) { OVR_MATH_DEBUG_BREAK; } + #else + #define OVR_MATH_ASSERT(p) ((void)0) + #endif +#endif + + +//------------------------------------------------------------------------------------- +// ***** OVR_MATH_STATIC_ASSERT +// +// Independent OVR_MATH_ASSERT implementation for OVR_Math.h. + +#if !defined(OVR_MATH_STATIC_ASSERT) + #if defined(__cplusplus) && ((defined(_MSC_VER) && (defined(_MSC_VER) >= 1600)) || defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L)) + #define OVR_MATH_STATIC_ASSERT static_assert + #else + #if !defined(OVR_SA_UNUSED) + #if defined(__GNUC__) || defined(__clang__) + #define OVR_SA_UNUSED __attribute__((unused)) + #else + #define OVR_SA_UNUSED + #endif + #define OVR_SA_PASTE(a,b) a##b + #define OVR_SA_HELP(a,b) OVR_SA_PASTE(a,b) + #endif + + #define OVR_MATH_STATIC_ASSERT(expression, msg) typedef char OVR_SA_HELP(compileTimeAssert, __LINE__) [((expression) != 0) ? 1 : -1] OVR_SA_UNUSED + #endif +#endif + + + +namespace OVR { + +template +const T OVRMath_Min(const T a, const T b) +{ return (a < b) ? a : b; } + +template +const T OVRMath_Max(const T a, const T b) +{ return (b < a) ? a : b; } + +template +void OVRMath_Swap(T& a, T& b) +{ T temp(a); a = b; b = temp; } + + +//------------------------------------------------------------------------------------- +// ***** Constants for 3D world/axis definitions. + +// Definitions of axes for coordinate and rotation conversions. +enum Axis +{ + Axis_X = 0, Axis_Y = 1, Axis_Z = 2 +}; + +// RotateDirection describes the rotation direction around an axis, interpreted as follows: +// CW - Clockwise while looking "down" from positive axis towards the origin. +// CCW - Counter-clockwise while looking from the positive axis towards the origin, +// which is in the negative axis direction. +// CCW is the default for the RHS coordinate system. Oculus standard RHS coordinate +// system defines Y up, X right, and Z back (pointing out from the screen). In this +// system Rotate_CCW around Z will specifies counter-clockwise rotation in XY plane. +enum RotateDirection +{ + Rotate_CCW = 1, + Rotate_CW = -1 +}; + +// Constants for right handed and left handed coordinate systems +enum HandedSystem +{ + Handed_R = 1, Handed_L = -1 +}; + +// AxisDirection describes which way the coordinate axis points. Used by WorldAxes. +enum AxisDirection +{ + Axis_Up = 2, + Axis_Down = -2, + Axis_Right = 1, + Axis_Left = -1, + Axis_In = 3, + Axis_Out = -3 +}; + +struct WorldAxes +{ + AxisDirection XAxis, YAxis, ZAxis; + + WorldAxes(AxisDirection x, AxisDirection y, AxisDirection z) + : XAxis(x), YAxis(y), ZAxis(z) + { OVR_MATH_ASSERT(abs(x) != abs(y) && abs(y) != abs(z) && abs(z) != abs(x));} +}; + +} // namespace OVR + + +//------------------------------------------------------------------------------------// +// ***** C Compatibility Types + +// These declarations are used to support conversion between C types used in +// LibOVR C interfaces and their C++ versions. As an example, they allow passing +// Vector3f into a function that expects ovrVector3f. + +typedef struct ovrQuatf_ ovrQuatf; +typedef struct ovrQuatd_ ovrQuatd; +typedef struct ovrSizei_ ovrSizei; +typedef struct ovrSizef_ ovrSizef; +typedef struct ovrSized_ ovrSized; +typedef struct ovrRecti_ ovrRecti; +typedef struct ovrVector2i_ ovrVector2i; +typedef struct ovrVector2f_ ovrVector2f; +typedef struct ovrVector2d_ ovrVector2d; +typedef struct ovrVector3f_ ovrVector3f; +typedef struct ovrVector3d_ ovrVector3d; +typedef struct ovrVector4f_ ovrVector4f; +typedef struct ovrVector4d_ ovrVector4d; +typedef struct ovrMatrix2f_ ovrMatrix2f; +typedef struct ovrMatrix2d_ ovrMatrix2d; +typedef struct ovrMatrix3f_ ovrMatrix3f; +typedef struct ovrMatrix3d_ ovrMatrix3d; +typedef struct ovrMatrix4f_ ovrMatrix4f; +typedef struct ovrMatrix4d_ ovrMatrix4d; +typedef struct ovrPosef_ ovrPosef; +typedef struct ovrPosed_ ovrPosed; +typedef struct ovrPoseStatef_ ovrPoseStatef; +typedef struct ovrPoseStated_ ovrPoseStated; + +namespace OVR { + +// Forward-declare our templates. +template class Quat; +template class Size; +template class Rect; +template class Vector2; +template class Vector3; +template class Vector4; +template class Matrix2; +template class Matrix3; +template class Matrix4; +template class Pose; +template class PoseState; + +// CompatibleTypes::Type is used to lookup a compatible C-version of a C++ class. +template +struct CompatibleTypes +{ + // Declaration here seems necessary for MSVC; specializations are + // used instead. + typedef struct {} Type; +}; + +// Specializations providing CompatibleTypes::Type value. +template<> struct CompatibleTypes > { typedef ovrQuatf Type; }; +template<> struct CompatibleTypes > { typedef ovrQuatd Type; }; +template<> struct CompatibleTypes > { typedef ovrMatrix2f Type; }; +template<> struct CompatibleTypes > { typedef ovrMatrix2d Type; }; +template<> struct CompatibleTypes > { typedef ovrMatrix3f Type; }; +template<> struct CompatibleTypes > { typedef ovrMatrix3d Type; }; +template<> struct CompatibleTypes > { typedef ovrMatrix4f Type; }; +template<> struct CompatibleTypes > { typedef ovrMatrix4d Type; }; +template<> struct CompatibleTypes > { typedef ovrSizei Type; }; +template<> struct CompatibleTypes > { typedef ovrSizef Type; }; +template<> struct CompatibleTypes > { typedef ovrSized Type; }; +template<> struct CompatibleTypes > { typedef ovrRecti Type; }; +template<> struct CompatibleTypes > { typedef ovrVector2i Type; }; +template<> struct CompatibleTypes > { typedef ovrVector2f Type; }; +template<> struct CompatibleTypes > { typedef ovrVector2d Type; }; +template<> struct CompatibleTypes > { typedef ovrVector3f Type; }; +template<> struct CompatibleTypes > { typedef ovrVector3d Type; }; +template<> struct CompatibleTypes > { typedef ovrVector4f Type; }; +template<> struct CompatibleTypes > { typedef ovrVector4d Type; }; +template<> struct CompatibleTypes > { typedef ovrPosef Type; }; +template<> struct CompatibleTypes > { typedef ovrPosed Type; }; + +//------------------------------------------------------------------------------------// +// ***** Math +// +// Math class contains constants and functions. This class is a template specialized +// per type, with Math and Math being distinct. +template +class Math +{ +public: + // By default, support explicit conversion to float. This allows Vector2 to + // compile, for example. + typedef float OtherFloatType; + + static int Tolerance() { return 0; } // Default value so integer types compile +}; + + +//------------------------------------------------------------------------------------// +// ***** double constants +#define MATH_DOUBLE_PI 3.14159265358979323846 +#define MATH_DOUBLE_TWOPI (2*MATH_DOUBLE_PI) +#define MATH_DOUBLE_PIOVER2 (0.5*MATH_DOUBLE_PI) +#define MATH_DOUBLE_PIOVER4 (0.25*MATH_DOUBLE_PI) +#define MATH_FLOAT_MAXVALUE (FLT_MAX) + +#define MATH_DOUBLE_RADTODEGREEFACTOR (360.0 / MATH_DOUBLE_TWOPI) +#define MATH_DOUBLE_DEGREETORADFACTOR (MATH_DOUBLE_TWOPI / 360.0) + +#define MATH_DOUBLE_E 2.71828182845904523536 +#define MATH_DOUBLE_LOG2E 1.44269504088896340736 +#define MATH_DOUBLE_LOG10E 0.434294481903251827651 +#define MATH_DOUBLE_LN2 0.693147180559945309417 +#define MATH_DOUBLE_LN10 2.30258509299404568402 + +#define MATH_DOUBLE_SQRT2 1.41421356237309504880 +#define MATH_DOUBLE_SQRT1_2 0.707106781186547524401 + +#define MATH_DOUBLE_TOLERANCE 1e-12 // a default number for value equality tolerance: about 4500*Epsilon; +#define MATH_DOUBLE_SINGULARITYRADIUS 1e-12 // about 1-cos(.0001 degree), for gimbal lock numerical problems + +//------------------------------------------------------------------------------------// +// ***** float constants +#define MATH_FLOAT_PI float(MATH_DOUBLE_PI) +#define MATH_FLOAT_TWOPI float(MATH_DOUBLE_TWOPI) +#define MATH_FLOAT_PIOVER2 float(MATH_DOUBLE_PIOVER2) +#define MATH_FLOAT_PIOVER4 float(MATH_DOUBLE_PIOVER4) + +#define MATH_FLOAT_RADTODEGREEFACTOR float(MATH_DOUBLE_RADTODEGREEFACTOR) +#define MATH_FLOAT_DEGREETORADFACTOR float(MATH_DOUBLE_DEGREETORADFACTOR) + +#define MATH_FLOAT_E float(MATH_DOUBLE_E) +#define MATH_FLOAT_LOG2E float(MATH_DOUBLE_LOG2E) +#define MATH_FLOAT_LOG10E float(MATH_DOUBLE_LOG10E) +#define MATH_FLOAT_LN2 float(MATH_DOUBLE_LN2) +#define MATH_FLOAT_LN10 float(MATH_DOUBLE_LN10) + +#define MATH_FLOAT_SQRT2 float(MATH_DOUBLE_SQRT2) +#define MATH_FLOAT_SQRT1_2 float(MATH_DOUBLE_SQRT1_2) + +#define MATH_FLOAT_TOLERANCE 1e-5f // a default number for value equality tolerance: 1e-5, about 84*EPSILON; +#define MATH_FLOAT_SINGULARITYRADIUS 1e-7f // about 1-cos(.025 degree), for gimbal lock numerical problems + + + +// Single-precision Math constants class. +template<> +class Math +{ +public: + typedef double OtherFloatType; + + static inline float Tolerance() { return MATH_FLOAT_TOLERANCE; }; // a default number for value equality tolerance + static inline float SingularityRadius() { return MATH_FLOAT_SINGULARITYRADIUS; }; // for gimbal lock numerical problems +}; + +// Double-precision Math constants class +template<> +class Math +{ +public: + typedef float OtherFloatType; + + static inline double Tolerance() { return MATH_DOUBLE_TOLERANCE; }; // a default number for value equality tolerance + static inline double SingularityRadius() { return MATH_DOUBLE_SINGULARITYRADIUS; }; // for gimbal lock numerical problems +}; + +typedef Math Mathf; +typedef Math Mathd; + +// Conversion functions between degrees and radians +// (non-templated to ensure passing int arguments causes warning) +inline float RadToDegree(float rad) { return rad * MATH_FLOAT_RADTODEGREEFACTOR; } +inline double RadToDegree(double rad) { return rad * MATH_DOUBLE_RADTODEGREEFACTOR; } + +inline float DegreeToRad(float deg) { return deg * MATH_FLOAT_DEGREETORADFACTOR; } +inline double DegreeToRad(double deg) { return deg * MATH_DOUBLE_DEGREETORADFACTOR; } + +// Square function +template +inline T Sqr(T x) { return x*x; } + +// Sign: returns 0 if x == 0, -1 if x < 0, and 1 if x > 0 +template +inline T Sign(T x) { return (x != T(0)) ? (x < T(0) ? T(-1) : T(1)) : T(0); } + +// Numerically stable acos function +inline float Acos(float x) { return (x > 1.0f) ? 0.0f : (x < -1.0f) ? MATH_FLOAT_PI : acosf(x); } +inline double Acos(double x) { return (x > 1.0) ? 0.0 : (x < -1.0) ? MATH_DOUBLE_PI : acos(x); } + +// Numerically stable asin function +inline float Asin(float x) { return (x > 1.0f) ? MATH_FLOAT_PIOVER2 : (x < -1.0f) ? -MATH_FLOAT_PIOVER2 : asinf(x); } +inline double Asin(double x) { return (x > 1.0) ? MATH_DOUBLE_PIOVER2 : (x < -1.0) ? -MATH_DOUBLE_PIOVER2 : asin(x); } + +#if defined(_MSC_VER) + inline int isnan(double x) { return ::_isnan(x); } +#elif !defined(isnan) // Some libraries #define isnan. + inline int isnan(double x) { return ::isnan(x); } +#endif + +template +class Quat; + + +//------------------------------------------------------------------------------------- +// ***** Vector2<> + +// Vector2f (Vector2d) represents a 2-dimensional vector or point in space, +// consisting of coordinates x and y + +template +class Vector2 +{ +public: + typedef T ElementType; + static const size_t ElementCount = 2; + + T x, y; + + Vector2() : x(0), y(0) { } + Vector2(T x_, T y_) : x(x_), y(y_) { } + explicit Vector2(T s) : x(s), y(s) { } + explicit Vector2(const Vector2::OtherFloatType> &src) + : x((T)src.x), y((T)src.y) { } + + static Vector2 Zero() { return Vector2(0, 0); } + + // C-interop support. + typedef typename CompatibleTypes >::Type CompatibleType; + + Vector2(const CompatibleType& s) : x(s.x), y(s.y) { } + + operator const CompatibleType& () const + { + OVR_MATH_STATIC_ASSERT(sizeof(Vector2) == sizeof(CompatibleType), "sizeof(Vector2) failure"); + return reinterpret_cast(*this); + } + + + bool operator== (const Vector2& b) const { return x == b.x && y == b.y; } + bool operator!= (const Vector2& b) const { return x != b.x || y != b.y; } + + Vector2 operator+ (const Vector2& b) const { return Vector2(x + b.x, y + b.y); } + Vector2& operator+= (const Vector2& b) { x += b.x; y += b.y; return *this; } + Vector2 operator- (const Vector2& b) const { return Vector2(x - b.x, y - b.y); } + Vector2& operator-= (const Vector2& b) { x -= b.x; y -= b.y; return *this; } + Vector2 operator- () const { return Vector2(-x, -y); } + + // Scalar multiplication/division scales vector. + Vector2 operator* (T s) const { return Vector2(x*s, y*s); } + Vector2& operator*= (T s) { x *= s; y *= s; return *this; } + + Vector2 operator/ (T s) const { T rcp = T(1)/s; + return Vector2(x*rcp, y*rcp); } + Vector2& operator/= (T s) { T rcp = T(1)/s; + x *= rcp; y *= rcp; + return *this; } + + static Vector2 Min(const Vector2& a, const Vector2& b) { return Vector2((a.x < b.x) ? a.x : b.x, + (a.y < b.y) ? a.y : b.y); } + static Vector2 Max(const Vector2& a, const Vector2& b) { return Vector2((a.x > b.x) ? a.x : b.x, + (a.y > b.y) ? a.y : b.y); } + + Vector2 Clamped(T maxMag) const + { + T magSquared = LengthSq(); + if (magSquared <= Sqr(maxMag)) + return *this; + else + return *this * (maxMag / sqrt(magSquared)); + } + + // Compare two vectors for equality with tolerance. Returns true if vectors match withing tolerance. + bool IsEqual(const Vector2& b, T tolerance =Math::Tolerance()) const + { + return (fabs(b.x-x) <= tolerance) && + (fabs(b.y-y) <= tolerance); + } + bool Compare(const Vector2& b, T tolerance = Math::Tolerance()) const + { + return IsEqual(b, tolerance); + } + + // Access element by index + T& operator[] (int idx) + { + OVR_MATH_ASSERT(0 <= idx && idx < 2); + return *(&x + idx); + } + const T& operator[] (int idx) const + { + OVR_MATH_ASSERT(0 <= idx && idx < 2); + return *(&x + idx); + } + + // Entry-wise product of two vectors + Vector2 EntrywiseMultiply(const Vector2& b) const { return Vector2(x * b.x, y * b.y);} + + + // Multiply and divide operators do entry-wise math. Used Dot() for dot product. + Vector2 operator* (const Vector2& b) const { return Vector2(x * b.x, y * b.y); } + Vector2 operator/ (const Vector2& b) const { return Vector2(x / b.x, y / b.y); } + + // Dot product + // Used to calculate angle q between two vectors among other things, + // as (A dot B) = |a||b|cos(q). + T Dot(const Vector2& b) const { return x*b.x + y*b.y; } + + // Returns the angle from this vector to b, in radians. + T Angle(const Vector2& b) const + { + T div = LengthSq()*b.LengthSq(); + OVR_MATH_ASSERT(div != T(0)); + T result = Acos((this->Dot(b))/sqrt(div)); + return result; + } + + // Return Length of the vector squared. + T LengthSq() const { return (x * x + y * y); } + + // Return vector length. + T Length() const { return sqrt(LengthSq()); } + + // Returns squared distance between two points represented by vectors. + T DistanceSq(const Vector2& b) const { return (*this - b).LengthSq(); } + + // Returns distance between two points represented by vectors. + T Distance(const Vector2& b) const { return (*this - b).Length(); } + + // Determine if this a unit vector. + bool IsNormalized() const { return fabs(LengthSq() - T(1)) < Math::Tolerance(); } + + // Normalize, convention vector length to 1. + void Normalize() + { + T s = Length(); + if (s != T(0)) + s = T(1) / s; + *this *= s; + } + + // Returns normalized (unit) version of the vector without modifying itself. + Vector2 Normalized() const + { + T s = Length(); + if (s != T(0)) + s = T(1) / s; + return *this * s; + } + + // Linearly interpolates from this vector to another. + // Factor should be between 0.0 and 1.0, with 0 giving full value to this. + Vector2 Lerp(const Vector2& b, T f) const { return *this*(T(1) - f) + b*f; } + + // Projects this vector onto the argument; in other words, + // A.Project(B) returns projection of vector A onto B. + Vector2 ProjectTo(const Vector2& b) const + { + T l2 = b.LengthSq(); + OVR_MATH_ASSERT(l2 != T(0)); + return b * ( Dot(b) / l2 ); + } + + // returns true if vector b is clockwise from this vector + bool IsClockwise(const Vector2& b) const + { + return (x * b.y - y * b.x) < 0; + } +}; + + +typedef Vector2 Vector2f; +typedef Vector2 Vector2d; +typedef Vector2 Vector2i; + +typedef Vector2 Point2f; +typedef Vector2 Point2d; +typedef Vector2 Point2i; + +//------------------------------------------------------------------------------------- +// ***** Vector3<> - 3D vector of {x, y, z} + +// +// Vector3f (Vector3d) represents a 3-dimensional vector or point in space, +// consisting of coordinates x, y and z. + +template +class Vector3 +{ +public: + typedef T ElementType; + static const size_t ElementCount = 3; + + T x, y, z; + + // FIXME: default initialization of a vector class can be very expensive in a full-blown + // application. A few hundred thousand vector constructions is not unlikely and can add + // up to milliseconds of time on processors like the PS3 PPU. + Vector3() : x(0), y(0), z(0) { } + Vector3(T x_, T y_, T z_ = 0) : x(x_), y(y_), z(z_) { } + explicit Vector3(T s) : x(s), y(s), z(s) { } + explicit Vector3(const Vector3::OtherFloatType> &src) + : x((T)src.x), y((T)src.y), z((T)src.z) { } + + static Vector3 Zero() { return Vector3(0, 0, 0); } + + // C-interop support. + typedef typename CompatibleTypes >::Type CompatibleType; + + Vector3(const CompatibleType& s) : x(s.x), y(s.y), z(s.z) { } + + operator const CompatibleType& () const + { + OVR_MATH_STATIC_ASSERT(sizeof(Vector3) == sizeof(CompatibleType), "sizeof(Vector3) failure"); + return reinterpret_cast(*this); + } + + bool operator== (const Vector3& b) const { return x == b.x && y == b.y && z == b.z; } + bool operator!= (const Vector3& b) const { return x != b.x || y != b.y || z != b.z; } + + Vector3 operator+ (const Vector3& b) const { return Vector3(x + b.x, y + b.y, z + b.z); } + Vector3& operator+= (const Vector3& b) { x += b.x; y += b.y; z += b.z; return *this; } + Vector3 operator- (const Vector3& b) const { return Vector3(x - b.x, y - b.y, z - b.z); } + Vector3& operator-= (const Vector3& b) { x -= b.x; y -= b.y; z -= b.z; return *this; } + Vector3 operator- () const { return Vector3(-x, -y, -z); } + + // Scalar multiplication/division scales vector. + Vector3 operator* (T s) const { return Vector3(x*s, y*s, z*s); } + Vector3& operator*= (T s) { x *= s; y *= s; z *= s; return *this; } + + Vector3 operator/ (T s) const { T rcp = T(1)/s; + return Vector3(x*rcp, y*rcp, z*rcp); } + Vector3& operator/= (T s) { T rcp = T(1)/s; + x *= rcp; y *= rcp; z *= rcp; + return *this; } + + static Vector3 Min(const Vector3& a, const Vector3& b) + { + return Vector3((a.x < b.x) ? a.x : b.x, + (a.y < b.y) ? a.y : b.y, + (a.z < b.z) ? a.z : b.z); + } + static Vector3 Max(const Vector3& a, const Vector3& b) + { + return Vector3((a.x > b.x) ? a.x : b.x, + (a.y > b.y) ? a.y : b.y, + (a.z > b.z) ? a.z : b.z); + } + + Vector3 Clamped(T maxMag) const + { + T magSquared = LengthSq(); + if (magSquared <= Sqr(maxMag)) + return *this; + else + return *this * (maxMag / sqrt(magSquared)); + } + + // Compare two vectors for equality with tolerance. Returns true if vectors match withing tolerance. + bool IsEqual(const Vector3& b, T tolerance = Math::Tolerance()) const + { + return (fabs(b.x-x) <= tolerance) && + (fabs(b.y-y) <= tolerance) && + (fabs(b.z-z) <= tolerance); + } + bool Compare(const Vector3& b, T tolerance = Math::Tolerance()) const + { + return IsEqual(b, tolerance); + } + + T& operator[] (int idx) + { + OVR_MATH_ASSERT(0 <= idx && idx < 3); + return *(&x + idx); + } + + const T& operator[] (int idx) const + { + OVR_MATH_ASSERT(0 <= idx && idx < 3); + return *(&x + idx); + } + + // Entrywise product of two vectors + Vector3 EntrywiseMultiply(const Vector3& b) const { return Vector3(x * b.x, + y * b.y, + z * b.z);} + + // Multiply and divide operators do entry-wise math + Vector3 operator* (const Vector3& b) const { return Vector3(x * b.x, + y * b.y, + z * b.z); } + + Vector3 operator/ (const Vector3& b) const { return Vector3(x / b.x, + y / b.y, + z / b.z); } + + + // Dot product + // Used to calculate angle q between two vectors among other things, + // as (A dot B) = |a||b|cos(q). + T Dot(const Vector3& b) const { return x*b.x + y*b.y + z*b.z; } + + // Compute cross product, which generates a normal vector. + // Direction vector can be determined by right-hand rule: Pointing index finder in + // direction a and middle finger in direction b, thumb will point in a.Cross(b). + Vector3 Cross(const Vector3& b) const { return Vector3(y*b.z - z*b.y, + z*b.x - x*b.z, + x*b.y - y*b.x); } + + // Returns the angle from this vector to b, in radians. + T Angle(const Vector3& b) const + { + T div = LengthSq()*b.LengthSq(); + OVR_MATH_ASSERT(div != T(0)); + T result = Acos((this->Dot(b))/sqrt(div)); + return result; + } + + // Return Length of the vector squared. + T LengthSq() const { return (x * x + y * y + z * z); } + + // Return vector length. + T Length() const { return (T)sqrt(LengthSq()); } + + // Returns squared distance between two points represented by vectors. + T DistanceSq(Vector3 const& b) const { return (*this - b).LengthSq(); } + + // Returns distance between two points represented by vectors. + T Distance(Vector3 const& b) const { return (*this - b).Length(); } + + bool IsNormalized() const { return fabs(LengthSq() - T(1)) < Math::Tolerance(); } + + // Normalize, convention vector length to 1. + void Normalize() + { + T s = Length(); + if (s != T(0)) + s = T(1) / s; + *this *= s; + } + + // Returns normalized (unit) version of the vector without modifying itself. + Vector3 Normalized() const + { + T s = Length(); + if (s != T(0)) + s = T(1) / s; + return *this * s; + } + + // Linearly interpolates from this vector to another. + // Factor should be between 0.0 and 1.0, with 0 giving full value to this. + Vector3 Lerp(const Vector3& b, T f) const { return *this*(T(1) - f) + b*f; } + + // Projects this vector onto the argument; in other words, + // A.Project(B) returns projection of vector A onto B. + Vector3 ProjectTo(const Vector3& b) const + { + T l2 = b.LengthSq(); + OVR_MATH_ASSERT(l2 != T(0)); + return b * ( Dot(b) / l2 ); + } + + // Projects this vector onto a plane defined by a normal vector + Vector3 ProjectToPlane(const Vector3& normal) const { return *this - this->ProjectTo(normal); } +}; + +typedef Vector3 Vector3f; +typedef Vector3 Vector3d; +typedef Vector3 Vector3i; + +OVR_MATH_STATIC_ASSERT((sizeof(Vector3f) == 3*sizeof(float)), "sizeof(Vector3f) failure"); +OVR_MATH_STATIC_ASSERT((sizeof(Vector3d) == 3*sizeof(double)), "sizeof(Vector3d) failure"); +OVR_MATH_STATIC_ASSERT((sizeof(Vector3i) == 3*sizeof(int32_t)), "sizeof(Vector3i) failure"); + +typedef Vector3 Point3f; +typedef Vector3 Point3d; +typedef Vector3 Point3i; + + +//------------------------------------------------------------------------------------- +// ***** Vector4<> - 4D vector of {x, y, z, w} + +// +// Vector4f (Vector4d) represents a 3-dimensional vector or point in space, +// consisting of coordinates x, y, z and w. + +template +class Vector4 +{ +public: + typedef T ElementType; + static const size_t ElementCount = 4; + + T x, y, z, w; + + // FIXME: default initialization of a vector class can be very expensive in a full-blown + // application. A few hundred thousand vector constructions is not unlikely and can add + // up to milliseconds of time on processors like the PS3 PPU. + Vector4() : x(0), y(0), z(0), w(0) { } + Vector4(T x_, T y_, T z_, T w_) : x(x_), y(y_), z(z_), w(w_) { } + explicit Vector4(T s) : x(s), y(s), z(s), w(s) { } + explicit Vector4(const Vector3& v, const T w_=T(1)) : x(v.x), y(v.y), z(v.z), w(w_) { } + explicit Vector4(const Vector4::OtherFloatType> &src) + : x((T)src.x), y((T)src.y), z((T)src.z), w((T)src.w) { } + + static Vector4 Zero() { return Vector4(0, 0, 0, 0); } + + // C-interop support. + typedef typename CompatibleTypes< Vector4 >::Type CompatibleType; + + Vector4(const CompatibleType& s) : x(s.x), y(s.y), z(s.z), w(s.w) { } + + operator const CompatibleType& () const + { + OVR_MATH_STATIC_ASSERT(sizeof(Vector4) == sizeof(CompatibleType), "sizeof(Vector4) failure"); + return reinterpret_cast(*this); + } + + Vector4& operator= (const Vector3& other) { x=other.x; y=other.y; z=other.z; w=1; return *this; } + bool operator== (const Vector4& b) const { return x == b.x && y == b.y && z == b.z && w == b.w; } + bool operator!= (const Vector4& b) const { return x != b.x || y != b.y || z != b.z || w != b.w; } + + Vector4 operator+ (const Vector4& b) const { return Vector4(x + b.x, y + b.y, z + b.z, w + b.w); } + Vector4& operator+= (const Vector4& b) { x += b.x; y += b.y; z += b.z; w += b.w; return *this; } + Vector4 operator- (const Vector4& b) const { return Vector4(x - b.x, y - b.y, z - b.z, w - b.w); } + Vector4& operator-= (const Vector4& b) { x -= b.x; y -= b.y; z -= b.z; w -= b.w; return *this; } + Vector4 operator- () const { return Vector4(-x, -y, -z, -w); } + + // Scalar multiplication/division scales vector. + Vector4 operator* (T s) const { return Vector4(x*s, y*s, z*s, w*s); } + Vector4& operator*= (T s) { x *= s; y *= s; z *= s; w *= s;return *this; } + + Vector4 operator/ (T s) const { T rcp = T(1)/s; + return Vector4(x*rcp, y*rcp, z*rcp, w*rcp); } + Vector4& operator/= (T s) { T rcp = T(1)/s; + x *= rcp; y *= rcp; z *= rcp; w *= rcp; + return *this; } + + static Vector4 Min(const Vector4& a, const Vector4& b) + { + return Vector4((a.x < b.x) ? a.x : b.x, + (a.y < b.y) ? a.y : b.y, + (a.z < b.z) ? a.z : b.z, + (a.w < b.w) ? a.w : b.w); + } + static Vector4 Max(const Vector4& a, const Vector4& b) + { + return Vector4((a.x > b.x) ? a.x : b.x, + (a.y > b.y) ? a.y : b.y, + (a.z > b.z) ? a.z : b.z, + (a.w > b.w) ? a.w : b.w); + } + + Vector4 Clamped(T maxMag) const + { + T magSquared = LengthSq(); + if (magSquared <= Sqr(maxMag)) + return *this; + else + return *this * (maxMag / sqrt(magSquared)); + } + + // Compare two vectors for equality with tolerance. Returns true if vectors match withing tolerance. + bool IsEqual(const Vector4& b, T tolerance = Math::Tolerance()) const + { + return (fabs(b.x-x) <= tolerance) && + (fabs(b.y-y) <= tolerance) && + (fabs(b.z-z) <= tolerance) && + (fabs(b.w-w) <= tolerance); + } + bool Compare(const Vector4& b, T tolerance = Math::Tolerance()) const + { + return IsEqual(b, tolerance); + } + + T& operator[] (int idx) + { + OVR_MATH_ASSERT(0 <= idx && idx < 4); + return *(&x + idx); + } + + const T& operator[] (int idx) const + { + OVR_MATH_ASSERT(0 <= idx && idx < 4); + return *(&x + idx); + } + + // Entry wise product of two vectors + Vector4 EntrywiseMultiply(const Vector4& b) const { return Vector4(x * b.x, + y * b.y, + z * b.z, + w * b.w);} + + // Multiply and divide operators do entry-wise math + Vector4 operator* (const Vector4& b) const { return Vector4(x * b.x, + y * b.y, + z * b.z, + w * b.w); } + + Vector4 operator/ (const Vector4& b) const { return Vector4(x / b.x, + y / b.y, + z / b.z, + w / b.w); } + + + // Dot product + T Dot(const Vector4& b) const { return x*b.x + y*b.y + z*b.z + w*b.w; } + + // Return Length of the vector squared. + T LengthSq() const { return (x * x + y * y + z * z + w * w); } + + // Return vector length. + T Length() const { return sqrt(LengthSq()); } + + bool IsNormalized() const { return fabs(LengthSq() - T(1)) < Math::Tolerance(); } + + // Normalize, convention vector length to 1. + void Normalize() + { + T s = Length(); + if (s != T(0)) + s = T(1) / s; + *this *= s; + } + + // Returns normalized (unit) version of the vector without modifying itself. + Vector4 Normalized() const + { + T s = Length(); + if (s != T(0)) + s = T(1) / s; + return *this * s; + } + + // Linearly interpolates from this vector to another. + // Factor should be between 0.0 and 1.0, with 0 giving full value to this. + Vector4 Lerp(const Vector4& b, T f) const { return *this*(T(1) - f) + b*f; } +}; + +typedef Vector4 Vector4f; +typedef Vector4 Vector4d; +typedef Vector4 Vector4i; + + +//------------------------------------------------------------------------------------- +// ***** Bounds3 + +// Bounds class used to describe a 3D axis aligned bounding box. + +template +class Bounds3 +{ +public: + Vector3 b[2]; + + Bounds3() + { + } + + Bounds3( const Vector3 & mins, const Vector3 & maxs ) +{ + b[0] = mins; + b[1] = maxs; + } + + void Clear() + { + b[0].x = b[0].y = b[0].z = Math::MaxValue; + b[1].x = b[1].y = b[1].z = -Math::MaxValue; + } + + void AddPoint( const Vector3 & v ) + { + b[0].x = (b[0].x < v.x ? b[0].x : v.x); + b[0].y = (b[0].y < v.y ? b[0].y : v.y); + b[0].z = (b[0].z < v.z ? b[0].z : v.z); + b[1].x = (v.x < b[1].x ? b[1].x : v.x); + b[1].y = (v.y < b[1].y ? b[1].y : v.y); + b[1].z = (v.z < b[1].z ? b[1].z : v.z); + } + + const Vector3 & GetMins() const { return b[0]; } + const Vector3 & GetMaxs() const { return b[1]; } + + Vector3 & GetMins() { return b[0]; } + Vector3 & GetMaxs() { return b[1]; } +}; + +typedef Bounds3 Bounds3f; +typedef Bounds3 Bounds3d; + + +//------------------------------------------------------------------------------------- +// ***** Size + +// Size class represents 2D size with Width, Height components. +// Used to describe distentions of render targets, etc. + +template +class Size +{ +public: + T w, h; + + Size() : w(0), h(0) { } + Size(T w_, T h_) : w(w_), h(h_) { } + explicit Size(T s) : w(s), h(s) { } + explicit Size(const Size::OtherFloatType> &src) + : w((T)src.w), h((T)src.h) { } + + // C-interop support. + typedef typename CompatibleTypes >::Type CompatibleType; + + Size(const CompatibleType& s) : w(s.w), h(s.h) { } + + operator const CompatibleType& () const + { + OVR_MATH_STATIC_ASSERT(sizeof(Size) == sizeof(CompatibleType), "sizeof(Size) failure"); + return reinterpret_cast(*this); + } + + bool operator== (const Size& b) const { return w == b.w && h == b.h; } + bool operator!= (const Size& b) const { return w != b.w || h != b.h; } + + Size operator+ (const Size& b) const { return Size(w + b.w, h + b.h); } + Size& operator+= (const Size& b) { w += b.w; h += b.h; return *this; } + Size operator- (const Size& b) const { return Size(w - b.w, h - b.h); } + Size& operator-= (const Size& b) { w -= b.w; h -= b.h; return *this; } + Size operator- () const { return Size(-w, -h); } + Size operator* (const Size& b) const { return Size(w * b.w, h * b.h); } + Size& operator*= (const Size& b) { w *= b.w; h *= b.h; return *this; } + Size operator/ (const Size& b) const { return Size(w / b.w, h / b.h); } + Size& operator/= (const Size& b) { w /= b.w; h /= b.h; return *this; } + + // Scalar multiplication/division scales both components. + Size operator* (T s) const { return Size(w*s, h*s); } + Size& operator*= (T s) { w *= s; h *= s; return *this; } + Size operator/ (T s) const { return Size(w/s, h/s); } + Size& operator/= (T s) { w /= s; h /= s; return *this; } + + static Size Min(const Size& a, const Size& b) { return Size((a.w < b.w) ? a.w : b.w, + (a.h < b.h) ? a.h : b.h); } + static Size Max(const Size& a, const Size& b) { return Size((a.w > b.w) ? a.w : b.w, + (a.h > b.h) ? a.h : b.h); } + + T Area() const { return w * h; } + + inline Vector2 ToVector() const { return Vector2(w, h); } +}; + + +typedef Size Sizei; +typedef Size Sizeu; +typedef Size Sizef; +typedef Size Sized; + + + +//----------------------------------------------------------------------------------- +// ***** Rect + +// Rect describes a rectangular area for rendering, that includes position and size. +template +class Rect +{ +public: + T x, y; + T w, h; + + Rect() { } + Rect(T x1, T y1, T w1, T h1) : x(x1), y(y1), w(w1), h(h1) { } + Rect(const Vector2& pos, const Size& sz) : x(pos.x), y(pos.y), w(sz.w), h(sz.h) { } + Rect(const Size& sz) : x(0), y(0), w(sz.w), h(sz.h) { } + + // C-interop support. + typedef typename CompatibleTypes >::Type CompatibleType; + + Rect(const CompatibleType& s) : x(s.Pos.x), y(s.Pos.y), w(s.Size.w), h(s.Size.h) { } + + operator const CompatibleType& () const + { + OVR_MATH_STATIC_ASSERT(sizeof(Rect) == sizeof(CompatibleType), "sizeof(Rect) failure"); + return reinterpret_cast(*this); + } + + Vector2 GetPos() const { return Vector2(x, y); } + Size GetSize() const { return Size(w, h); } + void SetPos(const Vector2& pos) { x = pos.x; y = pos.y; } + void SetSize(const Size& sz) { w = sz.w; h = sz.h; } + + bool operator == (const Rect& vp) const + { return (x == vp.x) && (y == vp.y) && (w == vp.w) && (h == vp.h); } + bool operator != (const Rect& vp) const + { return !operator == (vp); } +}; + +typedef Rect Recti; + + +//-------------------------------------------------------------------------------------// +// ***** Quat +// +// Quatf represents a quaternion class used for rotations. +// +// Quaternion multiplications are done in right-to-left order, to match the +// behavior of matrices. + + +template +class Quat +{ +public: + typedef T ElementType; + static const size_t ElementCount = 4; + + // x,y,z = axis*sin(angle), w = cos(angle) + T x, y, z, w; + + Quat() : x(0), y(0), z(0), w(1) { } + Quat(T x_, T y_, T z_, T w_) : x(x_), y(y_), z(z_), w(w_) { } + explicit Quat(const Quat::OtherFloatType> &src) + : x((T)src.x), y((T)src.y), z((T)src.z), w((T)src.w) + { + // NOTE: Converting a normalized Quat to Quat + // will generally result in an un-normalized quaternion. + // But we don't normalize here in case the quaternion + // being converted is not a normalized rotation quaternion. + } + + typedef typename CompatibleTypes >::Type CompatibleType; + + // C-interop support. + Quat(const CompatibleType& s) : x(s.x), y(s.y), z(s.z), w(s.w) { } + + operator CompatibleType () const + { + CompatibleType result; + result.x = x; + result.y = y; + result.z = z; + result.w = w; + return result; + } + + // Constructs quaternion for rotation around the axis by an angle. + Quat(const Vector3& axis, T angle) + { + // Make sure we don't divide by zero. + if (axis.LengthSq() == T(0)) + { + // Assert if the axis is zero, but the angle isn't + OVR_MATH_ASSERT(angle == T(0)); + x = y = z = T(0); w = T(1); + return; + } + + Vector3 unitAxis = axis.Normalized(); + T sinHalfAngle = sin(angle * T(0.5)); + + w = cos(angle * T(0.5)); + x = unitAxis.x * sinHalfAngle; + y = unitAxis.y * sinHalfAngle; + z = unitAxis.z * sinHalfAngle; + } + + // Constructs quaternion for rotation around one of the coordinate axis by an angle. + Quat(Axis A, T angle, RotateDirection d = Rotate_CCW, HandedSystem s = Handed_R) + { + T sinHalfAngle = s * d *sin(angle * T(0.5)); + T v[3]; + v[0] = v[1] = v[2] = T(0); + v[A] = sinHalfAngle; + + w = cos(angle * T(0.5)); + x = v[0]; + y = v[1]; + z = v[2]; + } + + Quat operator-() { return Quat(-x, -y, -z, -w); } // unary minus + + static Quat Identity() { return Quat(0, 0, 0, 1); } + + // Compute axis and angle from quaternion + void GetAxisAngle(Vector3* axis, T* angle) const + { + if ( x*x + y*y + z*z > Math::Tolerance() * Math::Tolerance() ) { + *axis = Vector3(x, y, z).Normalized(); + *angle = 2 * Acos(w); + if (*angle > ((T)MATH_DOUBLE_PI)) // Reduce the magnitude of the angle, if necessary + { + *angle = ((T)MATH_DOUBLE_TWOPI) - *angle; + *axis = *axis * (-1); + } + } + else + { + *axis = Vector3(1, 0, 0); + *angle= T(0); + } + } + + // Convert a quaternion to a rotation vector, also known as + // Rodrigues vector, AxisAngle vector, SORA vector, exponential map. + // A rotation vector describes a rotation about an axis: + // the axis of rotation is the vector normalized, + // the angle of rotation is the magnitude of the vector. + Vector3 ToRotationVector() const + { + OVR_MATH_ASSERT(IsNormalized() || LengthSq() == 0); + T s = T(0); + T sinHalfAngle = sqrt(x*x + y*y + z*z); + if (sinHalfAngle > T(0)) + { + T cosHalfAngle = w; + T halfAngle = atan2(sinHalfAngle, cosHalfAngle); + + // Ensure minimum rotation magnitude + if (cosHalfAngle < 0) + halfAngle -= T(MATH_DOUBLE_PI); + + s = T(2) * halfAngle / sinHalfAngle; + } + return Vector3(x*s, y*s, z*s); + } + + // Faster version of the above, optimized for use with small rotations, where rotation angle ~= sin(angle) + inline OVR::Vector3 FastToRotationVector() const + { + OVR_MATH_ASSERT(IsNormalized()); + T s; + T sinHalfSquared = x*x + y*y + z*z; + if (sinHalfSquared < T(.0037)) // =~ sin(7/2 degrees)^2 + { + // Max rotation magnitude error is about .062% at 7 degrees rotation, or about .0043 degrees + s = T(2) * Sign(w); + } + else + { + T sinHalfAngle = sqrt(sinHalfSquared); + T cosHalfAngle = w; + T halfAngle = atan2(sinHalfAngle, cosHalfAngle); + + // Ensure minimum rotation magnitude + if (cosHalfAngle < 0) + halfAngle -= T(MATH_DOUBLE_PI); + + s = T(2) * halfAngle / sinHalfAngle; + } + return Vector3(x*s, y*s, z*s); + } + + // Given a rotation vector of form unitRotationAxis * angle, + // returns the equivalent quaternion (unitRotationAxis * sin(angle), cos(Angle)). + static Quat FromRotationVector(const Vector3& v) + { + T angleSquared = v.LengthSq(); + T s = T(0); + T c = T(1); + if (angleSquared > T(0)) + { + T angle = sqrt(angleSquared); + s = sin(angle * T(0.5)) / angle; // normalize + c = cos(angle * T(0.5)); + } + return Quat(s*v.x, s*v.y, s*v.z, c); + } + + // Faster version of above, optimized for use with small rotation magnitudes, where rotation angle =~ sin(angle). + // If normalize is false, small-angle quaternions are returned un-normalized. + inline static Quat FastFromRotationVector(const OVR::Vector3& v, bool normalize = true) + { + T s, c; + T angleSquared = v.LengthSq(); + if (angleSquared < T(0.0076)) // =~ (5 degrees*pi/180)^2 + { + s = T(0.5); + c = T(1.0); + // Max rotation magnitude error (after normalization) is about .064% at 5 degrees rotation, or .0032 degrees + if (normalize && angleSquared > 0) + { + // sin(angle/2)^2 ~= (angle/2)^2 and cos(angle/2)^2 ~= 1 + T invLen = T(1) / sqrt(angleSquared * T(0.25) + T(1)); // normalize + s = s * invLen; + c = c * invLen; + } + } + else + { + T angle = sqrt(angleSquared); + s = sin(angle * T(0.5)) / angle; + c = cos(angle * T(0.5)); + } + return Quat(s*v.x, s*v.y, s*v.z, c); + } + + // Constructs the quaternion from a rotation matrix + explicit Quat(const Matrix4& m) + { + T trace = m.M[0][0] + m.M[1][1] + m.M[2][2]; + + // In almost all cases, the first part is executed. + // However, if the trace is not positive, the other + // cases arise. + if (trace > T(0)) + { + T s = sqrt(trace + T(1)) * T(2); // s=4*qw + w = T(0.25) * s; + x = (m.M[2][1] - m.M[1][2]) / s; + y = (m.M[0][2] - m.M[2][0]) / s; + z = (m.M[1][0] - m.M[0][1]) / s; + } + else if ((m.M[0][0] > m.M[1][1])&&(m.M[0][0] > m.M[2][2])) + { + T s = sqrt(T(1) + m.M[0][0] - m.M[1][1] - m.M[2][2]) * T(2); + w = (m.M[2][1] - m.M[1][2]) / s; + x = T(0.25) * s; + y = (m.M[0][1] + m.M[1][0]) / s; + z = (m.M[2][0] + m.M[0][2]) / s; + } + else if (m.M[1][1] > m.M[2][2]) + { + T s = sqrt(T(1) + m.M[1][1] - m.M[0][0] - m.M[2][2]) * T(2); // S=4*qy + w = (m.M[0][2] - m.M[2][0]) / s; + x = (m.M[0][1] + m.M[1][0]) / s; + y = T(0.25) * s; + z = (m.M[1][2] + m.M[2][1]) / s; + } + else + { + T s = sqrt(T(1) + m.M[2][2] - m.M[0][0] - m.M[1][1]) * T(2); // S=4*qz + w = (m.M[1][0] - m.M[0][1]) / s; + x = (m.M[0][2] + m.M[2][0]) / s; + y = (m.M[1][2] + m.M[2][1]) / s; + z = T(0.25) * s; + } + OVR_MATH_ASSERT(IsNormalized()); // Ensure input matrix is orthogonal + } + + // Constructs the quaternion from a rotation matrix + explicit Quat(const Matrix3& m) + { + T trace = m.M[0][0] + m.M[1][1] + m.M[2][2]; + + // In almost all cases, the first part is executed. + // However, if the trace is not positive, the other + // cases arise. + if (trace > T(0)) + { + T s = sqrt(trace + T(1)) * T(2); // s=4*qw + w = T(0.25) * s; + x = (m.M[2][1] - m.M[1][2]) / s; + y = (m.M[0][2] - m.M[2][0]) / s; + z = (m.M[1][0] - m.M[0][1]) / s; + } + else if ((m.M[0][0] > m.M[1][1])&&(m.M[0][0] > m.M[2][2])) + { + T s = sqrt(T(1) + m.M[0][0] - m.M[1][1] - m.M[2][2]) * T(2); + w = (m.M[2][1] - m.M[1][2]) / s; + x = T(0.25) * s; + y = (m.M[0][1] + m.M[1][0]) / s; + z = (m.M[2][0] + m.M[0][2]) / s; + } + else if (m.M[1][1] > m.M[2][2]) + { + T s = sqrt(T(1) + m.M[1][1] - m.M[0][0] - m.M[2][2]) * T(2); // S=4*qy + w = (m.M[0][2] - m.M[2][0]) / s; + x = (m.M[0][1] + m.M[1][0]) / s; + y = T(0.25) * s; + z = (m.M[1][2] + m.M[2][1]) / s; + } + else + { + T s = sqrt(T(1) + m.M[2][2] - m.M[0][0] - m.M[1][1]) * T(2); // S=4*qz + w = (m.M[1][0] - m.M[0][1]) / s; + x = (m.M[0][2] + m.M[2][0]) / s; + y = (m.M[1][2] + m.M[2][1]) / s; + z = T(0.25) * s; + } + OVR_MATH_ASSERT(IsNormalized()); // Ensure input matrix is orthogonal + } + + bool operator== (const Quat& b) const { return x == b.x && y == b.y && z == b.z && w == b.w; } + bool operator!= (const Quat& b) const { return x != b.x || y != b.y || z != b.z || w != b.w; } + + Quat operator+ (const Quat& b) const { return Quat(x + b.x, y + b.y, z + b.z, w + b.w); } + Quat& operator+= (const Quat& b) { w += b.w; x += b.x; y += b.y; z += b.z; return *this; } + Quat operator- (const Quat& b) const { return Quat(x - b.x, y - b.y, z - b.z, w - b.w); } + Quat& operator-= (const Quat& b) { w -= b.w; x -= b.x; y -= b.y; z -= b.z; return *this; } + + Quat operator* (T s) const { return Quat(x * s, y * s, z * s, w * s); } + Quat& operator*= (T s) { w *= s; x *= s; y *= s; z *= s; return *this; } + Quat operator/ (T s) const { T rcp = T(1)/s; return Quat(x * rcp, y * rcp, z * rcp, w *rcp); } + Quat& operator/= (T s) { T rcp = T(1)/s; w *= rcp; x *= rcp; y *= rcp; z *= rcp; return *this; } + + // Compare two quats for equality within tolerance. Returns true if quats match withing tolerance. + bool IsEqual(const Quat& b, T tolerance = Math::Tolerance()) const + { + return Abs(Dot(b)) >= T(1) - tolerance; + } + + static T Abs(const T v) { return (v >= 0) ? v : -v; } + + // Get Imaginary part vector + Vector3 Imag() const { return Vector3(x,y,z); } + + // Get quaternion length. + T Length() const { return sqrt(LengthSq()); } + + // Get quaternion length squared. + T LengthSq() const { return (x * x + y * y + z * z + w * w); } + + // Simple Euclidean distance in R^4 (not SLERP distance, but at least respects Haar measure) + T Distance(const Quat& q) const + { + T d1 = (*this - q).Length(); + T d2 = (*this + q).Length(); // Antipodal point check + return (d1 < d2) ? d1 : d2; + } + + T DistanceSq(const Quat& q) const + { + T d1 = (*this - q).LengthSq(); + T d2 = (*this + q).LengthSq(); // Antipodal point check + return (d1 < d2) ? d1 : d2; + } + + T Dot(const Quat& q) const + { + return x * q.x + y * q.y + z * q.z + w * q.w; + } + + // Angle between two quaternions in radians + T Angle(const Quat& q) const + { + return T(2) * Acos(Abs(Dot(q))); + } + + // Angle of quaternion + T Angle() const + { + return T(2) * Acos(Abs(w)); + } + + // Normalize + bool IsNormalized() const { return fabs(LengthSq() - T(1)) < Math::Tolerance(); } + + void Normalize() + { + T s = Length(); + if (s != T(0)) + s = T(1) / s; + *this *= s; + } + + Quat Normalized() const + { + T s = Length(); + if (s != T(0)) + s = T(1) / s; + return *this * s; + } + + inline void EnsureSameHemisphere(const Quat& o) + { + if (Dot(o) < T(0)) + { + x = -x; + y = -y; + z = -z; + w = -w; + } + } + + // Returns conjugate of the quaternion. Produces inverse rotation if quaternion is normalized. + Quat Conj() const { return Quat(-x, -y, -z, w); } + + // Quaternion multiplication. Combines quaternion rotations, performing the one on the + // right hand side first. + Quat operator* (const Quat& b) const { return Quat(w * b.x + x * b.w + y * b.z - z * b.y, + w * b.y - x * b.z + y * b.w + z * b.x, + w * b.z + x * b.y - y * b.x + z * b.w, + w * b.w - x * b.x - y * b.y - z * b.z); } + const Quat& operator*= (const Quat& b) { *this = *this * b; return *this; } + + // + // this^p normalized; same as rotating by this p times. + Quat PowNormalized(T p) const + { + Vector3 v; + T a; + GetAxisAngle(&v, &a); + return Quat(v, a * p); + } + + // Compute quaternion that rotates v into alignTo: alignTo = Quat::Align(alignTo, v).Rotate(v). + // NOTE: alignTo and v must be normalized. + static Quat Align(const Vector3& alignTo, const Vector3& v) + { + OVR_MATH_ASSERT(alignTo.IsNormalized() && v.IsNormalized()); + Vector3 bisector = (v + alignTo); + bisector.Normalize(); + T cosHalfAngle = v.Dot(bisector); // 0..1 + if (cosHalfAngle > T(0)) + { + Vector3 imag = v.Cross(bisector); + return Quat(imag.x, imag.y, imag.z, cosHalfAngle); + } + else + { + // cosHalfAngle == 0: a 180 degree rotation. + // sinHalfAngle == 1, rotation axis is any axis perpendicular + // to alignTo. Choose axis to include largest magnitude components + if (fabs(v.x) > fabs(v.y)) + { + // x or z is max magnitude component + // = Cross(v, (0,1,0)).Normalized(); + T invLen = sqrt(v.x*v.x + v.z*v.z); + if (invLen > T(0)) + invLen = T(1) / invLen; + return Quat(-v.z*invLen, 0, v.x*invLen, 0); + } + else + { + // y or z is max magnitude component + // = Cross(v, (1,0,0)).Normalized(); + T invLen = sqrt(v.y*v.y + v.z*v.z); + if (invLen > T(0)) + invLen = T(1) / invLen; + return Quat(0, v.z*invLen, -v.y*invLen, 0); + } + } + } + + // Normalized linear interpolation of quaternions + // NOTE: This function is a bad approximation of Slerp() + // when the angle between the *this and b is large. + // Use FastSlerp() or Slerp() instead. + Quat Lerp(const Quat& b, T s) const + { + return (*this * (T(1) - s) + b * (Dot(b) < 0 ? -s : s)).Normalized(); + } + + // Spherical linear interpolation between rotations + Quat Slerp(const Quat& b, T s) const + { + Vector3 delta = (b * this->Inverted()).ToRotationVector(); + return FromRotationVector(delta * s) * *this; + } + + // Spherical linear interpolation: much faster for small rotations, accurate for large rotations. See FastTo/FromRotationVector + Quat FastSlerp(const Quat& b, T s) const + { + Vector3 delta = (b * this->Inverted()).FastToRotationVector(); + return (FastFromRotationVector(delta * s, false) * *this).Normalized(); + } + + // Rotate transforms vector in a manner that matches Matrix rotations (counter-clockwise, + // assuming negative direction of the axis). Standard formula: q(t) * V * q(t)^-1. + Vector3 Rotate(const Vector3& v) const + { + OVR_MATH_ASSERT(isnan(w) || IsNormalized()); + + // rv = q * (v,0) * q' + // Same as rv = v + real * cross(imag,v)*2 + cross(imag, cross(imag,v)*2); + + // uv = 2 * Imag().Cross(v); + T uvx = T(2) * (y*v.z - z*v.y); + T uvy = T(2) * (z*v.x - x*v.z); + T uvz = T(2) * (x*v.y - y*v.x); + + // return v + Real()*uv + Imag().Cross(uv); + return Vector3(v.x + w*uvx + y*uvz - z*uvy, + v.y + w*uvy + z*uvx - x*uvz, + v.z + w*uvz + x*uvy - y*uvx); + } + + // Rotation by inverse of *this + Vector3 InverseRotate(const Vector3& v) const + { + OVR_MATH_ASSERT(IsNormalized()); + + // rv = q' * (v,0) * q + // Same as rv = v + real * cross(-imag,v)*2 + cross(-imag, cross(-imag,v)*2); + // or rv = v - real * cross(imag,v)*2 + cross(imag, cross(imag,v)*2); + + // uv = 2 * Imag().Cross(v); + T uvx = T(2) * (y*v.z - z*v.y); + T uvy = T(2) * (z*v.x - x*v.z); + T uvz = T(2) * (x*v.y - y*v.x); + + // return v - Real()*uv + Imag().Cross(uv); + return Vector3(v.x - w*uvx + y*uvz - z*uvy, + v.y - w*uvy + z*uvx - x*uvz, + v.z - w*uvz + x*uvy - y*uvx); + } + + // Inversed quaternion rotates in the opposite direction. + Quat Inverted() const + { + return Quat(-x, -y, -z, w); + } + + Quat Inverse() const + { + return Quat(-x, -y, -z, w); + } + + // Sets this quaternion to the one rotates in the opposite direction. + void Invert() + { + *this = Quat(-x, -y, -z, w); + } + + // Time integration of constant angular velocity over dt + Quat TimeIntegrate(Vector3 angularVelocity, T dt) const + { + // solution is: this * exp( omega*dt/2 ); FromRotationVector(v) gives exp(v*.5). + return (*this * FastFromRotationVector(angularVelocity * dt, false)).Normalized(); + } + + // Time integration of constant angular acceleration and velocity over dt + // These are the first two terms of the "Magnus expansion" of the solution + // + // o = o * exp( W=(W1 + W2 + W3+...) * 0.5 ); + // + // omega1 = (omega + omegaDot*dt) + // W1 = (omega + omega1)*dt/2 + // W2 = cross(omega, omega1)/12*dt^2 % (= -cross(omega_dot, omega)/12*dt^3) + // Terms 3 and beyond are vanishingly small: + // W3 = cross(omega_dot, cross(omega_dot, omega))/240*dt^5 + // + Quat TimeIntegrate(Vector3 angularVelocity, Vector3 angularAcceleration, T dt) const + { + const Vector3& omega = angularVelocity; + const Vector3& omegaDot = angularAcceleration; + + Vector3 omega1 = (omega + omegaDot * dt); + Vector3 W = ( (omega + omega1) + omega.Cross(omega1) * (dt/T(6)) ) * (dt/T(2)); + + // FromRotationVector(v) is exp(v*.5) + return (*this * FastFromRotationVector(W, false)).Normalized(); + } + + // Decompose rotation into three rotations: + // roll radians about Z axis, then pitch radians about X axis, then yaw radians about Y axis. + // Call with nullptr if a return value is not needed. + void GetYawPitchRoll(T* yaw, T* pitch, T* roll) const + { + return GetEulerAngles(yaw, pitch, roll); + } + + // GetEulerAngles extracts Euler angles from the quaternion, in the specified order of + // axis rotations and the specified coordinate system. Right-handed coordinate system + // is the default, with CCW rotations while looking in the negative axis direction. + // Here a,b,c, are the Yaw/Pitch/Roll angles to be returned. + // Rotation order is c, b, a: + // rotation c around axis A3 + // is followed by rotation b around axis A2 + // is followed by rotation a around axis A1 + // rotations are CCW or CW (D) in LH or RH coordinate system (S) + // + template + void GetEulerAngles(T *a, T *b, T *c) const + { + OVR_MATH_ASSERT(IsNormalized()); + OVR_MATH_STATIC_ASSERT((A1 != A2) && (A2 != A3) && (A1 != A3), "(A1 != A2) && (A2 != A3) && (A1 != A3)"); + + T Q[3] = { x, y, z }; //Quaternion components x,y,z + + T ww = w*w; + T Q11 = Q[A1]*Q[A1]; + T Q22 = Q[A2]*Q[A2]; + T Q33 = Q[A3]*Q[A3]; + + T psign = T(-1); + // Determine whether even permutation + if (((A1 + 1) % 3 == A2) && ((A2 + 1) % 3 == A3)) + psign = T(1); + + T s2 = psign * T(2) * (psign*w*Q[A2] + Q[A1]*Q[A3]); + + T singularityRadius = Math::SingularityRadius(); + if (s2 < T(-1) + singularityRadius) + { // South pole singularity + if (a) *a = T(0); + if (b) *b = -S*D*((T)MATH_DOUBLE_PIOVER2); + if (c) *c = S*D*atan2(T(2)*(psign*Q[A1] * Q[A2] + w*Q[A3]), ww + Q22 - Q11 - Q33 ); + } + else if (s2 > T(1) - singularityRadius) + { // North pole singularity + if (a) *a = T(0); + if (b) *b = S*D*((T)MATH_DOUBLE_PIOVER2); + if (c) *c = S*D*atan2(T(2)*(psign*Q[A1] * Q[A2] + w*Q[A3]), ww + Q22 - Q11 - Q33); + } + else + { + if (a) *a = -S*D*atan2(T(-2)*(w*Q[A1] - psign*Q[A2] * Q[A3]), ww + Q33 - Q11 - Q22); + if (b) *b = S*D*asin(s2); + if (c) *c = S*D*atan2(T(2)*(w*Q[A3] - psign*Q[A1] * Q[A2]), ww + Q11 - Q22 - Q33); + } + } + + template + void GetEulerAngles(T *a, T *b, T *c) const + { GetEulerAngles(a, b, c); } + + template + void GetEulerAngles(T *a, T *b, T *c) const + { GetEulerAngles(a, b, c); } + + // GetEulerAnglesABA extracts Euler angles from the quaternion, in the specified order of + // axis rotations and the specified coordinate system. Right-handed coordinate system + // is the default, with CCW rotations while looking in the negative axis direction. + // Here a,b,c, are the Yaw/Pitch/Roll angles to be returned. + // rotation a around axis A1 + // is followed by rotation b around axis A2 + // is followed by rotation c around axis A1 + // Rotations are CCW or CW (D) in LH or RH coordinate system (S) + template + void GetEulerAnglesABA(T *a, T *b, T *c) const + { + OVR_MATH_ASSERT(IsNormalized()); + OVR_MATH_STATIC_ASSERT(A1 != A2, "A1 != A2"); + + T Q[3] = {x, y, z}; // Quaternion components + + // Determine the missing axis that was not supplied + int m = 3 - A1 - A2; + + T ww = w*w; + T Q11 = Q[A1]*Q[A1]; + T Q22 = Q[A2]*Q[A2]; + T Qmm = Q[m]*Q[m]; + + T psign = T(-1); + if ((A1 + 1) % 3 == A2) // Determine whether even permutation + { + psign = T(1); + } + + T c2 = ww + Q11 - Q22 - Qmm; + T singularityRadius = Math::SingularityRadius(); + if (c2 < T(-1) + singularityRadius) + { // South pole singularity + if (a) *a = T(0); + if (b) *b = S*D*((T)MATH_DOUBLE_PI); + if (c) *c = S*D*atan2(T(2)*(w*Q[A1] - psign*Q[A2] * Q[m]), + ww + Q22 - Q11 - Qmm); + } + else if (c2 > T(1) - singularityRadius) + { // North pole singularity + if (a) *a = T(0); + if (b) *b = T(0); + if (c) *c = S*D*atan2(T(2)*(w*Q[A1] - psign*Q[A2] * Q[m]), + ww + Q22 - Q11 - Qmm); + } + else + { + if (a) *a = S*D*atan2(psign*w*Q[m] + Q[A1] * Q[A2], + w*Q[A2] -psign*Q[A1]*Q[m]); + if (b) *b = S*D*acos(c2); + if (c) *c = S*D*atan2(-psign*w*Q[m] + Q[A1] * Q[A2], + w*Q[A2] + psign*Q[A1]*Q[m]); + } + } +}; + +typedef Quat Quatf; +typedef Quat Quatd; + +OVR_MATH_STATIC_ASSERT((sizeof(Quatf) == 4*sizeof(float)), "sizeof(Quatf) failure"); +OVR_MATH_STATIC_ASSERT((sizeof(Quatd) == 4*sizeof(double)), "sizeof(Quatd) failure"); + +//------------------------------------------------------------------------------------- +// ***** Pose +// +// Position and orientation combined. +// +// This structure needs to be the same size and layout on 32-bit and 64-bit arch. +// Update OVR_PadCheck.cpp when updating this object. +template +class Pose +{ +public: + typedef typename CompatibleTypes >::Type CompatibleType; + + Pose() { } + Pose(const Quat& orientation, const Vector3& pos) + : Rotation(orientation), Translation(pos) { } + Pose(const Pose& s) + : Rotation(s.Rotation), Translation(s.Translation) { } + Pose(const Matrix3& R, const Vector3& t) + : Rotation((Quat)R), Translation(t) { } + Pose(const CompatibleType& s) + : Rotation(s.Orientation), Translation(s.Position) { } + + explicit Pose(const Pose::OtherFloatType> &s) + : Rotation(s.Rotation), Translation(s.Translation) + { + // Ensure normalized rotation if converting from float to double + if (sizeof(T) > sizeof(typename Math::OtherFloatType)) + Rotation.Normalize(); + } + + static Pose Identity() { return Pose(Quat(0, 0, 0, 1), Vector3(0, 0, 0)); } + + void SetIdentity() { Rotation = Quat(0, 0, 0, 1); Translation = Vector3(0, 0, 0); } + + // used to make things obviously broken if someone tries to use the value + void SetInvalid() { Rotation = Quat(NAN, NAN, NAN, NAN); Translation = Vector3(NAN, NAN, NAN); } + + bool IsEqual(const Pose&b, T tolerance = Math::Tolerance()) const + { + return Translation.IsEqual(b.Translation, tolerance) && Rotation.IsEqual(b.Rotation, tolerance); + } + + operator typename CompatibleTypes >::Type () const + { + typename CompatibleTypes >::Type result; + result.Orientation = Rotation; + result.Position = Translation; + return result; + } + + Quat Rotation; + Vector3 Translation; + + OVR_MATH_STATIC_ASSERT((sizeof(T) == sizeof(double) || sizeof(T) == sizeof(float)), "(sizeof(T) == sizeof(double) || sizeof(T) == sizeof(float))"); + + void ToArray(T* arr) const + { + T temp[7] = { Rotation.x, Rotation.y, Rotation.z, Rotation.w, Translation.x, Translation.y, Translation.z }; + for (int i = 0; i < 7; i++) arr[i] = temp[i]; + } + + static Pose FromArray(const T* v) + { + Quat rotation(v[0], v[1], v[2], v[3]); + Vector3 translation(v[4], v[5], v[6]); + // Ensure rotation is normalized, in case it was originally a float, stored in a .json file, etc. + return Pose(rotation.Normalized(), translation); + } + + Vector3 Rotate(const Vector3& v) const + { + return Rotation.Rotate(v); + } + + Vector3 InverseRotate(const Vector3& v) const + { + return Rotation.InverseRotate(v); + } + + Vector3 Translate(const Vector3& v) const + { + return v + Translation; + } + + Vector3 Transform(const Vector3& v) const + { + return Rotate(v) + Translation; + } + + Vector3 InverseTransform(const Vector3& v) const + { + return InverseRotate(v - Translation); + } + + + Vector3 Apply(const Vector3& v) const + { + return Transform(v); + } + + Pose operator*(const Pose& other) const + { + return Pose(Rotation * other.Rotation, Apply(other.Translation)); + } + + Pose Inverted() const + { + Quat inv = Rotation.Inverted(); + return Pose(inv, inv.Rotate(-Translation)); + } + + // Interpolation between two poses: translation is interpolated with Lerp(), + // and rotations are interpolated with Slerp(). + Pose Lerp(const Pose& b, T s) + { + return Pose(Rotation.Slerp(b.Rotation, s), Translation.Lerp(b.Translation, s)); + } + + // Similar to Lerp above, except faster in case of small rotation differences. See Quat::FastSlerp. + Pose FastLerp(const Pose& b, T s) + { + return Pose(Rotation.FastSlerp(b.Rotation, s), Translation.Lerp(b.Translation, s)); + } + + Pose TimeIntegrate(const Vector3& linearVelocity, const Vector3& angularVelocity, T dt) const + { + return Pose( + (Rotation * Quat::FastFromRotationVector(angularVelocity * dt, false)).Normalized(), + Translation + linearVelocity * dt); + } + + Pose TimeIntegrate(const Vector3& linearVelocity, const Vector3& linearAcceleration, + const Vector3& angularVelocity, const Vector3& angularAcceleration, + T dt) const + { + return Pose(Rotation.TimeIntegrate(angularVelocity, angularAcceleration, dt), + Translation + linearVelocity*dt + linearAcceleration*dt*dt * T(0.5)); + } +}; + +typedef Pose Posef; +typedef Pose Posed; + +OVR_MATH_STATIC_ASSERT((sizeof(Posed) == sizeof(Quatd) + sizeof(Vector3d)), "sizeof(Posed) failure"); +OVR_MATH_STATIC_ASSERT((sizeof(Posef) == sizeof(Quatf) + sizeof(Vector3f)), "sizeof(Posef) failure"); + + +//------------------------------------------------------------------------------------- +// ***** Matrix4 +// +// Matrix4 is a 4x4 matrix used for 3d transformations and projections. +// Translation stored in the last column. +// The matrix is stored in row-major order in memory, meaning that values +// of the first row are stored before the next one. +// +// The arrangement of the matrix is chosen to be in Right-Handed +// coordinate system and counterclockwise rotations when looking down +// the axis +// +// Transformation Order: +// - Transformations are applied from right to left, so the expression +// M1 * M2 * M3 * V means that the vector V is transformed by M3 first, +// followed by M2 and M1. +// +// Coordinate system: Right Handed +// +// Rotations: Counterclockwise when looking down the axis. All angles are in radians. +// +// | sx 01 02 tx | // First column (sx, 10, 20): Axis X basis vector. +// | 10 sy 12 ty | // Second column (01, sy, 21): Axis Y basis vector. +// | 20 21 sz tz | // Third columnt (02, 12, sz): Axis Z basis vector. +// | 30 31 32 33 | +// +// The basis vectors are first three columns. + +template +class Matrix4 +{ +public: + typedef T ElementType; + static const size_t Dimension = 4; + + T M[4][4]; + + enum NoInitType { NoInit }; + + // Construct with no memory initialization. + Matrix4(NoInitType) { } + + // By default, we construct identity matrix. + Matrix4() + { + M[0][0] = M[1][1] = M[2][2] = M[3][3] = T(1); + M[0][1] = M[1][0] = M[2][3] = M[3][1] = T(0); + M[0][2] = M[1][2] = M[2][0] = M[3][2] = T(0); + M[0][3] = M[1][3] = M[2][1] = M[3][0] = T(0); + } + + Matrix4(T m11, T m12, T m13, T m14, + T m21, T m22, T m23, T m24, + T m31, T m32, T m33, T m34, + T m41, T m42, T m43, T m44) + { + M[0][0] = m11; M[0][1] = m12; M[0][2] = m13; M[0][3] = m14; + M[1][0] = m21; M[1][1] = m22; M[1][2] = m23; M[1][3] = m24; + M[2][0] = m31; M[2][1] = m32; M[2][2] = m33; M[2][3] = m34; + M[3][0] = m41; M[3][1] = m42; M[3][2] = m43; M[3][3] = m44; + } + + Matrix4(T m11, T m12, T m13, + T m21, T m22, T m23, + T m31, T m32, T m33) + { + M[0][0] = m11; M[0][1] = m12; M[0][2] = m13; M[0][3] = T(0); + M[1][0] = m21; M[1][1] = m22; M[1][2] = m23; M[1][3] = T(0); + M[2][0] = m31; M[2][1] = m32; M[2][2] = m33; M[2][3] = T(0); + M[3][0] = T(0); M[3][1] = T(0); M[3][2] = T(0); M[3][3] = T(1); + } + + explicit Matrix4(const Matrix3& m) + { + M[0][0] = m.M[0][0]; M[0][1] = m.M[0][1]; M[0][2] = m.M[0][2]; M[0][3] = T(0); + M[1][0] = m.M[1][0]; M[1][1] = m.M[1][1]; M[1][2] = m.M[1][2]; M[1][3] = T(0); + M[2][0] = m.M[2][0]; M[2][1] = m.M[2][1]; M[2][2] = m.M[2][2]; M[2][3] = T(0); + M[3][0] = T(0); M[3][1] = T(0); M[3][2] = T(0); M[3][3] = T(1); + } + + explicit Matrix4(const Quat& q) + { + OVR_MATH_ASSERT(q.IsNormalized()); + T ww = q.w*q.w; + T xx = q.x*q.x; + T yy = q.y*q.y; + T zz = q.z*q.z; + + M[0][0] = ww + xx - yy - zz; M[0][1] = 2 * (q.x*q.y - q.w*q.z); M[0][2] = 2 * (q.x*q.z + q.w*q.y); M[0][3] = T(0); + M[1][0] = 2 * (q.x*q.y + q.w*q.z); M[1][1] = ww - xx + yy - zz; M[1][2] = 2 * (q.y*q.z - q.w*q.x); M[1][3] = T(0); + M[2][0] = 2 * (q.x*q.z - q.w*q.y); M[2][1] = 2 * (q.y*q.z + q.w*q.x); M[2][2] = ww - xx - yy + zz; M[2][3] = T(0); + M[3][0] = T(0); M[3][1] = T(0); M[3][2] = T(0); M[3][3] = T(1); + } + + explicit Matrix4(const Pose& p) + { + Matrix4 result(p.Rotation); + result.SetTranslation(p.Translation); + *this = result; + } + + + // C-interop support + explicit Matrix4(const Matrix4::OtherFloatType> &src) + { + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + M[i][j] = (T)src.M[i][j]; + } + + // C-interop support. + Matrix4(const typename CompatibleTypes >::Type& s) + { + OVR_MATH_STATIC_ASSERT(sizeof(s) == sizeof(Matrix4), "sizeof(s) == sizeof(Matrix4)"); + memcpy(M, s.M, sizeof(M)); + } + + operator typename CompatibleTypes >::Type () const + { + typename CompatibleTypes >::Type result; + OVR_MATH_STATIC_ASSERT(sizeof(result) == sizeof(Matrix4), "sizeof(result) == sizeof(Matrix4)"); + memcpy(result.M, M, sizeof(M)); + return result; + } + + void ToString(char* dest, size_t destsize) const + { + size_t pos = 0; + for (int r=0; r<4; r++) + { + for (int c=0; c<4; c++) + { + pos += OVRMath_sprintf(dest+pos, destsize-pos, "%g ", M[r][c]); + } + } + } + + static Matrix4 FromString(const char* src) + { + Matrix4 result; + if (src) + { + for (int r = 0; r < 4; r++) + { + for (int c = 0; c < 4; c++) + { + result.M[r][c] = (T)atof(src); + while (*src && *src != ' ') + { + src++; + } + while (*src && *src == ' ') + { + src++; + } + } + } + } + return result; + } + + static Matrix4 Identity() { return Matrix4(); } + + void SetIdentity() + { + M[0][0] = M[1][1] = M[2][2] = M[3][3] = T(1); + M[0][1] = M[1][0] = M[2][3] = M[3][1] = T(0); + M[0][2] = M[1][2] = M[2][0] = M[3][2] = T(0); + M[0][3] = M[1][3] = M[2][1] = M[3][0] = T(0); + } + + void SetXBasis(const Vector3& v) + { + M[0][0] = v.x; + M[1][0] = v.y; + M[2][0] = v.z; + } + Vector3 GetXBasis() const + { + return Vector3(M[0][0], M[1][0], M[2][0]); + } + + void SetYBasis(const Vector3 & v) + { + M[0][1] = v.x; + M[1][1] = v.y; + M[2][1] = v.z; + } + Vector3 GetYBasis() const + { + return Vector3(M[0][1], M[1][1], M[2][1]); + } + + void SetZBasis(const Vector3 & v) + { + M[0][2] = v.x; + M[1][2] = v.y; + M[2][2] = v.z; + } + Vector3 GetZBasis() const + { + return Vector3(M[0][2], M[1][2], M[2][2]); + } + + bool operator== (const Matrix4& b) const + { + bool isEqual = true; + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + isEqual &= (M[i][j] == b.M[i][j]); + + return isEqual; + } + + Matrix4 operator+ (const Matrix4& b) const + { + Matrix4 result(*this); + result += b; + return result; + } + + Matrix4& operator+= (const Matrix4& b) + { + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + M[i][j] += b.M[i][j]; + return *this; + } + + Matrix4 operator- (const Matrix4& b) const + { + Matrix4 result(*this); + result -= b; + return result; + } + + Matrix4& operator-= (const Matrix4& b) + { + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + M[i][j] -= b.M[i][j]; + return *this; + } + + // Multiplies two matrices into destination with minimum copying. + static Matrix4& Multiply(Matrix4* d, const Matrix4& a, const Matrix4& b) + { + OVR_MATH_ASSERT((d != &a) && (d != &b)); + int i = 0; + do { + d->M[i][0] = a.M[i][0] * b.M[0][0] + a.M[i][1] * b.M[1][0] + a.M[i][2] * b.M[2][0] + a.M[i][3] * b.M[3][0]; + d->M[i][1] = a.M[i][0] * b.M[0][1] + a.M[i][1] * b.M[1][1] + a.M[i][2] * b.M[2][1] + a.M[i][3] * b.M[3][1]; + d->M[i][2] = a.M[i][0] * b.M[0][2] + a.M[i][1] * b.M[1][2] + a.M[i][2] * b.M[2][2] + a.M[i][3] * b.M[3][2]; + d->M[i][3] = a.M[i][0] * b.M[0][3] + a.M[i][1] * b.M[1][3] + a.M[i][2] * b.M[2][3] + a.M[i][3] * b.M[3][3]; + } while((++i) < 4); + + return *d; + } + + Matrix4 operator* (const Matrix4& b) const + { + Matrix4 result(Matrix4::NoInit); + Multiply(&result, *this, b); + return result; + } + + Matrix4& operator*= (const Matrix4& b) + { + return Multiply(this, Matrix4(*this), b); + } + + Matrix4 operator* (T s) const + { + Matrix4 result(*this); + result *= s; + return result; + } + + Matrix4& operator*= (T s) + { + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + M[i][j] *= s; + return *this; + } + + + Matrix4 operator/ (T s) const + { + Matrix4 result(*this); + result /= s; + return result; + } + + Matrix4& operator/= (T s) + { + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + M[i][j] /= s; + return *this; + } + + Vector3 Transform(const Vector3& v) const + { + const T rcpW = T(1) / (M[3][0] * v.x + M[3][1] * v.y + M[3][2] * v.z + M[3][3]); + return Vector3((M[0][0] * v.x + M[0][1] * v.y + M[0][2] * v.z + M[0][3]) * rcpW, + (M[1][0] * v.x + M[1][1] * v.y + M[1][2] * v.z + M[1][3]) * rcpW, + (M[2][0] * v.x + M[2][1] * v.y + M[2][2] * v.z + M[2][3]) * rcpW); + } + + Vector4 Transform(const Vector4& v) const + { + return Vector4(M[0][0] * v.x + M[0][1] * v.y + M[0][2] * v.z + M[0][3] * v.w, + M[1][0] * v.x + M[1][1] * v.y + M[1][2] * v.z + M[1][3] * v.w, + M[2][0] * v.x + M[2][1] * v.y + M[2][2] * v.z + M[2][3] * v.w, + M[3][0] * v.x + M[3][1] * v.y + M[3][2] * v.z + M[3][3] * v.w); + } + + Matrix4 Transposed() const + { + return Matrix4(M[0][0], M[1][0], M[2][0], M[3][0], + M[0][1], M[1][1], M[2][1], M[3][1], + M[0][2], M[1][2], M[2][2], M[3][2], + M[0][3], M[1][3], M[2][3], M[3][3]); + } + + void Transpose() + { + *this = Transposed(); + } + + + T SubDet (const size_t* rows, const size_t* cols) const + { + return M[rows[0]][cols[0]] * (M[rows[1]][cols[1]] * M[rows[2]][cols[2]] - M[rows[1]][cols[2]] * M[rows[2]][cols[1]]) + - M[rows[0]][cols[1]] * (M[rows[1]][cols[0]] * M[rows[2]][cols[2]] - M[rows[1]][cols[2]] * M[rows[2]][cols[0]]) + + M[rows[0]][cols[2]] * (M[rows[1]][cols[0]] * M[rows[2]][cols[1]] - M[rows[1]][cols[1]] * M[rows[2]][cols[0]]); + } + + T Cofactor(size_t I, size_t J) const + { + const size_t indices[4][3] = {{1,2,3},{0,2,3},{0,1,3},{0,1,2}}; + return ((I+J)&1) ? -SubDet(indices[I],indices[J]) : SubDet(indices[I],indices[J]); + } + + T Determinant() const + { + return M[0][0] * Cofactor(0,0) + M[0][1] * Cofactor(0,1) + M[0][2] * Cofactor(0,2) + M[0][3] * Cofactor(0,3); + } + + Matrix4 Adjugated() const + { + return Matrix4(Cofactor(0,0), Cofactor(1,0), Cofactor(2,0), Cofactor(3,0), + Cofactor(0,1), Cofactor(1,1), Cofactor(2,1), Cofactor(3,1), + Cofactor(0,2), Cofactor(1,2), Cofactor(2,2), Cofactor(3,2), + Cofactor(0,3), Cofactor(1,3), Cofactor(2,3), Cofactor(3,3)); + } + + Matrix4 Inverted() const + { + T det = Determinant(); + OVR_MATH_ASSERT(det != 0); + return Adjugated() * (T(1)/det); + } + + void Invert() + { + *this = Inverted(); + } + + // This is more efficient than general inverse, but ONLY works + // correctly if it is a homogeneous transform matrix (rot + trans) + Matrix4 InvertedHomogeneousTransform() const + { + // Make the inverse rotation matrix + Matrix4 rinv = this->Transposed(); + rinv.M[3][0] = rinv.M[3][1] = rinv.M[3][2] = T(0); + // Make the inverse translation matrix + Vector3 tvinv(-M[0][3],-M[1][3],-M[2][3]); + Matrix4 tinv = Matrix4::Translation(tvinv); + return rinv * tinv; // "untranslate", then "unrotate" + } + + // This is more efficient than general inverse, but ONLY works + // correctly if it is a homogeneous transform matrix (rot + trans) + void InvertHomogeneousTransform() + { + *this = InvertedHomogeneousTransform(); + } + + // Matrix to Euler Angles conversion + // a,b,c, are the YawPitchRoll angles to be returned + // rotation a around axis A1 + // is followed by rotation b around axis A2 + // is followed by rotation c around axis A3 + // rotations are CCW or CW (D) in LH or RH coordinate system (S) + template + void ToEulerAngles(T *a, T *b, T *c) const + { + OVR_MATH_STATIC_ASSERT((A1 != A2) && (A2 != A3) && (A1 != A3), "(A1 != A2) && (A2 != A3) && (A1 != A3)"); + + T psign = T(-1); + if (((A1 + 1) % 3 == A2) && ((A2 + 1) % 3 == A3)) // Determine whether even permutation + psign = T(1); + + T pm = psign*M[A1][A3]; + T singularityRadius = Math::SingularityRadius(); + if (pm < T(-1) + singularityRadius) + { // South pole singularity + *a = T(0); + *b = -S*D*((T)MATH_DOUBLE_PIOVER2); + *c = S*D*atan2( psign*M[A2][A1], M[A2][A2] ); + } + else if (pm > T(1) - singularityRadius) + { // North pole singularity + *a = T(0); + *b = S*D*((T)MATH_DOUBLE_PIOVER2); + *c = S*D*atan2( psign*M[A2][A1], M[A2][A2] ); + } + else + { // Normal case (nonsingular) + *a = S*D*atan2( -psign*M[A2][A3], M[A3][A3] ); + *b = S*D*asin(pm); + *c = S*D*atan2( -psign*M[A1][A2], M[A1][A1] ); + } + } + + // Matrix to Euler Angles conversion + // a,b,c, are the YawPitchRoll angles to be returned + // rotation a around axis A1 + // is followed by rotation b around axis A2 + // is followed by rotation c around axis A1 + // rotations are CCW or CW (D) in LH or RH coordinate system (S) + template + void ToEulerAnglesABA(T *a, T *b, T *c) const + { + OVR_MATH_STATIC_ASSERT(A1 != A2, "A1 != A2"); + + // Determine the axis that was not supplied + int m = 3 - A1 - A2; + + T psign = T(-1); + if ((A1 + 1) % 3 == A2) // Determine whether even permutation + psign = T(1); + + T c2 = M[A1][A1]; + T singularityRadius = Math::SingularityRadius(); + if (c2 < T(-1) + singularityRadius) + { // South pole singularity + *a = T(0); + *b = S*D*((T)MATH_DOUBLE_PI); + *c = S*D*atan2( -psign*M[A2][m],M[A2][A2]); + } + else if (c2 > T(1) - singularityRadius) + { // North pole singularity + *a = T(0); + *b = T(0); + *c = S*D*atan2( -psign*M[A2][m],M[A2][A2]); + } + else + { // Normal case (nonsingular) + *a = S*D*atan2( M[A2][A1],-psign*M[m][A1]); + *b = S*D*acos(c2); + *c = S*D*atan2( M[A1][A2],psign*M[A1][m]); + } + } + + // Creates a matrix that converts the vertices from one coordinate system + // to another. + static Matrix4 AxisConversion(const WorldAxes& to, const WorldAxes& from) + { + // Holds axis values from the 'to' structure + int toArray[3] = { to.XAxis, to.YAxis, to.ZAxis }; + + // The inverse of the toArray + int inv[4]; + inv[0] = inv[abs(to.XAxis)] = 0; + inv[abs(to.YAxis)] = 1; + inv[abs(to.ZAxis)] = 2; + + Matrix4 m(0, 0, 0, + 0, 0, 0, + 0, 0, 0); + + // Only three values in the matrix need to be changed to 1 or -1. + m.M[inv[abs(from.XAxis)]][0] = T(from.XAxis/toArray[inv[abs(from.XAxis)]]); + m.M[inv[abs(from.YAxis)]][1] = T(from.YAxis/toArray[inv[abs(from.YAxis)]]); + m.M[inv[abs(from.ZAxis)]][2] = T(from.ZAxis/toArray[inv[abs(from.ZAxis)]]); + return m; + } + + + // Creates a matrix for translation by vector + static Matrix4 Translation(const Vector3& v) + { + Matrix4 t; + t.M[0][3] = v.x; + t.M[1][3] = v.y; + t.M[2][3] = v.z; + return t; + } + + // Creates a matrix for translation by vector + static Matrix4 Translation(T x, T y, T z = T(0)) + { + Matrix4 t; + t.M[0][3] = x; + t.M[1][3] = y; + t.M[2][3] = z; + return t; + } + + // Sets the translation part + void SetTranslation(const Vector3& v) + { + M[0][3] = v.x; + M[1][3] = v.y; + M[2][3] = v.z; + } + + Vector3 GetTranslation() const + { + return Vector3( M[0][3], M[1][3], M[2][3] ); + } + + // Creates a matrix for scaling by vector + static Matrix4 Scaling(const Vector3& v) + { + Matrix4 t; + t.M[0][0] = v.x; + t.M[1][1] = v.y; + t.M[2][2] = v.z; + return t; + } + + // Creates a matrix for scaling by vector + static Matrix4 Scaling(T x, T y, T z) + { + Matrix4 t; + t.M[0][0] = x; + t.M[1][1] = y; + t.M[2][2] = z; + return t; + } + + // Creates a matrix for scaling by constant + static Matrix4 Scaling(T s) + { + Matrix4 t; + t.M[0][0] = s; + t.M[1][1] = s; + t.M[2][2] = s; + return t; + } + + // Simple L1 distance in R^12 + T Distance(const Matrix4& m2) const + { + T d = fabs(M[0][0] - m2.M[0][0]) + fabs(M[0][1] - m2.M[0][1]); + d += fabs(M[0][2] - m2.M[0][2]) + fabs(M[0][3] - m2.M[0][3]); + d += fabs(M[1][0] - m2.M[1][0]) + fabs(M[1][1] - m2.M[1][1]); + d += fabs(M[1][2] - m2.M[1][2]) + fabs(M[1][3] - m2.M[1][3]); + d += fabs(M[2][0] - m2.M[2][0]) + fabs(M[2][1] - m2.M[2][1]); + d += fabs(M[2][2] - m2.M[2][2]) + fabs(M[2][3] - m2.M[2][3]); + d += fabs(M[3][0] - m2.M[3][0]) + fabs(M[3][1] - m2.M[3][1]); + d += fabs(M[3][2] - m2.M[3][2]) + fabs(M[3][3] - m2.M[3][3]); + return d; + } + + // Creates a rotation matrix rotating around the X axis by 'angle' radians. + // Just for quick testing. Not for final API. Need to remove case. + static Matrix4 RotationAxis(Axis A, T angle, RotateDirection d, HandedSystem s) + { + T sina = s * d *sin(angle); + T cosa = cos(angle); + + switch(A) + { + case Axis_X: + return Matrix4(1, 0, 0, + 0, cosa, -sina, + 0, sina, cosa); + case Axis_Y: + return Matrix4(cosa, 0, sina, + 0, 1, 0, + -sina, 0, cosa); + case Axis_Z: + return Matrix4(cosa, -sina, 0, + sina, cosa, 0, + 0, 0, 1); + default: + return Matrix4(); + } + } + + + // Creates a rotation matrix rotating around the X axis by 'angle' radians. + // Rotation direction is depends on the coordinate system: + // RHS (Oculus default): Positive angle values rotate Counter-clockwise (CCW), + // while looking in the negative axis direction. This is the + // same as looking down from positive axis values towards origin. + // LHS: Positive angle values rotate clock-wise (CW), while looking in the + // negative axis direction. + static Matrix4 RotationX(T angle) + { + T sina = sin(angle); + T cosa = cos(angle); + return Matrix4(1, 0, 0, + 0, cosa, -sina, + 0, sina, cosa); + } + + // Creates a rotation matrix rotating around the Y axis by 'angle' radians. + // Rotation direction is depends on the coordinate system: + // RHS (Oculus default): Positive angle values rotate Counter-clockwise (CCW), + // while looking in the negative axis direction. This is the + // same as looking down from positive axis values towards origin. + // LHS: Positive angle values rotate clock-wise (CW), while looking in the + // negative axis direction. + static Matrix4 RotationY(T angle) + { + T sina = (T)sin(angle); + T cosa = (T)cos(angle); + return Matrix4(cosa, 0, sina, + 0, 1, 0, + -sina, 0, cosa); + } + + // Creates a rotation matrix rotating around the Z axis by 'angle' radians. + // Rotation direction is depends on the coordinate system: + // RHS (Oculus default): Positive angle values rotate Counter-clockwise (CCW), + // while looking in the negative axis direction. This is the + // same as looking down from positive axis values towards origin. + // LHS: Positive angle values rotate clock-wise (CW), while looking in the + // negative axis direction. + static Matrix4 RotationZ(T angle) + { + T sina = sin(angle); + T cosa = cos(angle); + return Matrix4(cosa, -sina, 0, + sina, cosa, 0, + 0, 0, 1); + } + + // LookAtRH creates a View transformation matrix for right-handed coordinate system. + // The resulting matrix points camera from 'eye' towards 'at' direction, with 'up' + // specifying the up vector. The resulting matrix should be used with PerspectiveRH + // projection. + static Matrix4 LookAtRH(const Vector3& eye, const Vector3& at, const Vector3& up) + { + Vector3 z = (eye - at).Normalized(); // Forward + Vector3 x = up.Cross(z).Normalized(); // Right + Vector3 y = z.Cross(x); + + Matrix4 m(x.x, x.y, x.z, -(x.Dot(eye)), + y.x, y.y, y.z, -(y.Dot(eye)), + z.x, z.y, z.z, -(z.Dot(eye)), + 0, 0, 0, 1 ); + return m; + } + + // LookAtLH creates a View transformation matrix for left-handed coordinate system. + // The resulting matrix points camera from 'eye' towards 'at' direction, with 'up' + // specifying the up vector. + static Matrix4 LookAtLH(const Vector3& eye, const Vector3& at, const Vector3& up) + { + Vector3 z = (at - eye).Normalized(); // Forward + Vector3 x = up.Cross(z).Normalized(); // Right + Vector3 y = z.Cross(x); + + Matrix4 m(x.x, x.y, x.z, -(x.Dot(eye)), + y.x, y.y, y.z, -(y.Dot(eye)), + z.x, z.y, z.z, -(z.Dot(eye)), + 0, 0, 0, 1 ); + return m; + } + + // PerspectiveRH creates a right-handed perspective projection matrix that can be + // used with the Oculus sample renderer. + // yfov - Specifies vertical field of view in radians. + // aspect - Screen aspect ration, which is usually width/height for square pixels. + // Note that xfov = yfov * aspect. + // znear - Absolute value of near Z clipping clipping range. + // zfar - Absolute value of far Z clipping clipping range (larger then near). + // Even though RHS usually looks in the direction of negative Z, positive values + // are expected for znear and zfar. + static Matrix4 PerspectiveRH(T yfov, T aspect, T znear, T zfar) + { + Matrix4 m; + T tanHalfFov = tan(yfov * T(0.5)); + + m.M[0][0] = T(1) / (aspect * tanHalfFov); + m.M[1][1] = T(1) / tanHalfFov; + m.M[2][2] = zfar / (znear - zfar); + m.M[3][2] = T(-1); + m.M[2][3] = (zfar * znear) / (znear - zfar); + m.M[3][3] = T(0); + + // Note: Post-projection matrix result assumes Left-Handed coordinate system, + // with Y up, X right and Z forward. This supports positive z-buffer values. + // This is the case even for RHS coordinate input. + return m; + } + + // PerspectiveLH creates a left-handed perspective projection matrix that can be + // used with the Oculus sample renderer. + // yfov - Specifies vertical field of view in radians. + // aspect - Screen aspect ration, which is usually width/height for square pixels. + // Note that xfov = yfov * aspect. + // znear - Absolute value of near Z clipping clipping range. + // zfar - Absolute value of far Z clipping clipping range (larger then near). + static Matrix4 PerspectiveLH(T yfov, T aspect, T znear, T zfar) + { + Matrix4 m; + T tanHalfFov = tan(yfov * T(0.5)); + + m.M[0][0] = T(1) / (aspect * tanHalfFov); + m.M[1][1] = T(1) / tanHalfFov; + //m.M[2][2] = zfar / (znear - zfar); + m.M[2][2] = zfar / (zfar - znear); + m.M[3][2] = T(-1); + m.M[2][3] = (zfar * znear) / (znear - zfar); + m.M[3][3] = T(0); + + // Note: Post-projection matrix result assumes Left-Handed coordinate system, + // with Y up, X right and Z forward. This supports positive z-buffer values. + // This is the case even for RHS coordinate input. + return m; + } + + static Matrix4 Ortho2D(T w, T h) + { + Matrix4 m; + m.M[0][0] = T(2.0)/w; + m.M[1][1] = T(-2.0)/h; + m.M[0][3] = T(-1.0); + m.M[1][3] = T(1.0); + m.M[2][2] = T(0); + return m; + } +}; + +typedef Matrix4 Matrix4f; +typedef Matrix4 Matrix4d; + +//------------------------------------------------------------------------------------- +// ***** Matrix3 +// +// Matrix3 is a 3x3 matrix used for representing a rotation matrix. +// The matrix is stored in row-major order in memory, meaning that values +// of the first row are stored before the next one. +// +// The arrangement of the matrix is chosen to be in Right-Handed +// coordinate system and counterclockwise rotations when looking down +// the axis +// +// Transformation Order: +// - Transformations are applied from right to left, so the expression +// M1 * M2 * M3 * V means that the vector V is transformed by M3 first, +// followed by M2 and M1. +// +// Coordinate system: Right Handed +// +// Rotations: Counterclockwise when looking down the axis. All angles are in radians. + +template +class Matrix3 +{ +public: + typedef T ElementType; + static const size_t Dimension = 3; + + T M[3][3]; + + enum NoInitType { NoInit }; + + // Construct with no memory initialization. + Matrix3(NoInitType) { } + + // By default, we construct identity matrix. + Matrix3() + { + M[0][0] = M[1][1] = M[2][2] = T(1); + M[0][1] = M[1][0] = M[2][0] = T(0); + M[0][2] = M[1][2] = M[2][1] = T(0); + } + + Matrix3(T m11, T m12, T m13, + T m21, T m22, T m23, + T m31, T m32, T m33) + { + M[0][0] = m11; M[0][1] = m12; M[0][2] = m13; + M[1][0] = m21; M[1][1] = m22; M[1][2] = m23; + M[2][0] = m31; M[2][1] = m32; M[2][2] = m33; + } + + // Construction from X, Y, Z basis vectors + Matrix3(const Vector3& xBasis, const Vector3& yBasis, const Vector3& zBasis) + { + M[0][0] = xBasis.x; M[0][1] = yBasis.x; M[0][2] = zBasis.x; + M[1][0] = xBasis.y; M[1][1] = yBasis.y; M[1][2] = zBasis.y; + M[2][0] = xBasis.z; M[2][1] = yBasis.z; M[2][2] = zBasis.z; + } + + explicit Matrix3(const Quat& q) + { + OVR_MATH_ASSERT(q.IsNormalized()); + const T tx = q.x+q.x, ty = q.y+q.y, tz = q.z+q.z; + const T twx = q.w*tx, twy = q.w*ty, twz = q.w*tz; + const T txx = q.x*tx, txy = q.x*ty, txz = q.x*tz; + const T tyy = q.y*ty, tyz = q.y*tz, tzz = q.z*tz; + M[0][0] = T(1) - (tyy + tzz); M[0][1] = txy - twz; M[0][2] = txz + twy; + M[1][0] = txy + twz; M[1][1] = T(1) - (txx + tzz); M[1][2] = tyz - twx; + M[2][0] = txz - twy; M[2][1] = tyz + twx; M[2][2] = T(1) - (txx + tyy); + } + + inline explicit Matrix3(T s) + { + M[0][0] = M[1][1] = M[2][2] = s; + M[0][1] = M[0][2] = M[1][0] = M[1][2] = M[2][0] = M[2][1] = T(0); + } + + Matrix3(T m11, T m22, T m33) + { + M[0][0] = m11; M[0][1] = T(0); M[0][2] = T(0); + M[1][0] = T(0); M[1][1] = m22; M[1][2] = T(0); + M[2][0] = T(0); M[2][1] = T(0); M[2][2] = m33; + } + + explicit Matrix3(const Matrix3::OtherFloatType> &src) + { + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + M[i][j] = (T)src.M[i][j]; + } + + // C-interop support. + Matrix3(const typename CompatibleTypes >::Type& s) + { + OVR_MATH_STATIC_ASSERT(sizeof(s) == sizeof(Matrix3), "sizeof(s) == sizeof(Matrix3)"); + memcpy(M, s.M, sizeof(M)); + } + + operator const typename CompatibleTypes >::Type () const + { + typename CompatibleTypes >::Type result; + OVR_MATH_STATIC_ASSERT(sizeof(result) == sizeof(Matrix3), "sizeof(result) == sizeof(Matrix3)"); + memcpy(result.M, M, sizeof(M)); + return result; + } + + T operator()(int i, int j) const { return M[i][j]; } + T& operator()(int i, int j) { return M[i][j]; } + + void ToString(char* dest, size_t destsize) const + { + size_t pos = 0; + for (int r=0; r<3; r++) + { + for (int c=0; c<3; c++) + pos += OVRMath_sprintf(dest+pos, destsize-pos, "%g ", M[r][c]); + } + } + + static Matrix3 FromString(const char* src) + { + Matrix3 result; + if (src) + { + for (int r=0; r<3; r++) + { + for (int c=0; c<3; c++) + { + result.M[r][c] = (T)atof(src); + while (*src && *src != ' ') + src++; + while (*src && *src == ' ') + src++; + } + } + } + return result; + } + + static Matrix3 Identity() { return Matrix3(); } + + void SetIdentity() + { + M[0][0] = M[1][1] = M[2][2] = T(1); + M[0][1] = M[1][0] = M[2][0] = T(0); + M[0][2] = M[1][2] = M[2][1] = T(0); + } + + static Matrix3 Diagonal(T m00, T m11, T m22) + { + return Matrix3(m00, 0, 0, + 0, m11, 0, + 0, 0, m22); + } + static Matrix3 Diagonal(const Vector3& v) { return Diagonal(v.x, v.y, v.z); } + + T Trace() const { return M[0][0] + M[1][1] + M[2][2]; } + + bool operator== (const Matrix3& b) const + { + bool isEqual = true; + for (int i = 0; i < 3; i++) + { + for (int j = 0; j < 3; j++) + isEqual &= (M[i][j] == b.M[i][j]); + } + + return isEqual; + } + + Matrix3 operator+ (const Matrix3& b) const + { + Matrix3 result(*this); + result += b; + return result; + } + + Matrix3& operator+= (const Matrix3& b) + { + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + M[i][j] += b.M[i][j]; + return *this; + } + + void operator= (const Matrix3& b) + { + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + M[i][j] = b.M[i][j]; + } + + Matrix3 operator- (const Matrix3& b) const + { + Matrix3 result(*this); + result -= b; + return result; + } + + Matrix3& operator-= (const Matrix3& b) + { + for (int i = 0; i < 3; i++) + { + for (int j = 0; j < 3; j++) + M[i][j] -= b.M[i][j]; + } + + return *this; + } + + // Multiplies two matrices into destination with minimum copying. + static Matrix3& Multiply(Matrix3* d, const Matrix3& a, const Matrix3& b) + { + OVR_MATH_ASSERT((d != &a) && (d != &b)); + int i = 0; + do { + d->M[i][0] = a.M[i][0] * b.M[0][0] + a.M[i][1] * b.M[1][0] + a.M[i][2] * b.M[2][0]; + d->M[i][1] = a.M[i][0] * b.M[0][1] + a.M[i][1] * b.M[1][1] + a.M[i][2] * b.M[2][1]; + d->M[i][2] = a.M[i][0] * b.M[0][2] + a.M[i][1] * b.M[1][2] + a.M[i][2] * b.M[2][2]; + } while((++i) < 3); + + return *d; + } + + Matrix3 operator* (const Matrix3& b) const + { + Matrix3 result(Matrix3::NoInit); + Multiply(&result, *this, b); + return result; + } + + Matrix3& operator*= (const Matrix3& b) + { + return Multiply(this, Matrix3(*this), b); + } + + Matrix3 operator* (T s) const + { + Matrix3 result(*this); + result *= s; + return result; + } + + Matrix3& operator*= (T s) + { + for (int i = 0; i < 3; i++) + { + for (int j = 0; j < 3; j++) + M[i][j] *= s; + } + + return *this; + } + + Vector3 operator* (const Vector3 &b) const + { + Vector3 result; + result.x = M[0][0]*b.x + M[0][1]*b.y + M[0][2]*b.z; + result.y = M[1][0]*b.x + M[1][1]*b.y + M[1][2]*b.z; + result.z = M[2][0]*b.x + M[2][1]*b.y + M[2][2]*b.z; + + return result; + } + + Matrix3 operator/ (T s) const + { + Matrix3 result(*this); + result /= s; + return result; + } + + Matrix3& operator/= (T s) + { + for (int i = 0; i < 3; i++) + { + for (int j = 0; j < 3; j++) + M[i][j] /= s; + } + + return *this; + } + + Vector2 Transform(const Vector2& v) const + { + const T rcpZ = T(1) / (M[2][0] * v.x + M[2][1] * v.y + M[2][2]); + return Vector2((M[0][0] * v.x + M[0][1] * v.y + M[0][2]) * rcpZ, + (M[1][0] * v.x + M[1][1] * v.y + M[1][2]) * rcpZ); + } + + Vector3 Transform(const Vector3& v) const + { + return Vector3(M[0][0] * v.x + M[0][1] * v.y + M[0][2] * v.z, + M[1][0] * v.x + M[1][1] * v.y + M[1][2] * v.z, + M[2][0] * v.x + M[2][1] * v.y + M[2][2] * v.z); + } + + Matrix3 Transposed() const + { + return Matrix3(M[0][0], M[1][0], M[2][0], + M[0][1], M[1][1], M[2][1], + M[0][2], M[1][2], M[2][2]); + } + + void Transpose() + { + *this = Transposed(); + } + + + T SubDet (const size_t* rows, const size_t* cols) const + { + return M[rows[0]][cols[0]] * (M[rows[1]][cols[1]] * M[rows[2]][cols[2]] - M[rows[1]][cols[2]] * M[rows[2]][cols[1]]) + - M[rows[0]][cols[1]] * (M[rows[1]][cols[0]] * M[rows[2]][cols[2]] - M[rows[1]][cols[2]] * M[rows[2]][cols[0]]) + + M[rows[0]][cols[2]] * (M[rows[1]][cols[0]] * M[rows[2]][cols[1]] - M[rows[1]][cols[1]] * M[rows[2]][cols[0]]); + } + + + // M += a*b.t() + inline void Rank1Add(const Vector3 &a, const Vector3 &b) + { + M[0][0] += a.x*b.x; M[0][1] += a.x*b.y; M[0][2] += a.x*b.z; + M[1][0] += a.y*b.x; M[1][1] += a.y*b.y; M[1][2] += a.y*b.z; + M[2][0] += a.z*b.x; M[2][1] += a.z*b.y; M[2][2] += a.z*b.z; + } + + // M -= a*b.t() + inline void Rank1Sub(const Vector3 &a, const Vector3 &b) + { + M[0][0] -= a.x*b.x; M[0][1] -= a.x*b.y; M[0][2] -= a.x*b.z; + M[1][0] -= a.y*b.x; M[1][1] -= a.y*b.y; M[1][2] -= a.y*b.z; + M[2][0] -= a.z*b.x; M[2][1] -= a.z*b.y; M[2][2] -= a.z*b.z; + } + + inline Vector3 Col(int c) const + { + return Vector3(M[0][c], M[1][c], M[2][c]); + } + + inline Vector3 Row(int r) const + { + return Vector3(M[r][0], M[r][1], M[r][2]); + } + + inline Vector3 GetColumn(int c) const + { + return Vector3(M[0][c], M[1][c], M[2][c]); + } + + inline Vector3 GetRow(int r) const + { + return Vector3(M[r][0], M[r][1], M[r][2]); + } + + inline void SetColumn(int c, const Vector3& v) + { + M[0][c] = v.x; + M[1][c] = v.y; + M[2][c] = v.z; + } + + inline void SetRow(int r, const Vector3& v) + { + M[r][0] = v.x; + M[r][1] = v.y; + M[r][2] = v.z; + } + + inline T Determinant() const + { + const Matrix3& m = *this; + T d; + + d = m.M[0][0] * (m.M[1][1]*m.M[2][2] - m.M[1][2] * m.M[2][1]); + d -= m.M[0][1] * (m.M[1][0]*m.M[2][2] - m.M[1][2] * m.M[2][0]); + d += m.M[0][2] * (m.M[1][0]*m.M[2][1] - m.M[1][1] * m.M[2][0]); + + return d; + } + + inline Matrix3 Inverse() const + { + Matrix3 a; + const Matrix3& m = *this; + T d = Determinant(); + + OVR_MATH_ASSERT(d != 0); + T s = T(1)/d; + + a.M[0][0] = s * (m.M[1][1] * m.M[2][2] - m.M[1][2] * m.M[2][1]); + a.M[1][0] = s * (m.M[1][2] * m.M[2][0] - m.M[1][0] * m.M[2][2]); + a.M[2][0] = s * (m.M[1][0] * m.M[2][1] - m.M[1][1] * m.M[2][0]); + + a.M[0][1] = s * (m.M[0][2] * m.M[2][1] - m.M[0][1] * m.M[2][2]); + a.M[1][1] = s * (m.M[0][0] * m.M[2][2] - m.M[0][2] * m.M[2][0]); + a.M[2][1] = s * (m.M[0][1] * m.M[2][0] - m.M[0][0] * m.M[2][1]); + + a.M[0][2] = s * (m.M[0][1] * m.M[1][2] - m.M[0][2] * m.M[1][1]); + a.M[1][2] = s * (m.M[0][2] * m.M[1][0] - m.M[0][0] * m.M[1][2]); + a.M[2][2] = s * (m.M[0][0] * m.M[1][1] - m.M[0][1] * m.M[1][0]); + + return a; + } + + // Outer Product of two column vectors: a * b.Transpose() + static Matrix3 OuterProduct(const Vector3& a, const Vector3& b) + { + return Matrix3(a.x*b.x, a.x*b.y, a.x*b.z, + a.y*b.x, a.y*b.y, a.y*b.z, + a.z*b.x, a.z*b.y, a.z*b.z); + } + + // Vector cross product as a premultiply matrix: + // L.Cross(R) = LeftCrossAsMatrix(L) * R + static Matrix3 LeftCrossAsMatrix(const Vector3& L) + { + return Matrix3( + T(0), -L.z, +L.y, + +L.z, T(0), -L.x, + -L.y, +L.x, T(0)); + } + + // Vector cross product as a premultiply matrix: + // L.Cross(R) = RightCrossAsMatrix(R) * L + static Matrix3 RightCrossAsMatrix(const Vector3& R) + { + return Matrix3( + T(0), +R.z, -R.y, + -R.z, T(0), +R.x, + +R.y, -R.x, T(0)); + } + + // Angle in radians of a rotation matrix + // Uses identity trace(a) = 2*cos(theta) + 1 + T Angle() const + { + return Acos((Trace() - T(1)) * T(0.5)); + } + + // Angle in radians between two rotation matrices + T Angle(const Matrix3& b) const + { + // Compute trace of (this->Transposed() * b) + // This works out to sum of products of elements. + T trace = T(0); + for (int i = 0; i < 3; i++) + { + for (int j = 0; j < 3; j++) + { + trace += M[i][j] * b.M[i][j]; + } + } + return Acos((trace - T(1)) * T(0.5)); + } +}; + +typedef Matrix3 Matrix3f; +typedef Matrix3 Matrix3d; + +//------------------------------------------------------------------------------------- +// ***** Matrix2 + +template +class Matrix2 +{ +public: + typedef T ElementType; + static const size_t Dimension = 2; + + T M[2][2]; + + enum NoInitType { NoInit }; + + // Construct with no memory initialization. + Matrix2(NoInitType) { } + + // By default, we construct identity matrix. + Matrix2() + { + M[0][0] = M[1][1] = T(1); + M[0][1] = M[1][0] = T(0); + } + + Matrix2(T m11, T m12, + T m21, T m22) + { + M[0][0] = m11; M[0][1] = m12; + M[1][0] = m21; M[1][1] = m22; + } + + // Construction from X, Y basis vectors + Matrix2(const Vector2& xBasis, const Vector2& yBasis) + { + M[0][0] = xBasis.x; M[0][1] = yBasis.x; + M[1][0] = xBasis.y; M[1][1] = yBasis.y; + } + + explicit Matrix2(T s) + { + M[0][0] = M[1][1] = s; + M[0][1] = M[1][0] = T(0); + } + + Matrix2(T m11, T m22) + { + M[0][0] = m11; M[0][1] = T(0); + M[1][0] = T(0); M[1][1] = m22; + } + + explicit Matrix2(const Matrix2::OtherFloatType> &src) + { + M[0][0] = T(src.M[0][0]); M[0][1] = T(src.M[0][1]); + M[1][0] = T(src.M[1][0]); M[1][1] = T(src.M[1][1]); + } + + // C-interop support + Matrix2(const typename CompatibleTypes >::Type& s) + { + OVR_MATH_STATIC_ASSERT(sizeof(s) == sizeof(Matrix2), "sizeof(s) == sizeof(Matrix2)"); + memcpy(M, s.M, sizeof(M)); + } + + operator const typename CompatibleTypes >::Type() const + { + typename CompatibleTypes >::Type result; + OVR_MATH_STATIC_ASSERT(sizeof(result) == sizeof(Matrix2), "sizeof(result) == sizeof(Matrix2)"); + memcpy(result.M, M, sizeof(M)); + return result; + } + + T operator()(int i, int j) const { return M[i][j]; } + T& operator()(int i, int j) { return M[i][j]; } + const T* operator[](int i) const { return M[i]; } + T* operator[](int i) { return M[i]; } + + static Matrix2 Identity() { return Matrix2(); } + + void SetIdentity() + { + M[0][0] = M[1][1] = T(1); + M[0][1] = M[1][0] = T(0); + } + + static Matrix2 Diagonal(T m00, T m11) + { + return Matrix2(m00, m11); + } + static Matrix2 Diagonal(const Vector2& v) { return Matrix2(v.x, v.y); } + + T Trace() const { return M[0][0] + M[1][1]; } + + bool operator== (const Matrix2& b) const + { + return M[0][0] == b.M[0][0] && M[0][1] == b.M[0][1] && + M[1][0] == b.M[1][0] && M[1][1] == b.M[1][1]; + } + + Matrix2 operator+ (const Matrix2& b) const + { + return Matrix2(M[0][0] + b.M[0][0], M[0][1] + b.M[0][1], + M[1][0] + b.M[1][0], M[1][1] + b.M[1][1]); + } + + Matrix2& operator+= (const Matrix2& b) + { + M[0][0] += b.M[0][0]; M[0][1] += b.M[0][1]; + M[1][0] += b.M[1][0]; M[1][1] += b.M[1][1]; + return *this; + } + + void operator= (const Matrix2& b) + { + M[0][0] = b.M[0][0]; M[0][1] = b.M[0][1]; + M[1][0] = b.M[1][0]; M[1][1] = b.M[1][1]; + } + + Matrix2 operator- (const Matrix2& b) const + { + return Matrix2(M[0][0] - b.M[0][0], M[0][1] - b.M[0][1], + M[1][0] - b.M[1][0], M[1][1] - b.M[1][1]); + } + + Matrix2& operator-= (const Matrix2& b) + { + M[0][0] -= b.M[0][0]; M[0][1] -= b.M[0][1]; + M[1][0] -= b.M[1][0]; M[1][1] -= b.M[1][1]; + return *this; + } + + Matrix2 operator* (const Matrix2& b) const + { + return Matrix2(M[0][0] * b.M[0][0] + M[0][1] * b.M[1][0], M[0][0] * b.M[0][1] + M[0][1] * b.M[1][1], + M[1][0] * b.M[0][0] + M[1][1] * b.M[1][0], M[1][0] * b.M[0][1] + M[1][1] * b.M[1][1]); + } + + Matrix2& operator*= (const Matrix2& b) + { + *this = *this * b; + return *this; + } + + Matrix2 operator* (T s) const + { + return Matrix2(M[0][0] * s, M[0][1] * s, + M[1][0] * s, M[1][1] * s); + } + + Matrix2& operator*= (T s) + { + M[0][0] *= s; M[0][1] *= s; + M[1][0] *= s; M[1][1] *= s; + return *this; + } + + Matrix2 operator/ (T s) const + { + return *this * (T(1) / s); + } + + Matrix2& operator/= (T s) + { + return *this *= (T(1) / s); + } + + Vector2 operator* (const Vector2 &b) const + { + return Vector2(M[0][0] * b.x + M[0][1] * b.y, + M[1][0] * b.x + M[1][1] * b.y); + } + + Vector2 Transform(const Vector2& v) const + { + return Vector2(M[0][0] * v.x + M[0][1] * v.y, + M[1][0] * v.x + M[1][1] * v.y); + } + + Matrix2 Transposed() const + { + return Matrix2(M[0][0], M[1][0], + M[0][1], M[1][1]); + } + + void Transpose() + { + OVRMath_Swap(M[1][0], M[0][1]); + } + + Vector2 GetColumn(int c) const + { + return Vector2(M[0][c], M[1][c]); + } + + Vector2 GetRow(int r) const + { + return Vector2(M[r][0], M[r][1]); + } + + void SetColumn(int c, const Vector2& v) + { + M[0][c] = v.x; + M[1][c] = v.y; + } + + void SetRow(int r, const Vector2& v) + { + M[r][0] = v.x; + M[r][1] = v.y; + } + + T Determinant() const + { + return M[0][0] * M[1][1] - M[0][1] * M[1][0]; + } + + Matrix2 Inverse() const + { + T rcpDet = T(1) / Determinant(); + return Matrix2( M[1][1] * rcpDet, -M[0][1] * rcpDet, + -M[1][0] * rcpDet, M[0][0] * rcpDet); + } + + // Outer Product of two column vectors: a * b.Transpose() + static Matrix2 OuterProduct(const Vector2& a, const Vector2& b) + { + return Matrix2(a.x*b.x, a.x*b.y, + a.y*b.x, a.y*b.y); + } + + // Angle in radians between two rotation matrices + T Angle(const Matrix2& b) const + { + const Matrix2& a = *this; + return Acos(a(0, 0)*b(0, 0) + a(1, 0)*b(1, 0)); + } +}; + +typedef Matrix2 Matrix2f; +typedef Matrix2 Matrix2d; + +//------------------------------------------------------------------------------------- + +template +class SymMat3 +{ +private: + typedef SymMat3 this_type; + +public: + typedef T Value_t; + // Upper symmetric + T v[6]; // _00 _01 _02 _11 _12 _22 + + inline SymMat3() {} + + inline explicit SymMat3(T s) + { + v[0] = v[3] = v[5] = s; + v[1] = v[2] = v[4] = T(0); + } + + inline explicit SymMat3(T a00, T a01, T a02, T a11, T a12, T a22) + { + v[0] = a00; v[1] = a01; v[2] = a02; + v[3] = a11; v[4] = a12; + v[5] = a22; + } + + // Cast to symmetric Matrix3 + operator Matrix3() const + { + return Matrix3(v[0], v[1], v[2], + v[1], v[3], v[4], + v[2], v[4], v[5]); + } + + static inline int Index(unsigned int i, unsigned int j) + { + return (i <= j) ? (3*i - i*(i+1)/2 + j) : (3*j - j*(j+1)/2 + i); + } + + inline T operator()(int i, int j) const { return v[Index(i,j)]; } + + inline T &operator()(int i, int j) { return v[Index(i,j)]; } + + inline this_type& operator+=(const this_type& b) + { + v[0]+=b.v[0]; + v[1]+=b.v[1]; + v[2]+=b.v[2]; + v[3]+=b.v[3]; + v[4]+=b.v[4]; + v[5]+=b.v[5]; + return *this; + } + + inline this_type& operator-=(const this_type& b) + { + v[0]-=b.v[0]; + v[1]-=b.v[1]; + v[2]-=b.v[2]; + v[3]-=b.v[3]; + v[4]-=b.v[4]; + v[5]-=b.v[5]; + + return *this; + } + + inline this_type& operator*=(T s) + { + v[0]*=s; + v[1]*=s; + v[2]*=s; + v[3]*=s; + v[4]*=s; + v[5]*=s; + + return *this; + } + + inline SymMat3 operator*(T s) const + { + SymMat3 d; + d.v[0] = v[0]*s; + d.v[1] = v[1]*s; + d.v[2] = v[2]*s; + d.v[3] = v[3]*s; + d.v[4] = v[4]*s; + d.v[5] = v[5]*s; + + return d; + } + + // Multiplies two matrices into destination with minimum copying. + static SymMat3& Multiply(SymMat3* d, const SymMat3& a, const SymMat3& b) + { + // _00 _01 _02 _11 _12 _22 + + d->v[0] = a.v[0] * b.v[0]; + d->v[1] = a.v[0] * b.v[1] + a.v[1] * b.v[3]; + d->v[2] = a.v[0] * b.v[2] + a.v[1] * b.v[4]; + + d->v[3] = a.v[3] * b.v[3]; + d->v[4] = a.v[3] * b.v[4] + a.v[4] * b.v[5]; + + d->v[5] = a.v[5] * b.v[5]; + + return *d; + } + + inline T Determinant() const + { + const this_type& m = *this; + T d; + + d = m(0,0) * (m(1,1)*m(2,2) - m(1,2) * m(2,1)); + d -= m(0,1) * (m(1,0)*m(2,2) - m(1,2) * m(2,0)); + d += m(0,2) * (m(1,0)*m(2,1) - m(1,1) * m(2,0)); + + return d; + } + + inline this_type Inverse() const + { + this_type a; + const this_type& m = *this; + T d = Determinant(); + + OVR_MATH_ASSERT(d != 0); + T s = T(1)/d; + + a(0,0) = s * (m(1,1) * m(2,2) - m(1,2) * m(2,1)); + + a(0,1) = s * (m(0,2) * m(2,1) - m(0,1) * m(2,2)); + a(1,1) = s * (m(0,0) * m(2,2) - m(0,2) * m(2,0)); + + a(0,2) = s * (m(0,1) * m(1,2) - m(0,2) * m(1,1)); + a(1,2) = s * (m(0,2) * m(1,0) - m(0,0) * m(1,2)); + a(2,2) = s * (m(0,0) * m(1,1) - m(0,1) * m(1,0)); + + return a; + } + + inline T Trace() const { return v[0] + v[3] + v[5]; } + + // M = a*a.t() + inline void Rank1(const Vector3 &a) + { + v[0] = a.x*a.x; v[1] = a.x*a.y; v[2] = a.x*a.z; + v[3] = a.y*a.y; v[4] = a.y*a.z; + v[5] = a.z*a.z; + } + + // M += a*a.t() + inline void Rank1Add(const Vector3 &a) + { + v[0] += a.x*a.x; v[1] += a.x*a.y; v[2] += a.x*a.z; + v[3] += a.y*a.y; v[4] += a.y*a.z; + v[5] += a.z*a.z; + } + + // M -= a*a.t() + inline void Rank1Sub(const Vector3 &a) + { + v[0] -= a.x*a.x; v[1] -= a.x*a.y; v[2] -= a.x*a.z; + v[3] -= a.y*a.y; v[4] -= a.y*a.z; + v[5] -= a.z*a.z; + } +}; + +typedef SymMat3 SymMat3f; +typedef SymMat3 SymMat3d; + +template +inline Matrix3 operator*(const SymMat3& a, const SymMat3& b) +{ + #define AJB_ARBC(r,c) (a(r,0)*b(0,c)+a(r,1)*b(1,c)+a(r,2)*b(2,c)) + return Matrix3( + AJB_ARBC(0,0), AJB_ARBC(0,1), AJB_ARBC(0,2), + AJB_ARBC(1,0), AJB_ARBC(1,1), AJB_ARBC(1,2), + AJB_ARBC(2,0), AJB_ARBC(2,1), AJB_ARBC(2,2)); + #undef AJB_ARBC +} + +template +inline Matrix3 operator*(const Matrix3& a, const SymMat3& b) +{ + #define AJB_ARBC(r,c) (a(r,0)*b(0,c)+a(r,1)*b(1,c)+a(r,2)*b(2,c)) + return Matrix3( + AJB_ARBC(0,0), AJB_ARBC(0,1), AJB_ARBC(0,2), + AJB_ARBC(1,0), AJB_ARBC(1,1), AJB_ARBC(1,2), + AJB_ARBC(2,0), AJB_ARBC(2,1), AJB_ARBC(2,2)); + #undef AJB_ARBC +} + +//------------------------------------------------------------------------------------- +// ***** Angle + +// Cleanly representing the algebra of 2D rotations. +// The operations maintain the angle between -Pi and Pi, the same range as atan2. + +template +class Angle +{ +public: + enum AngularUnits + { + Radians = 0, + Degrees = 1 + }; + + Angle() : a(0) {} + + // Fix the range to be between -Pi and Pi + Angle(T a_, AngularUnits u = Radians) : a((u == Radians) ? a_ : a_*((T)MATH_DOUBLE_DEGREETORADFACTOR)) { FixRange(); } + + T Get(AngularUnits u = Radians) const { return (u == Radians) ? a : a*((T)MATH_DOUBLE_RADTODEGREEFACTOR); } + void Set(const T& x, AngularUnits u = Radians) { a = (u == Radians) ? x : x*((T)MATH_DOUBLE_DEGREETORADFACTOR); FixRange(); } + int Sign() const { if (a == 0) return 0; else return (a > 0) ? 1 : -1; } + T Abs() const { return (a >= 0) ? a : -a; } + + bool operator== (const Angle& b) const { return a == b.a; } + bool operator!= (const Angle& b) const { return a != b.a; } +// bool operator< (const Angle& b) const { return a < a.b; } +// bool operator> (const Angle& b) const { return a > a.b; } +// bool operator<= (const Angle& b) const { return a <= a.b; } +// bool operator>= (const Angle& b) const { return a >= a.b; } +// bool operator= (const T& x) { a = x; FixRange(); } + + // These operations assume a is already between -Pi and Pi. + Angle& operator+= (const Angle& b) { a = a + b.a; FastFixRange(); return *this; } + Angle& operator+= (const T& x) { a = a + x; FixRange(); return *this; } + Angle operator+ (const Angle& b) const { Angle res = *this; res += b; return res; } + Angle operator+ (const T& x) const { Angle res = *this; res += x; return res; } + Angle& operator-= (const Angle& b) { a = a - b.a; FastFixRange(); return *this; } + Angle& operator-= (const T& x) { a = a - x; FixRange(); return *this; } + Angle operator- (const Angle& b) const { Angle res = *this; res -= b; return res; } + Angle operator- (const T& x) const { Angle res = *this; res -= x; return res; } + + T Distance(const Angle& b) { T c = fabs(a - b.a); return (c <= ((T)MATH_DOUBLE_PI)) ? c : ((T)MATH_DOUBLE_TWOPI) - c; } + +private: + + // The stored angle, which should be maintained between -Pi and Pi + T a; + + // Fixes the angle range to [-Pi,Pi], but assumes no more than 2Pi away on either side + inline void FastFixRange() + { + if (a < -((T)MATH_DOUBLE_PI)) + a += ((T)MATH_DOUBLE_TWOPI); + else if (a > ((T)MATH_DOUBLE_PI)) + a -= ((T)MATH_DOUBLE_TWOPI); + } + + // Fixes the angle range to [-Pi,Pi] for any given range, but slower then the fast method + inline void FixRange() + { + // do nothing if the value is already in the correct range, since fmod call is expensive + if (a >= -((T)MATH_DOUBLE_PI) && a <= ((T)MATH_DOUBLE_PI)) + return; + a = fmod(a,((T)MATH_DOUBLE_TWOPI)); + if (a < -((T)MATH_DOUBLE_PI)) + a += ((T)MATH_DOUBLE_TWOPI); + else if (a > ((T)MATH_DOUBLE_PI)) + a -= ((T)MATH_DOUBLE_TWOPI); + } +}; + + +typedef Angle Anglef; +typedef Angle Angled; + + +//------------------------------------------------------------------------------------- +// ***** Plane + +// Consists of a normal vector and distance from the origin where the plane is located. + +template +class Plane +{ +public: + Vector3 N; + T D; + + Plane() : D(0) {} + + // Normals must already be normalized + Plane(const Vector3& n, T d) : N(n), D(d) {} + Plane(T x, T y, T z, T d) : N(x,y,z), D(d) {} + + // construct from a point on the plane and the normal + Plane(const Vector3& p, const Vector3& n) : N(n), D(-(p * n)) {} + + // Find the point to plane distance. The sign indicates what side of the plane the point is on (0 = point on plane). + T TestSide(const Vector3& p) const + { + return (N.Dot(p)) + D; + } + + Plane Flipped() const + { + return Plane(-N, -D); + } + + void Flip() + { + N = -N; + D = -D; + } + + bool operator==(const Plane& rhs) const + { + return (this->D == rhs.D && this->N == rhs.N); + } +}; + +typedef Plane Planef; +typedef Plane Planed; + + + + +//----------------------------------------------------------------------------------- +// ***** ScaleAndOffset2D + +struct ScaleAndOffset2D +{ + Vector2f Scale; + Vector2f Offset; + + ScaleAndOffset2D(float sx = 0.0f, float sy = 0.0f, float ox = 0.0f, float oy = 0.0f) + : Scale(sx, sy), Offset(ox, oy) + { } +}; + + +//----------------------------------------------------------------------------------- +// ***** FovPort + +// FovPort describes Field Of View (FOV) of a viewport. +// This class has values for up, down, left and right, stored in +// tangent of the angle units to simplify calculations. +// +// As an example, for a standard 90 degree vertical FOV, we would +// have: { UpTan = tan(90 degrees / 2), DownTan = tan(90 degrees / 2) }. +// +// CreateFromRadians/Degrees helper functions can be used to +// access FOV in different units. + + +// ***** FovPort + +struct FovPort +{ + float UpTan; + float DownTan; + float LeftTan; + float RightTan; + + FovPort ( float sideTan = 0.0f ) : + UpTan(sideTan), DownTan(sideTan), LeftTan(sideTan), RightTan(sideTan) { } + FovPort ( float u, float d, float l, float r ) : + UpTan(u), DownTan(d), LeftTan(l), RightTan(r) { } + + // C-interop support: FovPort <-> ovrFovPort (implementation in OVR_CAPI.cpp). + FovPort(const ovrFovPort &src) + : UpTan(src.UpTan), DownTan(src.DownTan), LeftTan(src.LeftTan), RightTan(src.RightTan) + { } + + operator ovrFovPort () const + { + ovrFovPort result; + result.LeftTan = LeftTan; + result.RightTan = RightTan; + result.UpTan = UpTan; + result.DownTan = DownTan; + return result; + } + + static FovPort CreateFromRadians(float horizontalFov, float verticalFov) + { + FovPort result; + result.UpTan = tanf ( verticalFov * 0.5f ); + result.DownTan = tanf ( verticalFov * 0.5f ); + result.LeftTan = tanf ( horizontalFov * 0.5f ); + result.RightTan = tanf ( horizontalFov * 0.5f ); + return result; + } + + static FovPort CreateFromDegrees(float horizontalFovDegrees, + float verticalFovDegrees) + { + return CreateFromRadians(DegreeToRad(horizontalFovDegrees), + DegreeToRad(verticalFovDegrees)); + } + + // Get Horizontal/Vertical components of Fov in radians. + float GetVerticalFovRadians() const { return atanf(UpTan) + atanf(DownTan); } + float GetHorizontalFovRadians() const { return atanf(LeftTan) + atanf(RightTan); } + // Get Horizontal/Vertical components of Fov in degrees. + float GetVerticalFovDegrees() const { return RadToDegree(GetVerticalFovRadians()); } + float GetHorizontalFovDegrees() const { return RadToDegree(GetHorizontalFovRadians()); } + + // Compute maximum tangent value among all four sides. + float GetMaxSideTan() const + { + return OVRMath_Max(OVRMath_Max(UpTan, DownTan), OVRMath_Max(LeftTan, RightTan)); + } + + static ScaleAndOffset2D CreateNDCScaleAndOffsetFromFov ( FovPort tanHalfFov ) + { + float projXScale = 2.0f / ( tanHalfFov.LeftTan + tanHalfFov.RightTan ); + float projXOffset = ( tanHalfFov.LeftTan - tanHalfFov.RightTan ) * projXScale * 0.5f; + float projYScale = 2.0f / ( tanHalfFov.UpTan + tanHalfFov.DownTan ); + float projYOffset = ( tanHalfFov.UpTan - tanHalfFov.DownTan ) * projYScale * 0.5f; + + ScaleAndOffset2D result; + result.Scale = Vector2f(projXScale, projYScale); + result.Offset = Vector2f(projXOffset, projYOffset); + // Hey - why is that Y.Offset negated? + // It's because a projection matrix transforms from world coords with Y=up, + // whereas this is from NDC which is Y=down. + + return result; + } + + // Converts Fov Tan angle units to [-1,1] render target NDC space + Vector2f TanAngleToRendertargetNDC(Vector2f const &tanEyeAngle) + { + ScaleAndOffset2D eyeToSourceNDC = CreateNDCScaleAndOffsetFromFov(*this); + return tanEyeAngle * eyeToSourceNDC.Scale + eyeToSourceNDC.Offset; + } + + // Compute per-channel minimum and maximum of Fov. + static FovPort Min(const FovPort& a, const FovPort& b) + { + FovPort fov( OVRMath_Min( a.UpTan , b.UpTan ), + OVRMath_Min( a.DownTan , b.DownTan ), + OVRMath_Min( a.LeftTan , b.LeftTan ), + OVRMath_Min( a.RightTan, b.RightTan ) ); + return fov; + } + + static FovPort Max(const FovPort& a, const FovPort& b) + { + FovPort fov( OVRMath_Max( a.UpTan , b.UpTan ), + OVRMath_Max( a.DownTan , b.DownTan ), + OVRMath_Max( a.LeftTan , b.LeftTan ), + OVRMath_Max( a.RightTan, b.RightTan ) ); + return fov; + } +}; + + +} // Namespace OVR + + +#if defined(_MSC_VER) + #pragma warning(pop) +#endif + + +#endif diff --git a/src/external/OculusSDK/LibOVR/Include/Extras/OVR_StereoProjection.h b/src/external/OculusSDK/LibOVR/Include/Extras/OVR_StereoProjection.h new file mode 100644 index 000000000..b4bc3bc77 --- /dev/null +++ b/src/external/OculusSDK/LibOVR/Include/Extras/OVR_StereoProjection.h @@ -0,0 +1,70 @@ +/************************************************************************************ + +Filename : OVR_StereoProjection.h +Content : Stereo projection functions +Created : November 30, 2013 +Authors : Tom Fosyth + +Copyright : Copyright 2014-2016 Oculus VR, LLC All Rights reserved. + +Licensed under the Oculus VR Rift SDK License Version 3.3 (the "License"); +you may not use the Oculus VR Rift SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +http://www.oculusvr.com/licenses/LICENSE-3.3 + +Unless required by applicable law or agreed to in writing, the Oculus VR SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*************************************************************************************/ + +#ifndef OVR_StereoProjection_h +#define OVR_StereoProjection_h + + +#include "Extras/OVR_Math.h" + + +namespace OVR { + + +//----------------------------------------------------------------------------------- +// ***** Stereo Enumerations + +// StereoEye specifies which eye we are rendering for; it is used to +// retrieve StereoEyeParams. +enum StereoEye +{ + StereoEye_Left, + StereoEye_Right, + StereoEye_Center +}; + + + +//----------------------------------------------------------------------------------- +// ***** Propjection functions + +Matrix4f CreateProjection ( bool rightHanded, bool isOpenGL, FovPort fov, StereoEye eye, + float zNear = 0.01f, float zFar = 10000.0f, + bool flipZ = false, bool farAtInfinity = false); + +Matrix4f CreateOrthoSubProjection ( bool rightHanded, StereoEye eyeType, + float tanHalfFovX, float tanHalfFovY, + float unitsX, float unitsY, float distanceFromCamera, + float interpupillaryDistance, Matrix4f const &projection, + float zNear = 0.0f, float zFar = 0.0f, + bool flipZ = false, bool farAtInfinity = false); + +ScaleAndOffset2D CreateNDCScaleAndOffsetFromFov ( FovPort fov ); + + +} //namespace OVR + +#endif // OVR_StereoProjection_h diff --git a/src/external/OculusSDK/LibOVR/Include/OVR_CAPI.h b/src/external/OculusSDK/LibOVR/Include/OVR_CAPI.h new file mode 100644 index 000000000..b1ec3cc0e --- /dev/null +++ b/src/external/OculusSDK/LibOVR/Include/OVR_CAPI.h @@ -0,0 +1,2116 @@ +/********************************************************************************//** +\file OVR_CAPI.h +\brief C Interface to the Oculus PC SDK tracking and rendering library. +\copyright Copyright 2014 Oculus VR, LLC All Rights reserved. +************************************************************************************/ + +#ifndef OVR_CAPI_h // We don't use version numbers within this name, as all versioned variations of this file are currently mutually exclusive. +#define OVR_CAPI_h ///< Header include guard + + +#include "OVR_CAPI_Keys.h" +#include "OVR_Version.h" +#include "OVR_ErrorCode.h" + + +#include + +#if defined(_MSC_VER) + #pragma warning(push) + #pragma warning(disable: 4324) // structure was padded due to __declspec(align()) + #pragma warning(disable: 4359) // The alignment specified for a type is less than the alignment of the type of one of its data members +#endif + + + +//----------------------------------------------------------------------------------- +// ***** OVR_OS +// +#if !defined(OVR_OS_WIN32) && defined(_WIN32) + #define OVR_OS_WIN32 +#endif + +#if !defined(OVR_OS_MAC) && defined(__APPLE__) + #define OVR_OS_MAC +#endif + +#if !defined(OVR_OS_LINUX) && defined(__linux__) + #define OVR_OS_LINUX +#endif + + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP +// +#if !defined(OVR_CPP) + #if defined(__cplusplus) + #define OVR_CPP(x) x + #else + #define OVR_CPP(x) /* Not C++ */ + #endif +#endif + + + +//----------------------------------------------------------------------------------- +// ***** OVR_CDECL +// +/// LibOVR calling convention for 32-bit Windows builds. +// +#if !defined(OVR_CDECL) + #if defined(_WIN32) + #define OVR_CDECL __cdecl + #else + #define OVR_CDECL + #endif +#endif + + + +//----------------------------------------------------------------------------------- +// ***** OVR_EXTERN_C +// +/// Defined as extern "C" when built from C++ code. +// +#if !defined(OVR_EXTERN_C) + #ifdef __cplusplus + #define OVR_EXTERN_C extern "C" + #else + #define OVR_EXTERN_C + #endif +#endif + + + +//----------------------------------------------------------------------------------- +// ***** OVR_PUBLIC_FUNCTION / OVR_PRIVATE_FUNCTION +// +// OVR_PUBLIC_FUNCTION - Functions that externally visible from a shared library. Corresponds to Microsoft __dllexport. +// OVR_PUBLIC_CLASS - C++ structs and classes that are externally visible from a shared library. Corresponds to Microsoft __dllexport. +// OVR_PRIVATE_FUNCTION - Functions that are not visible outside of a shared library. They are private to the shared library. +// OVR_PRIVATE_CLASS - C++ structs and classes that are not visible outside of a shared library. They are private to the shared library. +// +// OVR_DLL_BUILD - Used to indicate that the current compilation unit is of a shared library. +// OVR_DLL_IMPORT - Used to indicate that the current compilation unit is a user of the corresponding shared library. +// OVR_STATIC_BUILD - used to indicate that the current compilation unit is not a shared library but rather statically linked code. +// +#if !defined(OVR_PUBLIC_FUNCTION) + #if defined(OVR_DLL_BUILD) + #if defined(_WIN32) + #define OVR_PUBLIC_FUNCTION(rval) OVR_EXTERN_C __declspec(dllexport) rval OVR_CDECL + #define OVR_PUBLIC_CLASS __declspec(dllexport) + #define OVR_PRIVATE_FUNCTION(rval) rval OVR_CDECL + #define OVR_PRIVATE_CLASS + #else + #define OVR_PUBLIC_FUNCTION(rval) OVR_EXTERN_C __attribute__((visibility("default"))) rval OVR_CDECL /* Requires GCC 4.0+ */ + #define OVR_PUBLIC_CLASS __attribute__((visibility("default"))) /* Requires GCC 4.0+ */ + #define OVR_PRIVATE_FUNCTION(rval) __attribute__((visibility("hidden"))) rval OVR_CDECL + #define OVR_PRIVATE_CLASS __attribute__((visibility("hidden"))) + #endif + #elif defined(OVR_DLL_IMPORT) + #if defined(_WIN32) + #define OVR_PUBLIC_FUNCTION(rval) OVR_EXTERN_C __declspec(dllimport) rval OVR_CDECL + #define OVR_PUBLIC_CLASS __declspec(dllimport) + #else + #define OVR_PUBLIC_FUNCTION(rval) OVR_EXTERN_C rval OVR_CDECL + #define OVR_PUBLIC_CLASS + #endif + #define OVR_PRIVATE_FUNCTION(rval) rval OVR_CDECL + #define OVR_PRIVATE_CLASS + #else // OVR_STATIC_BUILD + #define OVR_PUBLIC_FUNCTION(rval) OVR_EXTERN_C rval OVR_CDECL + #define OVR_PUBLIC_CLASS + #define OVR_PRIVATE_FUNCTION(rval) rval OVR_CDECL + #define OVR_PRIVATE_CLASS + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_EXPORT +// +/// Provided for backward compatibility with older versions of this library. +// +#if !defined(OVR_EXPORT) + #ifdef OVR_OS_WIN32 + #define OVR_EXPORT __declspec(dllexport) + #else + #define OVR_EXPORT + #endif +#endif + + + +//----------------------------------------------------------------------------------- +// ***** OVR_ALIGNAS +// +#if !defined(OVR_ALIGNAS) + #if defined(__GNUC__) || defined(__clang__) + #define OVR_ALIGNAS(n) __attribute__((aligned(n))) + #elif defined(_MSC_VER) || defined(__INTEL_COMPILER) + #define OVR_ALIGNAS(n) __declspec(align(n)) + #elif defined(__CC_ARM) + #define OVR_ALIGNAS(n) __align(n) + #else + #error Need to define OVR_ALIGNAS + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CC_HAS_FEATURE +// +// This is a portable way to use compile-time feature identification available +// with some compilers in a clean way. Direct usage of __has_feature in preprocessing +// statements of non-supporting compilers results in a preprocessing error. +// +// Example usage: +// #if OVR_CC_HAS_FEATURE(is_pod) +// if(__is_pod(T)) // If the type is plain data then we can safely memcpy it. +// memcpy(&destObject, &srcObject, sizeof(object)); +// #endif +// +#if !defined(OVR_CC_HAS_FEATURE) + #if defined(__clang__) // http://clang.llvm.org/docs/LanguageExtensions.html#id2 + #define OVR_CC_HAS_FEATURE(x) __has_feature(x) + #else + #define OVR_CC_HAS_FEATURE(x) 0 + #endif +#endif + + +// ------------------------------------------------------------------------ +// ***** OVR_STATIC_ASSERT +// +// Portable support for C++11 static_assert(). +// Acts as if the following were declared: +// void OVR_STATIC_ASSERT(bool const_expression, const char* msg); +// +// Example usage: +// OVR_STATIC_ASSERT(sizeof(int32_t) == 4, "int32_t expected to be 4 bytes."); + +#if !defined(OVR_STATIC_ASSERT) + #if !(defined(__cplusplus) && (__cplusplus >= 201103L)) /* Other */ && \ + !(defined(__GXX_EXPERIMENTAL_CXX0X__)) /* GCC */ && \ + !(defined(__clang__) && defined(__cplusplus) && OVR_CC_HAS_FEATURE(cxx_static_assert)) /* clang */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1600) && defined(__cplusplus)) /* VS2010+ */ + + #if !defined(OVR_SA_UNUSED) + #if defined(OVR_CC_GNU) || defined(OVR_CC_CLANG) + #define OVR_SA_UNUSED __attribute__((unused)) + #else + #define OVR_SA_UNUSED + #endif + #define OVR_SA_PASTE(a,b) a##b + #define OVR_SA_HELP(a,b) OVR_SA_PASTE(a,b) + #endif + + #if defined(__COUNTER__) + #define OVR_STATIC_ASSERT(expression, msg) typedef char OVR_SA_HELP(compileTimeAssert, __COUNTER__) [((expression) != 0) ? 1 : -1] OVR_SA_UNUSED + #else + #define OVR_STATIC_ASSERT(expression, msg) typedef char OVR_SA_HELP(compileTimeAssert, __LINE__) [((expression) != 0) ? 1 : -1] OVR_SA_UNUSED + #endif + + #else + #define OVR_STATIC_ASSERT(expression, msg) static_assert(expression, msg) + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** Padding +// +/// Defines explicitly unused space for a struct. +/// When used correcly, usage of this macro should not change the size of the struct. +/// Compile-time and runtime behavior with and without this defined should be identical. +/// +#if !defined(OVR_UNUSED_STRUCT_PAD) + #define OVR_UNUSED_STRUCT_PAD(padName, size) char padName[size]; +#endif + + +//----------------------------------------------------------------------------------- +// ***** Word Size +// +/// Specifies the size of a pointer on the given platform. +/// +#if !defined(OVR_PTR_SIZE) + #if defined(__WORDSIZE) + #define OVR_PTR_SIZE ((__WORDSIZE) / 8) + #elif defined(_WIN64) || defined(__LP64__) || defined(_LP64) || defined(_M_IA64) || defined(__ia64__) || defined(__arch64__) || defined(__64BIT__) || defined(__Ptr_Is_64) + #define OVR_PTR_SIZE 8 + #elif defined(__CC_ARM) && (__sizeof_ptr == 8) + #define OVR_PTR_SIZE 8 + #else + #define OVR_PTR_SIZE 4 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_ON32 / OVR_ON64 +// +#if OVR_PTR_SIZE == 8 + #define OVR_ON32(x) + #define OVR_ON64(x) x +#else + #define OVR_ON32(x) x + #define OVR_ON64(x) +#endif + + +//----------------------------------------------------------------------------------- +// ***** ovrBool + +typedef char ovrBool; ///< Boolean type +#define ovrFalse 0 ///< ovrBool value of false. +#define ovrTrue 1 ///< ovrBool value of true. + + +//----------------------------------------------------------------------------------- +// ***** Simple Math Structures + +/// A 2D vector with integer components. +typedef struct OVR_ALIGNAS(4) ovrVector2i_ +{ + int x, y; +} ovrVector2i; + +/// A 2D size with integer components. +typedef struct OVR_ALIGNAS(4) ovrSizei_ +{ + int w, h; +} ovrSizei; + +/// A 2D rectangle with a position and size. +/// All components are integers. +typedef struct OVR_ALIGNAS(4) ovrRecti_ +{ + ovrVector2i Pos; + ovrSizei Size; +} ovrRecti; + +/// A quaternion rotation. +typedef struct OVR_ALIGNAS(4) ovrQuatf_ +{ + float x, y, z, w; +} ovrQuatf; + +/// A 2D vector with float components. +typedef struct OVR_ALIGNAS(4) ovrVector2f_ +{ + float x, y; +} ovrVector2f; + +/// A 3D vector with float components. +typedef struct OVR_ALIGNAS(4) ovrVector3f_ +{ + float x, y, z; +} ovrVector3f; + +/// A 4x4 matrix with float elements. +typedef struct OVR_ALIGNAS(4) ovrMatrix4f_ +{ + float M[4][4]; +} ovrMatrix4f; + + +/// Position and orientation together. +typedef struct OVR_ALIGNAS(4) ovrPosef_ +{ + ovrQuatf Orientation; + ovrVector3f Position; +} ovrPosef; + +/// A full pose (rigid body) configuration with first and second derivatives. +/// +/// Body refers to any object for which ovrPoseStatef is providing data. +/// It can be the HMD, Touch controller, sensor or something else. The context +/// depends on the usage of the struct. +typedef struct OVR_ALIGNAS(8) ovrPoseStatef_ +{ + ovrPosef ThePose; ///< Position and orientation. + ovrVector3f AngularVelocity; ///< Angular velocity in radians per second. + ovrVector3f LinearVelocity; ///< Velocity in meters per second. + ovrVector3f AngularAcceleration; ///< Angular acceleration in radians per second per second. + ovrVector3f LinearAcceleration; ///< Acceleration in meters per second per second. + OVR_UNUSED_STRUCT_PAD(pad0, 4) ///< \internal struct pad. + double TimeInSeconds; ///< Absolute time that this pose refers to. \see ovr_GetTimeInSeconds +} ovrPoseStatef; + +/// Describes the up, down, left, and right angles of the field of view. +/// +/// Field Of View (FOV) tangent of the angle units. +/// \note For a standard 90 degree vertical FOV, we would +/// have: { UpTan = tan(90 degrees / 2), DownTan = tan(90 degrees / 2) }. +typedef struct OVR_ALIGNAS(4) ovrFovPort_ +{ + float UpTan; ///< The tangent of the angle between the viewing vector and the top edge of the field of view. + float DownTan; ///< The tangent of the angle between the viewing vector and the bottom edge of the field of view. + float LeftTan; ///< The tangent of the angle between the viewing vector and the left edge of the field of view. + float RightTan; ///< The tangent of the angle between the viewing vector and the right edge of the field of view. +} ovrFovPort; + + +//----------------------------------------------------------------------------------- +// ***** HMD Types + +/// Enumerates all HMD types that we support. +/// +/// The currently released developer kits are ovrHmd_DK1 and ovrHmd_DK2. The other enumerations are for internal use only. +typedef enum ovrHmdType_ +{ + ovrHmd_None = 0, + ovrHmd_DK1 = 3, + ovrHmd_DKHD = 4, + ovrHmd_DK2 = 6, + ovrHmd_CB = 8, + ovrHmd_Other = 9, + ovrHmd_E3_2015 = 10, + ovrHmd_ES06 = 11, + ovrHmd_ES09 = 12, + ovrHmd_ES11 = 13, + ovrHmd_CV1 = 14, + + ovrHmd_EnumSize = 0x7fffffff ///< \internal Force type int32_t. +} ovrHmdType; + + +/// HMD capability bits reported by device. +/// +typedef enum ovrHmdCaps_ +{ + // Read-only flags + ovrHmdCap_DebugDevice = 0x0010, ///< (read only) Specifies that the HMD is a virtual debug device. + + + ovrHmdCap_EnumSize = 0x7fffffff ///< \internal Force type int32_t. +} ovrHmdCaps; + + +/// Tracking capability bits reported by the device. +/// Used with ovr_GetTrackingCaps. +typedef enum ovrTrackingCaps_ +{ + ovrTrackingCap_Orientation = 0x0010, ///< Supports orientation tracking (IMU). + ovrTrackingCap_MagYawCorrection = 0x0020, ///< Supports yaw drift correction via a magnetometer or other means. + ovrTrackingCap_Position = 0x0040, ///< Supports positional tracking. + ovrTrackingCap_EnumSize = 0x7fffffff ///< \internal Force type int32_t. +} ovrTrackingCaps; + + +/// Specifies which eye is being used for rendering. +/// This type explicitly does not include a third "NoStereo" monoscopic option, as such is +/// not required for an HMD-centered API. +typedef enum ovrEyeType_ +{ + ovrEye_Left = 0, ///< The left eye, from the viewer's perspective. + ovrEye_Right = 1, ///< The right eye, from the viewer's perspective. + ovrEye_Count = 2, ///< \internal Count of enumerated elements. + ovrEye_EnumSize = 0x7fffffff ///< \internal Force type int32_t. +} ovrEyeType; + +/// Specifies the coordinate system ovrTrackingState returns tracking poses in. +/// Used with ovr_SetTrackingOriginType() +typedef enum ovrTrackingOrigin_ +{ + /// \brief Tracking system origin reported at eye (HMD) height + /// \details Prefer using this origin when your application requires + /// matching user's current physical head pose to a virtual head pose + /// without any regards to a the height of the floor. Cockpit-based, + /// or 3rd-person experiences are ideal candidates. + /// When used, all poses in ovrTrackingState are reported as an offset + /// transform from the profile calibrated or recentered HMD pose. + /// It is recommended that apps using this origin type call ovr_RecenterTrackingOrigin + /// prior to starting the VR experience, but notify the user before doing so + /// to make sure the user is in a comfortable pose, facing a comfortable + /// direction. + ovrTrackingOrigin_EyeLevel = 0, + /// \brief Tracking system origin reported at floor height + /// \details Prefer using this origin when your application requires the + /// physical floor height to match the virtual floor height, such as + /// standing experiences. + /// When used, all poses in ovrTrackingState are reported as an offset + /// transform from the profile calibrated floor pose. Calling ovr_RecenterTrackingOrigin + /// will recenter the X & Z axes as well as yaw, but the Y-axis (i.e. height) will continue + /// to be reported using the floor height as the origin for all poses. + ovrTrackingOrigin_FloorLevel = 1, + ovrTrackingOrigin_Count = 2, ///< \internal Count of enumerated elements. + ovrTrackingOrigin_EnumSize = 0x7fffffff ///< \internal Force type int32_t. +} ovrTrackingOrigin; + +/// Identifies a graphics device in a platform-specific way. +/// For Windows this is a LUID type. +typedef struct OVR_ALIGNAS(OVR_PTR_SIZE) ovrGraphicsLuid_ +{ + // Public definition reserves space for graphics API-specific implementation + char Reserved[8]; +} ovrGraphicsLuid; + + +/// This is a complete descriptor of the HMD. +typedef struct OVR_ALIGNAS(OVR_PTR_SIZE) ovrHmdDesc_ +{ + ovrHmdType Type; ///< The type of HMD. + OVR_ON64(OVR_UNUSED_STRUCT_PAD(pad0, 4)) ///< \internal struct paddding. + char ProductName[64]; ///< UTF8-encoded product identification string (e.g. "Oculus Rift DK1"). + char Manufacturer[64]; ///< UTF8-encoded HMD manufacturer identification string. + short VendorId; ///< HID (USB) vendor identifier of the device. + short ProductId; ///< HID (USB) product identifier of the device. + char SerialNumber[24]; ///< HMD serial number. + short FirmwareMajor; ///< HMD firmware major version. + short FirmwareMinor; ///< HMD firmware minor version. + unsigned int AvailableHmdCaps; ///< Capability bits described by ovrHmdCaps which the HMD currently supports. + unsigned int DefaultHmdCaps; ///< Capability bits described by ovrHmdCaps which are default for the current Hmd. + unsigned int AvailableTrackingCaps; ///< Capability bits described by ovrTrackingCaps which the system currently supports. + unsigned int DefaultTrackingCaps; ///< Capability bits described by ovrTrackingCaps which are default for the current system. + ovrFovPort DefaultEyeFov[ovrEye_Count]; ///< Defines the recommended FOVs for the HMD. + ovrFovPort MaxEyeFov[ovrEye_Count]; ///< Defines the maximum FOVs for the HMD. + ovrSizei Resolution; ///< Resolution of the full HMD screen (both eyes) in pixels. + float DisplayRefreshRate; ///< Nominal refresh rate of the display in cycles per second at the time of HMD creation. + OVR_ON64(OVR_UNUSED_STRUCT_PAD(pad1, 4)) ///< \internal struct paddding. +} ovrHmdDesc; + + +/// Used as an opaque pointer to an OVR session. +typedef struct ovrHmdStruct* ovrSession; + + + +/// Bit flags describing the current status of sensor tracking. +/// The values must be the same as in enum StatusBits +/// +/// \see ovrTrackingState +/// +typedef enum ovrStatusBits_ +{ + ovrStatus_OrientationTracked = 0x0001, ///< Orientation is currently tracked (connected and in use). + ovrStatus_PositionTracked = 0x0002, ///< Position is currently tracked (false if out of range). + ovrStatus_EnumSize = 0x7fffffff ///< \internal Force type int32_t. +} ovrStatusBits; + + +/// Specifies the description of a single sensor. +/// +/// \see ovrGetTrackerDesc +/// +typedef struct OVR_ALIGNAS(OVR_PTR_SIZE) ovrTrackerDesc_ +{ + float FrustumHFovInRadians; ///< Sensor frustum horizontal field-of-view (if present). + float FrustumVFovInRadians; ///< Sensor frustum vertical field-of-view (if present). + float FrustumNearZInMeters; ///< Sensor frustum near Z (if present). + float FrustumFarZInMeters; ///< Sensor frustum far Z (if present). +} ovrTrackerDesc; + + +/// Specifies sensor flags. +/// +/// /see ovrTrackerPose +/// +typedef enum ovrTrackerFlags_ +{ + ovrTracker_Connected = 0x0020, ///< The sensor is present, else the sensor is absent or offline. + ovrTracker_PoseTracked = 0x0004 ///< The sensor has a valid pose, else the pose is unavailable. This will only be set if ovrTracker_Connected is set. +} ovrTrackerFlags; + + +/// Specifies the pose for a single sensor. +/// +typedef struct OVR_ALIGNAS(8) _ovrTrackerPose +{ + unsigned int TrackerFlags; ///< ovrTrackerFlags. + ovrPosef Pose; ///< The sensor's pose. This pose includes sensor tilt (roll and pitch). For a leveled coordinate system use LeveledPose. + ovrPosef LeveledPose; ///< The sensor's leveled pose, aligned with gravity. This value includes position and yaw of the sensor, but not roll and pitch. It can be used as a reference point to render real-world objects in the correct location. + OVR_UNUSED_STRUCT_PAD(pad0, 4) ///< \internal struct pad. +} ovrTrackerPose; + + +/// Tracking state at a given absolute time (describes predicted HMD pose, etc.). +/// Returned by ovr_GetTrackingState. +/// +/// \see ovr_GetTrackingState +/// +typedef struct OVR_ALIGNAS(8) ovrTrackingState_ +{ + /// Predicted head pose (and derivatives) at the requested absolute time. + ovrPoseStatef HeadPose; + + /// HeadPose tracking status described by ovrStatusBits. + unsigned int StatusFlags; + + /// The most recent calculated pose for each hand when hand controller tracking is present. + /// HandPoses[ovrHand_Left] refers to the left hand and HandPoses[ovrHand_Right] to the right hand. + /// These values can be combined with ovrInputState for complete hand controller information. + ovrPoseStatef HandPoses[2]; + + /// HandPoses status flags described by ovrStatusBits. + /// Only ovrStatus_OrientationTracked and ovrStatus_PositionTracked are reported. + unsigned int HandStatusFlags[2]; + + /// The pose of the origin captured during calibration. + /// Like all other poses here, this is expressed in the space set by ovr_RecenterTrackingOrigin, + /// and so will change every time that is called. This pose can be used to calculate + /// where the calibrated origin lands in the new recentered space. + /// If an application never calls ovr_RecenterTrackingOrigin, expect this value to be the identity + /// pose and as such will point respective origin based on ovrTrackingOrigin requested when + /// calling ovr_GetTrackingState. + ovrPosef CalibratedOrigin; + +} ovrTrackingState; + + +/// Rendering information for each eye. Computed by ovr_GetRenderDesc() based on the +/// specified FOV. Note that the rendering viewport is not included +/// here as it can be specified separately and modified per frame by +/// passing different Viewport values in the layer structure. +/// +/// \see ovr_GetRenderDesc +/// +typedef struct OVR_ALIGNAS(4) ovrEyeRenderDesc_ +{ + ovrEyeType Eye; ///< The eye index to which this instance corresponds. + ovrFovPort Fov; ///< The field of view. + ovrRecti DistortedViewport; ///< Distortion viewport. + ovrVector2f PixelsPerTanAngleAtCenter; ///< How many display pixels will fit in tan(angle) = 1. + ovrVector3f HmdToEyeOffset; ///< Translation of each eye, in meters. +} ovrEyeRenderDesc; + + +/// Projection information for ovrLayerEyeFovDepth. +/// +/// Use the utility function ovrTimewarpProjectionDesc_FromProjection to +/// generate this structure from the application's projection matrix. +/// +/// \see ovrLayerEyeFovDepth, ovrTimewarpProjectionDesc_FromProjection +/// +typedef struct OVR_ALIGNAS(4) ovrTimewarpProjectionDesc_ +{ + float Projection22; ///< Projection matrix element [2][2]. + float Projection23; ///< Projection matrix element [2][3]. + float Projection32; ///< Projection matrix element [3][2]. +} ovrTimewarpProjectionDesc; + + +/// Contains the data necessary to properly calculate position info for various layer types. +/// - HmdToEyeOffset is the same value pair provided in ovrEyeRenderDesc. +/// - HmdSpaceToWorldScaleInMeters is used to scale player motion into in-application units. +/// In other words, it is how big an in-application unit is in the player's physical meters. +/// For example, if the application uses inches as its units then HmdSpaceToWorldScaleInMeters would be 0.0254. +/// Note that if you are scaling the player in size, this must also scale. So if your application +/// units are inches, but you're shrinking the player to half their normal size, then +/// HmdSpaceToWorldScaleInMeters would be 0.0254*2.0. +/// +/// \see ovrEyeRenderDesc, ovr_SubmitFrame +/// +typedef struct OVR_ALIGNAS(4) ovrViewScaleDesc_ +{ + ovrVector3f HmdToEyeOffset[ovrEye_Count]; ///< Translation of each eye. + float HmdSpaceToWorldScaleInMeters; ///< Ratio of viewer units to meter units. +} ovrViewScaleDesc; + + +//----------------------------------------------------------------------------------- +// ***** Platform-independent Rendering Configuration + +/// The type of texture resource. +/// +/// \see ovrTextureSwapChainDesc +/// +typedef enum ovrTextureType_ +{ + ovrTexture_2D, ///< 2D textures. + ovrTexture_2D_External, ///< External 2D texture. Not used on PC + ovrTexture_Cube, ///< Cube maps. Not currently supported on PC. + ovrTexture_Count, + ovrTexture_EnumSize = 0x7fffffff ///< \internal Force type int32_t. +} ovrTextureType; + +/// The bindings required for texture swap chain. +/// +/// All texture swap chains are automatically bindable as shader +/// input resources since the Oculus runtime needs this to read them. +/// +/// \see ovrTextureSwapChainDesc +/// +typedef enum ovrTextureBindFlags_ +{ + ovrTextureBind_None, + ovrTextureBind_DX_RenderTarget = 0x0001, ///< The application can write into the chain with pixel shader + ovrTextureBind_DX_UnorderedAccess = 0x0002, ///< The application can write to the chain with compute shader + ovrTextureBind_DX_DepthStencil = 0x0004, ///< The chain buffers can be bound as depth and/or stencil buffers + + ovrTextureBind_EnumSize = 0x7fffffff ///< \internal Force type int32_t. +} ovrTextureBindFlags; + +/// The format of a texture. +/// +/// \see ovrTextureSwapChainDesc +/// +typedef enum ovrTextureFormat_ +{ + OVR_FORMAT_UNKNOWN, + OVR_FORMAT_B5G6R5_UNORM, ///< Not currently supported on PC. Would require a DirectX 11.1 device. + OVR_FORMAT_B5G5R5A1_UNORM, ///< Not currently supported on PC. Would require a DirectX 11.1 device. + OVR_FORMAT_B4G4R4A4_UNORM, ///< Not currently supported on PC. Would require a DirectX 11.1 device. + OVR_FORMAT_R8G8B8A8_UNORM, + OVR_FORMAT_R8G8B8A8_UNORM_SRGB, + OVR_FORMAT_B8G8R8A8_UNORM, + OVR_FORMAT_B8G8R8A8_UNORM_SRGB, ///< Not supported for OpenGL applications + OVR_FORMAT_B8G8R8X8_UNORM, ///< Not supported for OpenGL applications + OVR_FORMAT_B8G8R8X8_UNORM_SRGB, ///< Not supported for OpenGL applications + OVR_FORMAT_R16G16B16A16_FLOAT, + OVR_FORMAT_D16_UNORM, + OVR_FORMAT_D24_UNORM_S8_UINT, + OVR_FORMAT_D32_FLOAT, + OVR_FORMAT_D32_FLOAT_S8X24_UINT, + + OVR_FORMAT_ENUMSIZE = 0x7fffffff ///< \internal Force type int32_t. +} ovrTextureFormat; + +/// Misc flags overriding particular +/// behaviors of a texture swap chain +/// +/// \see ovrTextureSwapChainDesc +/// +typedef enum ovrTextureMiscFlags_ +{ + ovrTextureMisc_None, + + /// DX only: The underlying texture is created with a TYPELESS equivalent of the + /// format specified in the texture desc. The SDK will still access the + /// texture using the format specified in the texture desc, but the app can + /// create views with different formats if this is specified. + ovrTextureMisc_DX_Typeless = 0x0001, + + /// DX only: Allow generation of the mip chain on the GPU via the GenerateMips + /// call. This flag requires that RenderTarget binding also be specified. + ovrTextureMisc_AllowGenerateMips = 0x0002, + + /// Texture swap chain contains protected content, and requires + /// HDCP connection in order to display to HMD. Also prevents + /// mirroring or other redirection of any frame containing this contents + ovrTextureMisc_ProtectedContent = 0x0004, + + ovrTextureMisc_EnumSize = 0x7fffffff ///< \internal Force type int32_t. +} ovrTextureFlags; + +/// Description used to create a texture swap chain. +/// +/// \see ovr_CreateTextureSwapChainDX +/// \see ovr_CreateTextureSwapChainGL +/// +typedef struct ovrTextureSwapChainDesc_ +{ + ovrTextureType Type; + ovrTextureFormat Format; + int ArraySize; ///< Only supported with ovrTexture_2D. Not supported on PC at this time. + int Width; + int Height; + int MipLevels; + int SampleCount; ///< Current only supported on depth textures + ovrBool StaticImage; ///< Not buffered in a chain. For images that don't change + unsigned int MiscFlags; ///< ovrTextureFlags + unsigned int BindFlags; ///< ovrTextureBindFlags. Not used for GL. +} ovrTextureSwapChainDesc; + +/// Description used to create a mirror texture. +/// +/// \see ovr_CreateMirrorTextureDX +/// \see ovr_CreateMirrorTextureGL +/// +typedef struct ovrMirrorTextureDesc_ +{ + ovrTextureFormat Format; + int Width; + int Height; + unsigned int MiscFlags; ///< ovrTextureFlags +} ovrMirrorTextureDesc; + +typedef struct ovrTextureSwapChainData* ovrTextureSwapChain; +typedef struct ovrMirrorTextureData* ovrMirrorTexture; + +//----------------------------------------------------------------------------------- + +/// Describes button input types. +/// Button inputs are combined; that is they will be reported as pressed if they are +/// pressed on either one of the two devices. +/// The ovrButton_Up/Down/Left/Right map to both XBox D-Pad and directional buttons. +/// The ovrButton_Enter and ovrButton_Return map to Start and Back controller buttons, respectively. +typedef enum ovrButton_ +{ + ovrButton_A = 0x00000001, + ovrButton_B = 0x00000002, + ovrButton_RThumb = 0x00000004, + ovrButton_RShoulder = 0x00000008, + + // Bit mask of all buttons on the right Touch controller + ovrButton_RMask = ovrButton_A | ovrButton_B | ovrButton_RThumb | ovrButton_RShoulder, + + ovrButton_X = 0x00000100, + ovrButton_Y = 0x00000200, + ovrButton_LThumb = 0x00000400, + ovrButton_LShoulder = 0x00000800, + + // Bit mask of all buttons on the left Touch controller + ovrButton_LMask = ovrButton_X | ovrButton_Y | ovrButton_LThumb | ovrButton_LShoulder, + + // Navigation through DPad. + ovrButton_Up = 0x00010000, + ovrButton_Down = 0x00020000, + ovrButton_Left = 0x00040000, + ovrButton_Right = 0x00080000, + ovrButton_Enter = 0x00100000, // Start on XBox controller. + ovrButton_Back = 0x00200000, // Back on Xbox controller. + ovrButton_VolUp = 0x00400000, // only supported by Remote. + ovrButton_VolDown = 0x00800000, // only supported by Remote. + ovrButton_Home = 0x01000000, + ovrButton_Private = ovrButton_VolUp | ovrButton_VolDown | ovrButton_Home, + + + ovrButton_EnumSize = 0x7fffffff ///< \internal Force type int32_t. +} ovrButton; + +/// Describes touch input types. +/// These values map to capacitive touch values reported ovrInputState::Touch. +/// Some of these values are mapped to button bits for consistency. +typedef enum ovrTouch_ +{ + ovrTouch_A = ovrButton_A, + ovrTouch_B = ovrButton_B, + ovrTouch_RThumb = ovrButton_RThumb, + ovrTouch_RIndexTrigger = 0x00000010, + + // Bit mask of all the button touches on the right controller + ovrTouch_RButtonMask = ovrTouch_A | ovrTouch_B | ovrTouch_RThumb | ovrTouch_RIndexTrigger, + + ovrTouch_X = ovrButton_X, + ovrTouch_Y = ovrButton_Y, + ovrTouch_LThumb = ovrButton_LThumb, + ovrTouch_LIndexTrigger = 0x00001000, + + // Bit mask of all the button touches on the left controller + ovrTouch_LButtonMask = ovrTouch_X | ovrTouch_Y | ovrTouch_LThumb | ovrTouch_LIndexTrigger, + + // Finger pose state + // Derived internally based on distance, proximity to sensors and filtering. + ovrTouch_RIndexPointing = 0x00000020, + ovrTouch_RThumbUp = 0x00000040, + + // Bit mask of all right controller poses + ovrTouch_RPoseMask = ovrTouch_RIndexPointing | ovrTouch_RThumbUp, + + ovrTouch_LIndexPointing = 0x00002000, + ovrTouch_LThumbUp = 0x00004000, + + // Bit mask of all left controller poses + ovrTouch_LPoseMask = ovrTouch_LIndexPointing | ovrTouch_LThumbUp, + + ovrTouch_EnumSize = 0x7fffffff ///< \internal Force type int32_t. +} ovrTouch; + +/// Specifies which controller is connected; multiple can be connected at once. +typedef enum ovrControllerType_ +{ + ovrControllerType_None = 0x00, + ovrControllerType_LTouch = 0x01, + ovrControllerType_RTouch = 0x02, + ovrControllerType_Touch = 0x03, + ovrControllerType_Remote = 0x04, + ovrControllerType_XBox = 0x10, + + ovrControllerType_Active = 0xff, ///< Operate on or query whichever controller is active. + + ovrControllerType_EnumSize = 0x7fffffff ///< \internal Force type int32_t. +} ovrControllerType; + + +/// Provides names for the left and right hand array indexes. +/// +/// \see ovrInputState, ovrTrackingState +/// +typedef enum ovrHandType_ +{ + ovrHand_Left = 0, + ovrHand_Right = 1, + ovrHand_Count = 2, + ovrHand_EnumSize = 0x7fffffff ///< \internal Force type int32_t. +} ovrHandType; + + + +/// ovrInputState describes the complete controller input state, including Oculus Touch, +/// and XBox gamepad. If multiple inputs are connected and used at the same time, +/// their inputs are combined. +typedef struct ovrInputState_ +{ + // System type when the controller state was last updated. + double TimeInSeconds; + + // Values for buttons described by ovrButton. + unsigned int Buttons; + + // Touch values for buttons and sensors as described by ovrTouch. + unsigned int Touches; + + // Left and right finger trigger values (ovrHand_Left and ovrHand_Right), in the range 0.0 to 1.0f. + float IndexTrigger[ovrHand_Count]; + + // Left and right hand trigger values (ovrHand_Left and ovrHand_Right), in the range 0.0 to 1.0f. + float HandTrigger[ovrHand_Count]; + + // Horizontal and vertical thumbstick axis values (ovrHand_Left and ovrHand_Right), in the range -1.0f to 1.0f. + ovrVector2f Thumbstick[ovrHand_Count]; + + // The type of the controller this state is for. + ovrControllerType ControllerType; + +} ovrInputState; + + + +//----------------------------------------------------------------------------------- +// ***** Initialize structures + +/// Initialization flags. +/// +/// \see ovrInitParams, ovr_Initialize +/// +typedef enum ovrInitFlags_ +{ + /// When a debug library is requested, a slower debugging version of the library will + /// run which can be used to help solve problems in the library and debug application code. + ovrInit_Debug = 0x00000001, + + /// When a version is requested, the LibOVR runtime respects the RequestedMinorVersion + /// field and verifies that the RequestedMinorVersion is supported. + ovrInit_RequestVersion = 0x00000004, + + // These bits are writable by user code. + ovrinit_WritableBits = 0x00ffffff, + + ovrInit_EnumSize = 0x7fffffff ///< \internal Force type int32_t. +} ovrInitFlags; + + +/// Logging levels +/// +/// \see ovrInitParams, ovrLogCallback +/// +typedef enum ovrLogLevel_ +{ + ovrLogLevel_Debug = 0, ///< Debug-level log event. + ovrLogLevel_Info = 1, ///< Info-level log event. + ovrLogLevel_Error = 2, ///< Error-level log event. + + ovrLogLevel_EnumSize = 0x7fffffff ///< \internal Force type int32_t. +} ovrLogLevel; + + +/// Signature of the logging callback function pointer type. +/// +/// \param[in] userData is an arbitrary value specified by the user of ovrInitParams. +/// \param[in] level is one of the ovrLogLevel constants. +/// \param[in] message is a UTF8-encoded null-terminated string. +/// \see ovrInitParams, ovrLogLevel, ovr_Initialize +/// +typedef void (OVR_CDECL* ovrLogCallback)(uintptr_t userData, int level, const char* message); + + +/// Parameters for ovr_Initialize. +/// +/// \see ovr_Initialize +/// +typedef struct OVR_ALIGNAS(8) ovrInitParams_ +{ + /// Flags from ovrInitFlags to override default behavior. + /// Use 0 for the defaults. + uint32_t Flags; + + /// Requests a specific minimum minor version of the LibOVR runtime. + /// Flags must include ovrInit_RequestVersion or this will be ignored + /// and OVR_MINOR_VERSION will be used. + uint32_t RequestedMinorVersion; + + /// User-supplied log callback function, which may be called at any time + /// asynchronously from multiple threads until ovr_Shutdown completes. + /// Use NULL to specify no log callback. + ovrLogCallback LogCallback; + + /// User-supplied data which is passed as-is to LogCallback. Typically this + /// is used to store an application-specific pointer which is read in the + /// callback function. + uintptr_t UserData; + + /// Relative number of milliseconds to wait for a connection to the server + /// before failing. Use 0 for the default timeout. + uint32_t ConnectionTimeoutMS; + + OVR_ON64(OVR_UNUSED_STRUCT_PAD(pad0, 4)) ///< \internal + +} ovrInitParams; + + +#ifdef __cplusplus +extern "C" { +#endif + + +// ----------------------------------------------------------------------------------- +// ***** API Interfaces + +// Overview of the API +// +// Setup: +// - ovr_Initialize(). +// - ovr_Create(&hmd, &graphicsId). +// - Use hmd members and ovr_GetFovTextureSize() to determine graphics configuration +// and ovr_GetRenderDesc() to get per-eye rendering parameters. +// - Allocate texture swap chains with ovr_CreateTextureSwapChainDX() or +// ovr_CreateTextureSwapChainGL(). Create any associated render target views or +// frame buffer objects. +// +// Application Loop: +// - Call ovr_GetPredictedDisplayTime() to get the current frame timing information. +// - Call ovr_GetTrackingState() and ovr_CalcEyePoses() to obtain the predicted +// rendering pose for each eye based on timing. +// - Render the scene content into the current buffer of the texture swapchains +// for each eye and layer you plan to update this frame. If you render into a +// texture swap chain, you must call ovr_CommitTextureSwapChain() on it to commit +// the changes before you reference the chain this frame (otherwise, your latest +// changes won't be picked up). +// - Call ovr_SubmitFrame() to render the distorted layers to and present them on the HMD. +// If ovr_SubmitFrame returns ovrSuccess_NotVisible, there is no need to render the scene +// for the next loop iteration. Instead, just call ovr_SubmitFrame again until it returns +// ovrSuccess. +// +// Shutdown: +// - ovr_Destroy(). +// - ovr_Shutdown(). + + +/// Initializes LibOVR +/// +/// Initialize LibOVR for application usage. This includes finding and loading the LibOVRRT +/// shared library. No LibOVR API functions, other than ovr_GetLastErrorInfo and ovr_Detect, can +/// be called unless ovr_Initialize succeeds. A successful call to ovr_Initialize must be eventually +/// followed by a call to ovr_Shutdown. ovr_Initialize calls are idempotent. +/// Calling ovr_Initialize twice does not require two matching calls to ovr_Shutdown. +/// If already initialized, the return value is ovr_Success. +/// +/// LibOVRRT shared library search order: +/// -# Current working directory (often the same as the application directory). +/// -# Module directory (usually the same as the application directory, +/// but not if the module is a separate shared library). +/// -# Application directory +/// -# Development directory (only if OVR_ENABLE_DEVELOPER_SEARCH is enabled, +/// which is off by default). +/// -# Standard OS shared library search location(s) (OS-specific). +/// +/// \param params Specifies custom initialization options. May be NULL to indicate default options. +/// \return Returns an ovrResult indicating success or failure. In the case of failure, use +/// ovr_GetLastErrorInfo to get more information. Example failed results include: +/// - ovrError_Initialize: Generic initialization error. +/// - ovrError_LibLoad: Couldn't load LibOVRRT. +/// - ovrError_LibVersion: LibOVRRT version incompatibility. +/// - ovrError_ServiceConnection: Couldn't connect to the OVR Service. +/// - ovrError_ServiceVersion: OVR Service version incompatibility. +/// - ovrError_IncompatibleOS: The operating system version is incompatible. +/// - ovrError_DisplayInit: Unable to initialize the HMD display. +/// - ovrError_ServerStart: Unable to start the server. Is it already running? +/// - ovrError_Reinitialization: Attempted to re-initialize with a different version. +/// +/// Example code +/// \code{.cpp} +/// ovrResult result = ovr_Initialize(NULL); +/// if(OVR_FAILURE(result)) { +/// ovrErrorInfo errorInfo; +/// ovr_GetLastErrorInfo(&errorInfo); +/// DebugLog("ovr_Initialize failed: %s", errorInfo.ErrorString); +/// return false; +/// } +/// [...] +/// \endcode +/// +/// \see ovr_Shutdown +/// +OVR_PUBLIC_FUNCTION(ovrResult) ovr_Initialize(const ovrInitParams* params); + + +/// Shuts down LibOVR +/// +/// A successful call to ovr_Initialize must be eventually matched by a call to ovr_Shutdown. +/// After calling ovr_Shutdown, no LibOVR functions can be called except ovr_GetLastErrorInfo +/// or another ovr_Initialize. ovr_Shutdown invalidates all pointers, references, and created objects +/// previously returned by LibOVR functions. The LibOVRRT shared library can be unloaded by +/// ovr_Shutdown. +/// +/// \see ovr_Initialize +/// +OVR_PUBLIC_FUNCTION(void) ovr_Shutdown(); + +/// Returns information about the most recent failed return value by the +/// current thread for this library. +/// +/// This function itself can never generate an error. +/// The last error is never cleared by LibOVR, but will be overwritten by new errors. +/// Do not use this call to determine if there was an error in the last API +/// call as successful API calls don't clear the last ovrErrorInfo. +/// To avoid any inconsistency, ovr_GetLastErrorInfo should be called immediately +/// after an API function that returned a failed ovrResult, with no other API +/// functions called in the interim. +/// +/// \param[out] errorInfo The last ovrErrorInfo for the current thread. +/// +/// \see ovrErrorInfo +/// +OVR_PUBLIC_FUNCTION(void) ovr_GetLastErrorInfo(ovrErrorInfo* errorInfo); + + +/// Returns the version string representing the LibOVRRT version. +/// +/// The returned string pointer is valid until the next call to ovr_Shutdown. +/// +/// Note that the returned version string doesn't necessarily match the current +/// OVR_MAJOR_VERSION, etc., as the returned string refers to the LibOVRRT shared +/// library version and not the locally compiled interface version. +/// +/// The format of this string is subject to change in future versions and its contents +/// should not be interpreted. +/// +/// \return Returns a UTF8-encoded null-terminated version string. +/// +OVR_PUBLIC_FUNCTION(const char*) ovr_GetVersionString(); + + +/// Writes a message string to the LibOVR tracing mechanism (if enabled). +/// +/// This message will be passed back to the application via the ovrLogCallback if +/// it was registered. +/// +/// \param[in] level One of the ovrLogLevel constants. +/// \param[in] message A UTF8-encoded null-terminated string. +/// \return returns the strlen of the message or a negative value if the message is too large. +/// +/// \see ovrLogLevel, ovrLogCallback +/// +OVR_PUBLIC_FUNCTION(int) ovr_TraceMessage(int level, const char* message); + + +//------------------------------------------------------------------------------------- +/// @name HMD Management +/// +/// Handles the enumeration, creation, destruction, and properties of an HMD (head-mounted display). +///@{ + + +/// Returns information about the current HMD. +/// +/// ovr_Initialize must have first been called in order for this to succeed, otherwise ovrHmdDesc::Type +/// will be reported as ovrHmd_None. +/// +/// \param[in] session Specifies an ovrSession previously returned by ovr_Create, else NULL in which +/// case this function detects whether an HMD is present and returns its info if so. +/// +/// \return Returns an ovrHmdDesc. If the hmd is NULL and ovrHmdDesc::Type is ovrHmd_None then +/// no HMD is present. +/// +OVR_PUBLIC_FUNCTION(ovrHmdDesc) ovr_GetHmdDesc(ovrSession session); + + +/// Returns the number of sensors. +/// +/// The number of sensors may change at any time, so this function should be called before use +/// as opposed to once on startup. +/// +/// \param[in] session Specifies an ovrSession previously returned by ovr_Create. +/// +/// \return Returns unsigned int count. +/// +OVR_PUBLIC_FUNCTION(unsigned int) ovr_GetTrackerCount(ovrSession session); + + +/// Returns a given sensor description. +/// +/// It's possible that sensor desc [0] may indicate a unconnnected or non-pose tracked sensor, but +/// sensor desc [1] may be connected. +/// +/// ovr_Initialize must have first been called in order for this to succeed, otherwise the returned +/// trackerDescArray will be zero-initialized. The data returned by this function can change at runtime. +/// +/// \param[in] session Specifies an ovrSession previously returned by ovr_Create. +/// +/// \param[in] trackerDescIndex Specifies a sensor index. The valid indexes are in the range of 0 to +/// the sensor count returned by ovr_GetTrackerCount. +/// +/// \return Returns ovrTrackerDesc. An empty ovrTrackerDesc will be returned if trackerDescIndex is out of range. +/// +/// \see ovrTrackerDesc, ovr_GetTrackerCount +/// +OVR_PUBLIC_FUNCTION(ovrTrackerDesc) ovr_GetTrackerDesc(ovrSession session, unsigned int trackerDescIndex); + + +/// Creates a handle to a VR session. +/// +/// Upon success the returned ovrSession must be eventually freed with ovr_Destroy when it is no longer needed. +/// A second call to ovr_Create will result in an error return value if the previous Hmd has not been destroyed. +/// +/// \param[out] pSession Provides a pointer to an ovrSession which will be written to upon success. +/// \param[out] luid Provides a system specific graphics adapter identifier that locates which +/// graphics adapter has the HMD attached. This must match the adapter used by the application +/// or no rendering output will be possible. This is important for stability on multi-adapter systems. An +/// application that simply chooses the default adapter will not run reliably on multi-adapter systems. +/// \return Returns an ovrResult indicating success or failure. Upon failure +/// the returned pHmd will be NULL. +/// +/// Example code +/// \code{.cpp} +/// ovrSession session; +/// ovrGraphicsLuid luid; +/// ovrResult result = ovr_Create(&session, &luid); +/// if(OVR_FAILURE(result)) +/// ... +/// \endcode +/// +/// \see ovr_Destroy +/// +OVR_PUBLIC_FUNCTION(ovrResult) ovr_Create(ovrSession* pSession, ovrGraphicsLuid* pLuid); + + +/// Destroys the HMD. +/// +/// \param[in] session Specifies an ovrSession previously returned by ovr_Create. +/// \see ovr_Create +/// +OVR_PUBLIC_FUNCTION(void) ovr_Destroy(ovrSession session); + + +/// Specifies status information for the current session. +/// +/// \see ovr_GetSessionStatus +/// +typedef struct ovrSessionStatus_ +{ + ovrBool IsVisible; ///< True if the process has VR focus and thus is visible in the HMD. + ovrBool HmdPresent; ///< True if an HMD is present. + ovrBool HmdMounted; ///< True if the HMD is on the user's head. + ovrBool DisplayLost; ///< True if the session is in a display-lost state. See ovr_SubmitFrame. + ovrBool ShouldQuit; ///< True if the application should initiate shutdown. + ovrBool ShouldRecenter; ///< True if UX has requested re-centering. Must call ovr_ClearShouldRecenterFlag or ovr_RecenterTrackingOrigin. +}ovrSessionStatus; + + +/// Returns status information for the application. +/// +/// \param[in] session Specifies an ovrSession previously returned by ovr_Create. +/// \param[out] sessionStatus Provides an ovrSessionStatus that is filled in. +/// +/// \return Returns an ovrResult indicating success or failure. In the case of +/// failure, use ovr_GetLastErrorInfo to get more information. +// Return values include but aren't limited to: +/// - ovrSuccess: Completed successfully. +/// - ovrError_ServiceConnection: The service connection was lost and the application +// must destroy the session. +/// +OVR_PUBLIC_FUNCTION(ovrResult) ovr_GetSessionStatus(ovrSession session, ovrSessionStatus* sessionStatus); + + +//@} + + + +//------------------------------------------------------------------------------------- +/// @name Tracking +/// +/// Tracking functions handle the position, orientation, and movement of the HMD in space. +/// +/// All tracking interface functions are thread-safe, allowing tracking state to be sampled +/// from different threads. +/// +///@{ + + + +/// Sets the tracking origin type +/// +/// When the tracking origin is changed, all of the calls that either provide +/// or accept ovrPosef will use the new tracking origin provided. +/// +/// \param[in] session Specifies an ovrSession previously returned by ovr_Create. +/// \param[in] origin Specifies an ovrTrackingOrigin to be used for all ovrPosef +/// +/// \return Returns an ovrResult indicating success or failure. In the case of failure, use +/// ovr_GetLastErrorInfo to get more information. +/// +/// \see ovrTrackingOrigin, ovr_GetTrackingOriginType +OVR_PUBLIC_FUNCTION(ovrResult) ovr_SetTrackingOriginType(ovrSession session, ovrTrackingOrigin origin); + + +/// Gets the tracking origin state +/// +/// \param[in] session Specifies an ovrSession previously returned by ovr_Create. +/// +/// \return Returns the ovrTrackingOrigin that was either set by default, or previous set by the application. +/// +/// \see ovrTrackingOrigin, ovr_SetTrackingOriginType +OVR_PUBLIC_FUNCTION(ovrTrackingOrigin) ovr_GetTrackingOriginType(ovrSession session); + + +/// Re-centers the sensor position and orientation. +/// +/// This resets the (x,y,z) positional components and the yaw orientation component. +/// The Roll and pitch orientation components are always determined by gravity and cannot +/// be redefined. All future tracking will report values relative to this new reference position. +/// If you are using ovrTrackerPoses then you will need to call ovr_GetTrackerPose after +/// this, because the sensor position(s) will change as a result of this. +/// +/// The headset cannot be facing vertically upward or downward but rather must be roughly +/// level otherwise this function will fail with ovrError_InvalidHeadsetOrientation. +/// +/// For more info, see the notes on each ovrTrackingOrigin enumeration to understand how +/// recenter will vary slightly in its behavior based on the current ovrTrackingOrigin setting. +/// +/// \param[in] session Specifies an ovrSession previously returned by ovr_Create. +/// +/// \return Returns an ovrResult indicating success or failure. In the case of failure, use +/// ovr_GetLastErrorInfo to get more information. Return values include but aren't limited to: +/// - ovrSuccess: Completed successfully. +/// - ovrError_InvalidHeadsetOrientation: The headset was facing an invalid direction when +/// attempting recentering, such as facing vertically. +/// +/// \see ovrTrackingOrigin, ovr_GetTrackerPose +/// +OVR_PUBLIC_FUNCTION(ovrResult) ovr_RecenterTrackingOrigin(ovrSession session); + + +/// Clears the ShouldRecenter status bit in ovrSessionStatus. +/// +/// Clears the ShouldRecenter status bit in ovrSessionStatus, allowing further recenter +/// requests to be detected. Since this is automatically done by ovr_RecenterTrackingOrigin, +/// this is only needs to be called when application is doing its own re-centering. +OVR_PUBLIC_FUNCTION(void) ovr_ClearShouldRecenterFlag(ovrSession session); + + +/// Returns tracking state reading based on the specified absolute system time. +/// +/// Pass an absTime value of 0.0 to request the most recent sensor reading. In this case +/// both PredictedPose and SamplePose will have the same value. +/// +/// This may also be used for more refined timing of front buffer rendering logic, and so on. +/// This may be called by multiple threads. +/// +/// \param[in] session Specifies an ovrSession previously returned by ovr_Create. +/// \param[in] absTime Specifies the absolute future time to predict the return +/// ovrTrackingState value. Use 0 to request the most recent tracking state. +/// \param[in] latencyMarker Specifies that this call is the point in time where +/// the "App-to-Mid-Photon" latency timer starts from. If a given ovrLayer +/// provides "SensorSampleTimestamp", that will override the value stored here. +/// \return Returns the ovrTrackingState that is predicted for the given absTime. +/// +/// \see ovrTrackingState, ovr_GetEyePoses, ovr_GetTimeInSeconds +/// +OVR_PUBLIC_FUNCTION(ovrTrackingState) ovr_GetTrackingState(ovrSession session, double absTime, ovrBool latencyMarker); + + + +/// Returns the ovrTrackerPose for the given sensor. +/// +/// \param[in] session Specifies an ovrSession previously returned by ovr_Create. +/// \param[in] trackerPoseIndex Index of the sensor being requested. +/// +/// \return Returns the requested ovrTrackerPose. An empty ovrTrackerPose will be returned if trackerPoseIndex is out of range. +/// +/// \see ovr_GetTrackerCount +/// +OVR_PUBLIC_FUNCTION(ovrTrackerPose) ovr_GetTrackerPose(ovrSession session, unsigned int trackerPoseIndex); + + + +/// Returns the most recent input state for controllers, without positional tracking info. +/// +/// \param[out] inputState Input state that will be filled in. +/// \param[in] ovrControllerType Specifies which controller the input will be returned for. +/// \return Returns ovrSuccess if the new state was successfully obtained. +/// +/// \see ovrControllerType +/// +OVR_PUBLIC_FUNCTION(ovrResult) ovr_GetInputState(ovrSession session, ovrControllerType controllerType, ovrInputState* inputState); + + +/// Returns controller types connected to the system OR'ed together. +/// +/// \return A bitmask of ovrControllerTypes connected to the system. +/// +/// \see ovrControllerType +/// +OVR_PUBLIC_FUNCTION(unsigned int) ovr_GetConnectedControllerTypes(ovrSession session); + + +/// Turns on vibration of the given controller. +/// +/// To disable vibration, call ovr_SetControllerVibration with an amplitude of 0. +/// Vibration automatically stops after a nominal amount of time, so if you want vibration +/// to be continuous over multiple seconds then you need to call this function periodically. +/// +/// \param[in] session Specifies an ovrSession previously returned by ovr_Create. +/// \param[in] controllerType Specifies the controller to apply the vibration to. +/// \param[in] frequency Specifies a vibration frequency in the range of 0.0 to 1.0. +/// Currently the only valid values are 0.0, 0.5, and 1.0 and other values will +/// be clamped to one of these. +/// \param[in] amplitude Specifies a vibration amplitude in the range of 0.0 to 1.0. +/// +/// \return Returns ovrSuccess upon success. +/// +/// \see ovrControllerType +/// +OVR_PUBLIC_FUNCTION(ovrResult) ovr_SetControllerVibration(ovrSession session, ovrControllerType controllerType, + float frequency, float amplitude); + +///@} + + +//------------------------------------------------------------------------------------- +// @name Layers +// +///@{ + + +/// Specifies the maximum number of layers supported by ovr_SubmitFrame. +/// +/// /see ovr_SubmitFrame +/// +enum { + ovrMaxLayerCount = 16 +}; + +/// Describes layer types that can be passed to ovr_SubmitFrame. +/// Each layer type has an associated struct, such as ovrLayerEyeFov. +/// +/// \see ovrLayerHeader +/// +typedef enum ovrLayerType_ +{ + ovrLayerType_Disabled = 0, ///< Layer is disabled. + ovrLayerType_EyeFov = 1, ///< Described by ovrLayerEyeFov. + ovrLayerType_Quad = 3, ///< Described by ovrLayerQuad. Previously called ovrLayerType_QuadInWorld. + /// enum 4 used to be ovrLayerType_QuadHeadLocked. Instead, use ovrLayerType_Quad with ovrLayerFlag_HeadLocked. + ovrLayerType_EyeMatrix = 5, ///< Described by ovrLayerEyeMatrix. + ovrLayerType_EnumSize = 0x7fffffff ///< Force type int32_t. +} ovrLayerType; + + +/// Identifies flags used by ovrLayerHeader and which are passed to ovr_SubmitFrame. +/// +/// \see ovrLayerHeader +/// +typedef enum ovrLayerFlags_ +{ + /// ovrLayerFlag_HighQuality enables 4x anisotropic sampling during the composition of the layer. + /// The benefits are mostly visible at the periphery for high-frequency & high-contrast visuals. + /// For best results consider combining this flag with an ovrTextureSwapChain that has mipmaps and + /// instead of using arbitrary sized textures, prefer texture sizes that are powers-of-two. + /// Actual rendered viewport and doesn't necessarily have to fill the whole texture. + ovrLayerFlag_HighQuality = 0x01, + + /// ovrLayerFlag_TextureOriginAtBottomLeft: the opposite is TopLeft. + /// Generally this is false for D3D, true for OpenGL. + ovrLayerFlag_TextureOriginAtBottomLeft = 0x02, + + /// Mark this surface as "headlocked", which means it is specified + /// relative to the HMD and moves with it, rather than being specified + /// relative to sensor/torso space and remaining still while the head moves. + /// What used to be ovrLayerType_QuadHeadLocked is now ovrLayerType_Quad plus this flag. + /// However the flag can be applied to any layer type to achieve a similar effect. + ovrLayerFlag_HeadLocked = 0x04 + +} ovrLayerFlags; + + +/// Defines properties shared by all ovrLayer structs, such as ovrLayerEyeFov. +/// +/// ovrLayerHeader is used as a base member in these larger structs. +/// This struct cannot be used by itself except for the case that Type is ovrLayerType_Disabled. +/// +/// \see ovrLayerType, ovrLayerFlags +/// +typedef struct OVR_ALIGNAS(OVR_PTR_SIZE) ovrLayerHeader_ +{ + ovrLayerType Type; ///< Described by ovrLayerType. + unsigned Flags; ///< Described by ovrLayerFlags. +} ovrLayerHeader; + + +/// Describes a layer that specifies a monoscopic or stereoscopic view. +/// This is the kind of layer that's typically used as layer 0 to ovr_SubmitFrame, +/// as it is the kind of layer used to render a 3D stereoscopic view. +/// +/// Three options exist with respect to mono/stereo texture usage: +/// - ColorTexture[0] and ColorTexture[1] contain the left and right stereo renderings, respectively. +/// Viewport[0] and Viewport[1] refer to ColorTexture[0] and ColorTexture[1], respectively. +/// - ColorTexture[0] contains both the left and right renderings, ColorTexture[1] is NULL, +/// and Viewport[0] and Viewport[1] refer to sub-rects with ColorTexture[0]. +/// - ColorTexture[0] contains a single monoscopic rendering, and Viewport[0] and +/// Viewport[1] both refer to that rendering. +/// +/// \see ovrTextureSwapChain, ovr_SubmitFrame +/// +typedef struct OVR_ALIGNAS(OVR_PTR_SIZE) ovrLayerEyeFov_ +{ + /// Header.Type must be ovrLayerType_EyeFov. + ovrLayerHeader Header; + + /// ovrTextureSwapChains for the left and right eye respectively. + /// The second one of which can be NULL for cases described above. + ovrTextureSwapChain ColorTexture[ovrEye_Count]; + + /// Specifies the ColorTexture sub-rect UV coordinates. + /// Both Viewport[0] and Viewport[1] must be valid. + ovrRecti Viewport[ovrEye_Count]; + + /// The viewport field of view. + ovrFovPort Fov[ovrEye_Count]; + + /// Specifies the position and orientation of each eye view, with the position specified in meters. + /// RenderPose will typically be the value returned from ovr_CalcEyePoses, + /// but can be different in special cases if a different head pose is used for rendering. + ovrPosef RenderPose[ovrEye_Count]; + + /// Specifies the timestamp when the source ovrPosef (used in calculating RenderPose) + /// was sampled from the SDK. Typically retrieved by calling ovr_GetTimeInSeconds + /// around the instant the application calls ovr_GetTrackingState + /// The main purpose for this is to accurately track app tracking latency. + double SensorSampleTime; + +} ovrLayerEyeFov; + + + + +/// Describes a layer that specifies a monoscopic or stereoscopic view. +/// This uses a direct 3x4 matrix to map from view space to the UV coordinates. +/// It is essentially the same thing as ovrLayerEyeFov but using a much +/// lower level. This is mainly to provide compatibility with specific apps. +/// Unless the application really requires this flexibility, it is usually better +/// to use ovrLayerEyeFov. +/// +/// Three options exist with respect to mono/stereo texture usage: +/// - ColorTexture[0] and ColorTexture[1] contain the left and right stereo renderings, respectively. +/// Viewport[0] and Viewport[1] refer to ColorTexture[0] and ColorTexture[1], respectively. +/// - ColorTexture[0] contains both the left and right renderings, ColorTexture[1] is NULL, +/// and Viewport[0] and Viewport[1] refer to sub-rects with ColorTexture[0]. +/// - ColorTexture[0] contains a single monoscopic rendering, and Viewport[0] and +/// Viewport[1] both refer to that rendering. +/// +/// \see ovrTextureSwapChain, ovr_SubmitFrame +/// +typedef struct OVR_ALIGNAS(OVR_PTR_SIZE) ovrLayerEyeMatrix_ +{ + /// Header.Type must be ovrLayerType_EyeMatrix. + ovrLayerHeader Header; + + /// ovrTextureSwapChains for the left and right eye respectively. + /// The second one of which can be NULL for cases described above. + ovrTextureSwapChain ColorTexture[ovrEye_Count]; + + /// Specifies the ColorTexture sub-rect UV coordinates. + /// Both Viewport[0] and Viewport[1] must be valid. + ovrRecti Viewport[ovrEye_Count]; + + /// Specifies the position and orientation of each eye view, with the position specified in meters. + /// RenderPose will typically be the value returned from ovr_CalcEyePoses, + /// but can be different in special cases if a different head pose is used for rendering. + ovrPosef RenderPose[ovrEye_Count]; + + /// Specifies the mapping from a view-space vector + /// to a UV coordinate on the textures given above. + /// P = (x,y,z,1)*Matrix + /// TexU = P.x/P.z + /// TexV = P.y/P.z + ovrMatrix4f Matrix[ovrEye_Count]; + + /// Specifies the timestamp when the source ovrPosef (used in calculating RenderPose) + /// was sampled from the SDK. Typically retrieved by calling ovr_GetTimeInSeconds + /// around the instant the application calls ovr_GetTrackingState + /// The main purpose for this is to accurately track app tracking latency. + double SensorSampleTime; + +} ovrLayerEyeMatrix; + + + + + +/// Describes a layer of Quad type, which is a single quad in world or viewer space. +/// It is used for ovrLayerType_Quad. This type of layer represents a single +/// object placed in the world and not a stereo view of the world itself. +/// +/// A typical use of ovrLayerType_Quad is to draw a television screen in a room +/// that for some reason is more convenient to draw as a layer than as part of the main +/// view in layer 0. For example, it could implement a 3D popup GUI that is drawn at a +/// higher resolution than layer 0 to improve fidelity of the GUI. +/// +/// Quad layers are visible from both sides; they are not back-face culled. +/// +/// \see ovrTextureSwapChain, ovr_SubmitFrame +/// +typedef struct OVR_ALIGNAS(OVR_PTR_SIZE) ovrLayerQuad_ +{ + /// Header.Type must be ovrLayerType_Quad. + ovrLayerHeader Header; + + /// Contains a single image, never with any stereo view. + ovrTextureSwapChain ColorTexture; + + /// Specifies the ColorTexture sub-rect UV coordinates. + ovrRecti Viewport; + + /// Specifies the orientation and position of the center point of a Quad layer type. + /// The supplied direction is the vector perpendicular to the quad. + /// The position is in real-world meters (not the application's virtual world, + /// the physical world the user is in) and is relative to the "zero" position + /// set by ovr_RecenterTrackingOrigin unless the ovrLayerFlag_HeadLocked flag is used. + ovrPosef QuadPoseCenter; + + /// Width and height (respectively) of the quad in meters. + ovrVector2f QuadSize; + +} ovrLayerQuad; + + + + +/// Union that combines ovrLayer types in a way that allows them +/// to be used in a polymorphic way. +typedef union ovrLayer_Union_ +{ + ovrLayerHeader Header; + ovrLayerEyeFov EyeFov; + ovrLayerQuad Quad; +} ovrLayer_Union; + + +//@} + + + +/// @name SDK Distortion Rendering +/// +/// All of rendering functions including the configure and frame functions +/// are not thread safe. It is OK to use ConfigureRendering on one thread and handle +/// frames on another thread, but explicit synchronization must be done since +/// functions that depend on configured state are not reentrant. +/// +/// These functions support rendering of distortion by the SDK. +/// +//@{ + +/// TextureSwapChain creation is rendering API-specific. +/// ovr_CreateTextureSwapChainDX and ovr_CreateTextureSwapChainGL can be found in the +/// rendering API-specific headers, such as OVR_CAPI_D3D.h and OVR_CAPI_GL.h + +/// Gets the number of buffers in an ovrTextureSwapChain. +/// +/// \param[in] session Specifies an ovrSession previously returned by ovr_Create. +/// \param[in] chain Specifies the ovrTextureSwapChain for which the length should be retrieved. +/// \param[out] out_Length Returns the number of buffers in the specified chain. +/// +/// \return Returns an ovrResult for which OVR_SUCCESS(result) is false upon error. +/// +/// \see ovr_CreateTextureSwapChainDX, ovr_CreateTextureSwapChainGL +/// +OVR_PUBLIC_FUNCTION(ovrResult) ovr_GetTextureSwapChainLength(ovrSession session, ovrTextureSwapChain chain, int* out_Length); + +/// Gets the current index in an ovrTextureSwapChain. +/// +/// \param[in] session Specifies an ovrSession previously returned by ovr_Create. +/// \param[in] chain Specifies the ovrTextureSwapChain for which the index should be retrieved. +/// \param[out] out_Index Returns the current (free) index in specified chain. +/// +/// \return Returns an ovrResult for which OVR_SUCCESS(result) is false upon error. +/// +/// \see ovr_CreateTextureSwapChainDX, ovr_CreateTextureSwapChainGL +/// +OVR_PUBLIC_FUNCTION(ovrResult) ovr_GetTextureSwapChainCurrentIndex(ovrSession session, ovrTextureSwapChain chain, int* out_Index); + +/// Gets the description of the buffers in an ovrTextureSwapChain +/// +/// \param[in] session Specifies an ovrSession previously returned by ovr_Create. +/// \param[in] chain Specifies the ovrTextureSwapChain for which the description should be retrieved. +/// \param[out] out_Desc Returns the description of the specified chain. +/// +/// \return Returns an ovrResult for which OVR_SUCCESS(result) is false upon error. +/// +/// \see ovr_CreateTextureSwapChainDX, ovr_CreateTextureSwapChainGL +/// +OVR_PUBLIC_FUNCTION(ovrResult) ovr_GetTextureSwapChainDesc(ovrSession session, ovrTextureSwapChain chain, ovrTextureSwapChainDesc* out_Desc); + +/// Commits any pending changes to an ovrTextureSwapChain, and advances its current index +/// +/// \param[in] session Specifies an ovrSession previously returned by ovr_Create. +/// \param[in] chain Specifies the ovrTextureSwapChain to commit. +/// +/// \note When Commit is called, the texture at the current index is considered ready for use by the +/// runtime, and further writes to it should be avoided. The swap chain's current index is advanced, +/// providing there's room in the chain. The next time the SDK dereferences this texture swap chain, +/// it will synchronize with the app's graphics context and pick up the submitted index, opening up +/// room in the swap chain for further commits. +/// +/// \return Returns an ovrResult for which OVR_SUCCESS(result) is false upon error. +/// Failures include but aren't limited to: +/// - ovrError_TextureSwapChainFull: ovr_CommitTextureSwapChain was called too many times on a texture swapchain without calling submit to use the chain. +/// +/// \see ovr_CreateTextureSwapChainDX, ovr_CreateTextureSwapChainGL +/// +OVR_PUBLIC_FUNCTION(ovrResult) ovr_CommitTextureSwapChain(ovrSession session, ovrTextureSwapChain chain); + +/// Destroys an ovrTextureSwapChain and frees all the resources associated with it. +/// +/// \param[in] session Specifies an ovrSession previously returned by ovr_Create. +/// \param[in] chain Specifies the ovrTextureSwapChain to destroy. If it is NULL then this function has no effect. +/// +/// \see ovr_CreateTextureSwapChainDX, ovr_CreateTextureSwapChainGL +/// +OVR_PUBLIC_FUNCTION(void) ovr_DestroyTextureSwapChain(ovrSession session, ovrTextureSwapChain chain); + + +/// MirrorTexture creation is rendering API-specific. +/// ovr_CreateMirrorTextureDX and ovr_CreateMirrorTextureGL can be found in the +/// rendering API-specific headers, such as OVR_CAPI_D3D.h and OVR_CAPI_GL.h + +/// Destroys a mirror texture previously created by one of the mirror texture creation functions. +/// +/// \param[in] session Specifies an ovrSession previously returned by ovr_Create. +/// \param[in] mirrorTexture Specifies the ovrTexture to destroy. If it is NULL then this function has no effect. +/// +/// \see ovr_CreateMirrorTextureDX, ovr_CreateMirrorTextureGL +/// +OVR_PUBLIC_FUNCTION(void) ovr_DestroyMirrorTexture(ovrSession session, ovrMirrorTexture mirrorTexture); + + +/// Calculates the recommended viewport size for rendering a given eye within the HMD +/// with a given FOV cone. +/// +/// Higher FOV will generally require larger textures to maintain quality. +/// Apps packing multiple eye views together on the same texture should ensure there are +/// at least 8 pixels of padding between them to prevent texture filtering and chromatic +/// aberration causing images to leak between the two eye views. +/// +/// \param[in] session Specifies an ovrSession previously returned by ovr_Create. +/// \param[in] eye Specifies which eye (left or right) to calculate for. +/// \param[in] fov Specifies the ovrFovPort to use. +/// \param[in] pixelsPerDisplayPixel Specifies the ratio of the number of render target pixels +/// to display pixels at the center of distortion. 1.0 is the default value. Lower +/// values can improve performance, higher values give improved quality. +/// +/// Example code +/// \code{.cpp} +/// ovrHmdDesc hmdDesc = ovr_GetHmdDesc(session); +/// ovrSizei eyeSizeLeft = ovr_GetFovTextureSize(session, ovrEye_Left, hmdDesc.DefaultEyeFov[ovrEye_Left], 1.0f); +/// ovrSizei eyeSizeRight = ovr_GetFovTextureSize(session, ovrEye_Right, hmdDesc.DefaultEyeFov[ovrEye_Right], 1.0f); +/// \endcode +/// +/// \return Returns the texture width and height size. +/// +OVR_PUBLIC_FUNCTION(ovrSizei) ovr_GetFovTextureSize(ovrSession session, ovrEyeType eye, ovrFovPort fov, + float pixelsPerDisplayPixel); + +/// Computes the distortion viewport, view adjust, and other rendering parameters for +/// the specified eye. +/// +/// \param[in] session Specifies an ovrSession previously returned by ovr_Create. +/// \param[in] eyeType Specifies which eye (left or right) for which to perform calculations. +/// \param[in] fov Specifies the ovrFovPort to use. +/// +/// \return Returns the computed ovrEyeRenderDesc for the given eyeType and field of view. +/// +/// \see ovrEyeRenderDesc +/// +OVR_PUBLIC_FUNCTION(ovrEyeRenderDesc) ovr_GetRenderDesc(ovrSession session, + ovrEyeType eyeType, ovrFovPort fov); + +/// Submits layers for distortion and display. +/// +/// ovr_SubmitFrame triggers distortion and processing which might happen asynchronously. +/// The function will return when there is room in the submission queue and surfaces +/// are available. Distortion might or might not have completed. +/// +/// \param[in] session Specifies an ovrSession previously returned by ovr_Create. +/// +/// \param[in] frameIndex Specifies the targeted application frame index, or 0 to refer to one frame +/// after the last time ovr_SubmitFrame was called. +/// +/// \param[in] viewScaleDesc Provides additional information needed only if layerPtrList contains +/// an ovrLayerType_Quad. If NULL, a default version is used based on the current configuration and a 1.0 world scale. +/// +/// \param[in] layerPtrList Specifies a list of ovrLayer pointers, which can include NULL entries to +/// indicate that any previously shown layer at that index is to not be displayed. +/// Each layer header must be a part of a layer structure such as ovrLayerEyeFov or ovrLayerQuad, +/// with Header.Type identifying its type. A NULL layerPtrList entry in the array indicates the +// absence of the given layer. +/// +/// \param[in] layerCount Indicates the number of valid elements in layerPtrList. The maximum +/// supported layerCount is not currently specified, but may be specified in a future version. +/// +/// - Layers are drawn in the order they are specified in the array, regardless of the layer type. +/// +/// - Layers are not remembered between successive calls to ovr_SubmitFrame. A layer must be +/// specified in every call to ovr_SubmitFrame or it won't be displayed. +/// +/// - If a layerPtrList entry that was specified in a previous call to ovr_SubmitFrame is +/// passed as NULL or is of type ovrLayerType_Disabled, that layer is no longer displayed. +/// +/// - A layerPtrList entry can be of any layer type and multiple entries of the same layer type +/// are allowed. No layerPtrList entry may be duplicated (i.e. the same pointer as an earlier entry). +/// +/// Example code +/// \code{.cpp} +/// ovrLayerEyeFov layer0; +/// ovrLayerQuad layer1; +/// ... +/// ovrLayerHeader* layers[2] = { &layer0.Header, &layer1.Header }; +/// ovrResult result = ovr_SubmitFrame(hmd, frameIndex, nullptr, layers, 2); +/// \endcode +/// +/// \return Returns an ovrResult for which OVR_SUCCESS(result) is false upon error and true +/// upon success. Return values include but aren't limited to: +/// - ovrSuccess: rendering completed successfully. +/// - ovrSuccess_NotVisible: rendering completed successfully but was not displayed on the HMD, +/// usually because another application currently has ownership of the HMD. Applications receiving +/// this result should stop rendering new content, but continue to call ovr_SubmitFrame periodically +/// until it returns a value other than ovrSuccess_NotVisible. +/// - ovrError_DisplayLost: The session has become invalid (such as due to a device removal) +/// and the shared resources need to be released (ovr_DestroyTextureSwapChain), the session needs to +/// destroyed (ovr_Destroy) and recreated (ovr_Create), and new resources need to be created +/// (ovr_CreateTextureSwapChainXXX). The application's existing private graphics resources do not +/// need to be recreated unless the new ovr_Create call returns a different GraphicsLuid. +/// - ovrError_TextureSwapChainInvalid: The ovrTextureSwapChain is in an incomplete or inconsistent state. +/// Ensure ovr_CommitTextureSwapChain was called at least once first. +/// +/// \see ovr_GetPredictedDisplayTime, ovrViewScaleDesc, ovrLayerHeader +/// +OVR_PUBLIC_FUNCTION(ovrResult) ovr_SubmitFrame(ovrSession session, long long frameIndex, + const ovrViewScaleDesc* viewScaleDesc, + ovrLayerHeader const * const * layerPtrList, unsigned int layerCount); +///@} + + + +//------------------------------------------------------------------------------------- +/// @name Frame Timing +/// +//@{ + + +/// Gets the time of the specified frame midpoint. +/// +/// Predicts the time at which the given frame will be displayed. The predicted time +/// is the middle of the time period during which the corresponding eye images will +/// be displayed. +/// +/// The application should increment frameIndex for each successively targeted frame, +/// and pass that index to any relevent OVR functions that need to apply to the frame +/// identified by that index. +/// +/// This function is thread-safe and allows for multiple application threads to target +/// their processing to the same displayed frame. +/// +/// In the even that prediction fails due to various reasons (e.g. the display being off +/// or app has yet to present any frames), the return value will be current CPU time. +/// +/// \param[in] session Specifies an ovrSession previously returned by ovr_Create. +/// \param[in] frameIndex Identifies the frame the caller wishes to target. +/// A value of zero returns the next frame index. +/// \return Returns the absolute frame midpoint time for the given frameIndex. +/// \see ovr_GetTimeInSeconds +/// +OVR_PUBLIC_FUNCTION(double) ovr_GetPredictedDisplayTime(ovrSession session, long long frameIndex); + + +/// Returns global, absolute high-resolution time in seconds. +/// +/// The time frame of reference for this function is not specified and should not be +/// depended upon. +/// +/// \return Returns seconds as a floating point value. +/// \see ovrPoseStatef, ovrFrameTiming +/// +OVR_PUBLIC_FUNCTION(double) ovr_GetTimeInSeconds(); + + +/// Performance HUD enables the HMD user to see information critical to +/// the real-time operation of the VR application such as latency timing, +/// and CPU & GPU performance metrics +/// +/// App can toggle performance HUD modes as such: +/// \code{.cpp} +/// ovrPerfHudMode PerfHudMode = ovrPerfHud_LatencyTiming; +/// ovr_SetInt(Hmd, OVR_PERF_HUD_MODE, (int)PerfHudMode); +/// \endcode +/// +typedef enum ovrPerfHudMode_ +{ + ovrPerfHud_Off = 0, ///< Turns off the performance HUD + ovrPerfHud_PerfSummary = 1, ///< Shows performance summary and headroom + ovrPerfHud_LatencyTiming = 2, ///< Shows latency related timing info + ovrPerfHud_AppRenderTiming = 3, ///< Shows render timing info for application + ovrPerfHud_CompRenderTiming = 4, ///< Shows render timing info for OVR compositor + ovrPerfHud_VersionInfo = 5, ///< Shows SDK & HMD version Info + ovrPerfHud_Count = 6, ///< \internal Count of enumerated elements. + ovrPerfHud_EnumSize = 0x7fffffff ///< \internal Force type int32_t. +} ovrPerfHudMode; + +/// Layer HUD enables the HMD user to see information about a layer +/// +/// App can toggle layer HUD modes as such: +/// \code{.cpp} +/// ovrLayerHudMode LayerHudMode = ovrLayerHud_Info; +/// ovr_SetInt(Hmd, OVR_LAYER_HUD_MODE, (int)LayerHudMode); +/// \endcode +/// +typedef enum ovrLayerHudMode_ +{ + ovrLayerHud_Off = 0, ///< Turns off the layer HUD + ovrLayerHud_Info = 1, ///< Shows info about a specific layer + ovrLayerHud_EnumSize = 0x7fffffff +} ovrLayerHudMode; + +///@} + +/// Debug HUD is provided to help developers gauge and debug the fidelity of their app's +/// stereo rendering characteristics. Using the provided quad and crosshair guides, +/// the developer can verify various aspects such as VR tracking units (e.g. meters), +/// stereo camera-parallax properties (e.g. making sure objects at infinity are rendered +/// with the proper separation), measuring VR geometry sizes and distances and more. +/// +/// App can toggle the debug HUD modes as such: +/// \code{.cpp} +/// ovrDebugHudStereoMode DebugHudMode = ovrDebugHudStereo_QuadWithCrosshair; +/// ovr_SetInt(Hmd, OVR_DEBUG_HUD_STEREO_MODE, (int)DebugHudMode); +/// \endcode +/// +/// The app can modify the visual properties of the stereo guide (i.e. quad, crosshair) +/// using the ovr_SetFloatArray function. For a list of tweakable properties, +/// see the OVR_DEBUG_HUD_STEREO_GUIDE_* keys in the OVR_CAPI_Keys.h header file. +typedef enum ovrDebugHudStereoMode_ +{ + ovrDebugHudStereo_Off = 0, ///< Turns off the Stereo Debug HUD + ovrDebugHudStereo_Quad = 1, ///< Renders Quad in world for Stereo Debugging + ovrDebugHudStereo_QuadWithCrosshair = 2, ///< Renders Quad+crosshair in world for Stereo Debugging + ovrDebugHudStereo_CrosshairAtInfinity = 3, ///< Renders screen-space crosshair at infinity for Stereo Debugging + ovrDebugHudStereo_Count, ///< \internal Count of enumerated elements + + ovrDebugHudStereo_EnumSize = 0x7fffffff ///< \internal Force type int32_t +} ovrDebugHudStereoMode; + + + + +// ----------------------------------------------------------------------------------- +/// @name Property Access +/// +/// These functions read and write OVR properties. Supported properties +/// are defined in OVR_CAPI_Keys.h +/// +//@{ + +/// Reads a boolean property. +/// +/// \param[in] session Specifies an ovrSession previously returned by ovr_Create. +/// \param[in] propertyName The name of the property, which needs to be valid for only the call. +/// \param[in] defaultVal specifes the value to return if the property couldn't be read. +/// \return Returns the property interpreted as a boolean value. Returns defaultVal if +/// the property doesn't exist. +OVR_PUBLIC_FUNCTION(ovrBool) ovr_GetBool(ovrSession session, const char* propertyName, ovrBool defaultVal); + +/// Writes or creates a boolean property. +/// If the property wasn't previously a boolean property, it is changed to a boolean property. +/// +/// \param[in] session Specifies an ovrSession previously returned by ovr_Create. +/// \param[in] propertyName The name of the property, which needs to be valid only for the call. +/// \param[in] value The value to write. +/// \return Returns true if successful, otherwise false. A false result should only occur if the property +/// name is empty or if the property is read-only. +OVR_PUBLIC_FUNCTION(ovrBool) ovr_SetBool(ovrSession session, const char* propertyName, ovrBool value); + + +/// Reads an integer property. +/// +/// \param[in] session Specifies an ovrSession previously returned by ovr_Create. +/// \param[in] propertyName The name of the property, which needs to be valid only for the call. +/// \param[in] defaultVal Specifes the value to return if the property couldn't be read. +/// \return Returns the property interpreted as an integer value. Returns defaultVal if +/// the property doesn't exist. +OVR_PUBLIC_FUNCTION(int) ovr_GetInt(ovrSession session, const char* propertyName, int defaultVal); + +/// Writes or creates an integer property. +/// +/// If the property wasn't previously a boolean property, it is changed to an integer property. +/// +/// \param[in] session Specifies an ovrSession previously returned by ovr_Create. +/// \param[in] propertyName The name of the property, which needs to be valid only for the call. +/// \param[in] value The value to write. +/// \return Returns true if successful, otherwise false. A false result should only occur if the property +/// name is empty or if the property is read-only. +OVR_PUBLIC_FUNCTION(ovrBool) ovr_SetInt(ovrSession session, const char* propertyName, int value); + + +/// Reads a float property. +/// +/// \param[in] session Specifies an ovrSession previously returned by ovr_Create. +/// \param[in] propertyName The name of the property, which needs to be valid only for the call. +/// \param[in] defaultVal specifes the value to return if the property couldn't be read. +/// \return Returns the property interpreted as an float value. Returns defaultVal if +/// the property doesn't exist. +OVR_PUBLIC_FUNCTION(float) ovr_GetFloat(ovrSession session, const char* propertyName, float defaultVal); + +/// Writes or creates a float property. +/// If the property wasn't previously a float property, it's changed to a float property. +/// +/// \param[in] session Specifies an ovrSession previously returned by ovr_Create. +/// \param[in] propertyName The name of the property, which needs to be valid only for the call. +/// \param[in] value The value to write. +/// \return Returns true if successful, otherwise false. A false result should only occur if the property +/// name is empty or if the property is read-only. +OVR_PUBLIC_FUNCTION(ovrBool) ovr_SetFloat(ovrSession session, const char* propertyName, float value); + + +/// Reads a float array property. +/// +/// \param[in] session Specifies an ovrSession previously returned by ovr_Create. +/// \param[in] propertyName The name of the property, which needs to be valid only for the call. +/// \param[in] values An array of float to write to. +/// \param[in] valuesCapacity Specifies the maximum number of elements to write to the values array. +/// \return Returns the number of elements read, or 0 if property doesn't exist or is empty. +OVR_PUBLIC_FUNCTION(unsigned int) ovr_GetFloatArray(ovrSession session, const char* propertyName, + float values[], unsigned int valuesCapacity); + +/// Writes or creates a float array property. +/// +/// \param[in] session Specifies an ovrSession previously returned by ovr_Create. +/// \param[in] propertyName The name of the property, which needs to be valid only for the call. +/// \param[in] values An array of float to write from. +/// \param[in] valuesSize Specifies the number of elements to write. +/// \return Returns true if successful, otherwise false. A false result should only occur if the property +/// name is empty or if the property is read-only. +OVR_PUBLIC_FUNCTION(ovrBool) ovr_SetFloatArray(ovrSession session, const char* propertyName, + const float values[], unsigned int valuesSize); + + +/// Reads a string property. +/// Strings are UTF8-encoded and null-terminated. +/// +/// \param[in] session Specifies an ovrSession previously returned by ovr_Create. +/// \param[in] propertyName The name of the property, which needs to be valid only for the call. +/// \param[in] defaultVal Specifes the value to return if the property couldn't be read. +/// \return Returns the string property if it exists. Otherwise returns defaultVal, which can be specified as NULL. +/// The return memory is guaranteed to be valid until next call to ovr_GetString or +/// until the HMD is destroyed, whichever occurs first. +OVR_PUBLIC_FUNCTION(const char*) ovr_GetString(ovrSession session, const char* propertyName, + const char* defaultVal); + +/// Writes or creates a string property. +/// Strings are UTF8-encoded and null-terminated. +/// +/// \param[in] session Specifies an ovrSession previously returned by ovr_Create. +/// \param[in] propertyName The name of the property, which needs to be valid only for the call. +/// \param[in] value The string property, which only needs to be valid for the duration of the call. +/// \return Returns true if successful, otherwise false. A false result should only occur if the property +/// name is empty or if the property is read-only. +OVR_PUBLIC_FUNCTION(ovrBool) ovr_SetString(ovrSession session, const char* propertyName, + const char* value); + +///@} + + + +#ifdef __cplusplus +} // extern "C" +#endif + + +#if defined(_MSC_VER) + #pragma warning(pop) +#endif + +/// @cond DoxygenIgnore +//----------------------------------------------------------------------------- +// ***** Compiler packing validation +// +// These checks ensure that the compiler settings being used will be compatible +// with with pre-built dynamic library provided with the runtime. + +OVR_STATIC_ASSERT(sizeof(ovrBool) == 1, "ovrBool size mismatch"); +OVR_STATIC_ASSERT(sizeof(ovrVector2i) == 4 * 2, "ovrVector2i size mismatch"); +OVR_STATIC_ASSERT(sizeof(ovrSizei) == 4 * 2, "ovrSizei size mismatch"); +OVR_STATIC_ASSERT(sizeof(ovrRecti) == sizeof(ovrVector2i) + sizeof(ovrSizei), "ovrRecti size mismatch"); +OVR_STATIC_ASSERT(sizeof(ovrQuatf) == 4 * 4, "ovrQuatf size mismatch"); +OVR_STATIC_ASSERT(sizeof(ovrVector2f) == 4 * 2, "ovrVector2f size mismatch"); +OVR_STATIC_ASSERT(sizeof(ovrVector3f) == 4 * 3, "ovrVector3f size mismatch"); +OVR_STATIC_ASSERT(sizeof(ovrMatrix4f) == 4 * 16, "ovrMatrix4f size mismatch"); + +OVR_STATIC_ASSERT(sizeof(ovrPosef) == (7 * 4), "ovrPosef size mismatch"); +OVR_STATIC_ASSERT(sizeof(ovrPoseStatef) == (22 * 4), "ovrPoseStatef size mismatch"); +OVR_STATIC_ASSERT(sizeof(ovrFovPort) == (4 * 4), "ovrFovPort size mismatch"); + +OVR_STATIC_ASSERT(sizeof(ovrHmdCaps) == 4, "ovrHmdCaps size mismatch"); +OVR_STATIC_ASSERT(sizeof(ovrTrackingCaps) == 4, "ovrTrackingCaps size mismatch"); +OVR_STATIC_ASSERT(sizeof(ovrEyeType) == 4, "ovrEyeType size mismatch"); +OVR_STATIC_ASSERT(sizeof(ovrHmdType) == 4, "ovrHmdType size mismatch"); + +OVR_STATIC_ASSERT(sizeof(ovrTrackerDesc) == 4 + 4 + 4 + 4, "ovrTrackerDesc size mismatch"); +OVR_STATIC_ASSERT(sizeof(ovrTrackerPose) == 4 + 4 + sizeof(ovrPosef) + sizeof(ovrPosef), "ovrTrackerPose size mismatch"); +OVR_STATIC_ASSERT(sizeof(ovrTrackingState) == sizeof(ovrPoseStatef) + 4 + 4 + (sizeof(ovrPoseStatef) * 2) + (sizeof(unsigned int) * 2) + sizeof(ovrPosef) + 4, "ovrTrackingState size mismatch"); + + +//OVR_STATIC_ASSERT(sizeof(ovrTextureHeader) == sizeof(ovrRenderAPIType) + sizeof(ovrSizei), +// "ovrTextureHeader size mismatch"); +//OVR_STATIC_ASSERT(sizeof(ovrTexture) == sizeof(ovrTextureHeader) OVR_ON64(+4) + sizeof(uintptr_t) * 8, +// "ovrTexture size mismatch"); +// +OVR_STATIC_ASSERT(sizeof(ovrStatusBits) == 4, "ovrStatusBits size mismatch"); + +OVR_STATIC_ASSERT(sizeof(ovrSessionStatus) == 6, "ovrSessionStatus size mismatch"); + +OVR_STATIC_ASSERT(sizeof(ovrEyeRenderDesc) == sizeof(ovrEyeType) + sizeof(ovrFovPort) + sizeof(ovrRecti) + + sizeof(ovrVector2f) + sizeof(ovrVector3f), + "ovrEyeRenderDesc size mismatch"); +OVR_STATIC_ASSERT(sizeof(ovrTimewarpProjectionDesc) == 4 * 3, "ovrTimewarpProjectionDesc size mismatch"); + +OVR_STATIC_ASSERT(sizeof(ovrInitFlags) == 4, "ovrInitFlags size mismatch"); +OVR_STATIC_ASSERT(sizeof(ovrLogLevel) == 4, "ovrLogLevel size mismatch"); + +OVR_STATIC_ASSERT(sizeof(ovrInitParams) == 4 + 4 + sizeof(ovrLogCallback) + sizeof(uintptr_t) + 4 + 4, + "ovrInitParams size mismatch"); + +OVR_STATIC_ASSERT(sizeof(ovrHmdDesc) == + + sizeof(ovrHmdType) // Type + OVR_ON64(+ 4) // pad0 + + 64 // ProductName + + 64 // Manufacturer + + 2 // VendorId + + 2 // ProductId + + 24 // SerialNumber + + 2 // FirmwareMajor + + 2 // FirmwareMinor + + 4 * 4 // AvailableHmdCaps - DefaultTrackingCaps + + sizeof(ovrFovPort) * 2 // DefaultEyeFov + + sizeof(ovrFovPort) * 2 // MaxEyeFov + + sizeof(ovrSizei) // Resolution + + 4 // DisplayRefreshRate + OVR_ON64(+ 4) // pad1 + , "ovrHmdDesc size mismatch"); + + +// ----------------------------------------------------------------------------------- +// ***** Backward compatibility #includes +// +// This is at the bottom of this file because the following is dependent on the +// declarations above. + +#if !defined(OVR_CAPI_NO_UTILS) + #include "Extras/OVR_CAPI_Util.h" +#endif + +/// @endcond + +#endif // OVR_CAPI_h diff --git a/src/external/OculusSDK/LibOVR/Include/OVR_CAPI_Audio.h b/src/external/OculusSDK/LibOVR/Include/OVR_CAPI_Audio.h new file mode 100644 index 000000000..c53448133 --- /dev/null +++ b/src/external/OculusSDK/LibOVR/Include/OVR_CAPI_Audio.h @@ -0,0 +1,76 @@ +/********************************************************************************//** +\file OVR_CAPI_Audio.h +\brief CAPI audio functions. +\copyright Copyright 2015 Oculus VR, LLC. All Rights reserved. +************************************************************************************/ + + +#ifndef OVR_CAPI_Audio_h +#define OVR_CAPI_Audio_h + +#ifdef _WIN32 +#include +#include "OVR_CAPI.h" +#define OVR_AUDIO_MAX_DEVICE_STR_SIZE 128 + +/// Gets the ID of the preferred VR audio output device. +/// +/// \param[out] deviceOutId The ID of the user's preferred VR audio device to use, which will be valid upon a successful return value, else it will be WAVE_MAPPER. +/// +/// \return Returns an ovrResult indicating success or failure. In the case of failure, use +/// ovr_GetLastErrorInfo to get more information. +/// +OVR_PUBLIC_FUNCTION(ovrResult) ovr_GetAudioDeviceOutWaveId(UINT* deviceOutId); + +/// Gets the ID of the preferred VR audio input device. +/// +/// \param[out] deviceInId The ID of the user's preferred VR audio device to use, which will be valid upon a successful return value, else it will be WAVE_MAPPER. +/// +/// \return Returns an ovrResult indicating success or failure. In the case of failure, use +/// ovr_GetLastErrorInfo to get more information. +/// +OVR_PUBLIC_FUNCTION(ovrResult) ovr_GetAudioDeviceInWaveId(UINT* deviceInId); + + +/// Gets the GUID of the preferred VR audio device as a string. +/// +/// \param[out] deviceOutStrBuffer A buffer where the GUID string for the device will copied to. +/// +/// \return Returns an ovrResult indicating success or failure. In the case of failure, use +/// ovr_GetLastErrorInfo to get more information. +/// +OVR_PUBLIC_FUNCTION(ovrResult) ovr_GetAudioDeviceOutGuidStr(WCHAR deviceOutStrBuffer[OVR_AUDIO_MAX_DEVICE_STR_SIZE]); + + +/// Gets the GUID of the preferred VR audio device. +/// +/// \param[out] deviceOutGuid The GUID of the user's preferred VR audio device to use, which will be valid upon a successful return value, else it will be NULL. +/// +/// \return Returns an ovrResult indicating success or failure. In the case of failure, use +/// ovr_GetLastErrorInfo to get more information. +/// +OVR_PUBLIC_FUNCTION(ovrResult) ovr_GetAudioDeviceOutGuid(GUID* deviceOutGuid); + + +/// Gets the GUID of the preferred VR microphone device as a string. +/// +/// \param[out] deviceInStrBuffer A buffer where the GUID string for the device will copied to. +/// +/// \return Returns an ovrResult indicating success or failure. In the case of failure, use +/// ovr_GetLastErrorInfo to get more information. +/// +OVR_PUBLIC_FUNCTION(ovrResult) ovr_GetAudioDeviceInGuidStr(WCHAR deviceInStrBuffer[OVR_AUDIO_MAX_DEVICE_STR_SIZE]); + + +/// Gets the GUID of the preferred VR microphone device. +/// +/// \param[out] deviceInGuid The GUID of the user's preferred VR audio device to use, which will be valid upon a successful return value, else it will be NULL. +/// +/// \return Returns an ovrResult indicating success or failure. In the case of failure, use +/// ovr_GetLastErrorInfo to get more information. +/// +OVR_PUBLIC_FUNCTION(ovrResult) ovr_GetAudioDeviceInGuid(GUID* deviceInGuid); + +#endif //OVR_OS_MS + +#endif // OVR_CAPI_Audio_h diff --git a/src/external/OculusSDK/LibOVR/Include/OVR_CAPI_D3D.h b/src/external/OculusSDK/LibOVR/Include/OVR_CAPI_D3D.h new file mode 100644 index 000000000..50806bca1 --- /dev/null +++ b/src/external/OculusSDK/LibOVR/Include/OVR_CAPI_D3D.h @@ -0,0 +1,155 @@ +/********************************************************************************//** +\file OVR_CAPI_D3D.h +\brief D3D specific structures used by the CAPI interface. +\copyright Copyright 2014-2016 Oculus VR, LLC All Rights reserved. +************************************************************************************/ + +#ifndef OVR_CAPI_D3D_h +#define OVR_CAPI_D3D_h + +#include "OVR_CAPI.h" +#include "OVR_Version.h" + + +#if defined (_WIN32) +#include + +//----------------------------------------------------------------------------------- +// ***** Direct3D Specific + +/// Create Texture Swap Chain suitable for use with Direct3D 11 and 12. +/// +/// \param[in] session Specifies an ovrSession previously returned by ovr_Create. +/// \param[in] d3dPtr Specifies the application's D3D11Device to create resources with or the D3D12CommandQueue +/// which must be the same one the application renders to the eye textures with. +/// \param[in] desc Specifies requested texture properties. See notes for more info about texture format. +/// \param[in] bindFlags Specifies what ovrTextureBindFlags the application requires for this texture chain. +/// \param[out] out_TextureSwapChain Returns the created ovrTextureSwapChain, which will be valid upon a successful return value, else it will be NULL. +/// This texture chain must be eventually destroyed via ovr_DestroyTextureSwapChain before destroying the HMD with ovr_Destroy. +/// +/// \return Returns an ovrResult indicating success or failure. In the case of failure, use +/// ovr_GetLastErrorInfo to get more information. +/// +/// \note The texture format provided in \a desc should be thought of as the format the distortion-compositor will use for the +/// ShaderResourceView when reading the contents of the texture. To that end, it is highly recommended that the application +/// requests texture swapchain formats that are in sRGB-space (e.g. OVR_FORMAT_R8G8B8A8_UNORM_SRGB) as the compositor +/// does sRGB-correct rendering. As such, the compositor relies on the GPU's hardware sampler to do the sRGB-to-linear +/// conversion. If the application still prefers to render to a linear format (e.g. OVR_FORMAT_R8G8B8A8_UNORM) while handling the +/// linear-to-gamma conversion via HLSL code, then the application must still request the corresponding sRGB format and also use +/// the \a ovrTextureMisc_DX_Typeless flag in the ovrTextureSwapChainDesc's Flag field. This will allow the application to create +/// a RenderTargetView that is the desired linear format while the compositor continues to treat it as sRGB. Failure to do so +/// will cause the compositor to apply unexpected gamma conversions leading to gamma-curve artifacts. The \a ovrTextureMisc_DX_Typeless +/// flag for depth buffer formats (e.g. OVR_FORMAT_D32_FLOAT) is ignored as they are always converted to be typeless. +/// +/// \see ovr_GetTextureSwapChainLength +/// \see ovr_GetTextureSwapChainCurrentIndex +/// \see ovr_GetTextureSwapChainDesc +/// \see ovr_GetTextureSwapChainBufferDX +/// \see ovr_DestroyTextureSwapChain +/// +OVR_PUBLIC_FUNCTION(ovrResult) ovr_CreateTextureSwapChainDX(ovrSession session, + IUnknown* d3dPtr, + const ovrTextureSwapChainDesc* desc, + ovrTextureSwapChain* out_TextureSwapChain); + + +/// Get a specific buffer within the chain as any compatible COM interface (similar to QueryInterface) +/// +/// \param[in] session Specifies an ovrSession previously returned by ovr_Create. +/// \param[in] chain Specifies an ovrTextureSwapChain previously returned by ovr_CreateTextureSwapChainDX +/// \param[in] index Specifies the index within the chain to retrieve. Must be between 0 and length (see ovr_GetTextureSwapChainLength), +/// or may pass -1 to get the buffer at the CurrentIndex location. (Saving a call to GetTextureSwapChainCurrentIndex) +/// \param[in] iid Specifies the interface ID of the interface pointer to query the buffer for. +/// \param[out] out_Buffer Returns the COM interface pointer retrieved. +/// +/// \return Returns an ovrResult indicating success or failure. In the case of failure, use +/// ovr_GetLastErrorInfo to get more information. +/// +/// Example code +/// \code{.cpp} +/// ovr_GetTextureSwapChainBufferDX(session, chain, 0, IID_ID3D11Texture2D, &d3d11Texture); +/// ovr_GetTextureSwapChainBufferDX(session, chain, 1, IID_PPV_ARGS(&dxgiResource)); +/// \endcode +/// +OVR_PUBLIC_FUNCTION(ovrResult) ovr_GetTextureSwapChainBufferDX(ovrSession session, + ovrTextureSwapChain chain, + int index, + IID iid, + void** out_Buffer); + + +/// Create Mirror Texture which is auto-refreshed to mirror Rift contents produced by this application. +/// +/// A second call to ovr_CreateMirrorTextureDX for a given ovrSession before destroying the first one +/// is not supported and will result in an error return. +/// +/// \param[in] session Specifies an ovrSession previously returned by ovr_Create. +/// \param[in] d3dPtr Specifies the application's D3D11Device to create resources with or the D3D12CommandQueue +/// which must be the same one the application renders to the textures with. +/// \param[in] desc Specifies requested texture properties. See notes for more info about texture format. +/// \param[out] out_MirrorTexture Returns the created ovrMirrorTexture, which will be valid upon a successful return value, else it will be NULL. +/// This texture must be eventually destroyed via ovr_DestroyMirrorTexture before destroying the HMD with ovr_Destroy. +/// +/// \return Returns an ovrResult indicating success or failure. In the case of failure, use +/// ovr_GetLastErrorInfo to get more information. +/// +/// \note The texture format provided in \a desc should be thought of as the format the compositor will use for the RenderTargetView when +/// writing into mirror texture. To that end, it is highly recommended that the application requests a mirror texture format that is +/// in sRGB-space (e.g. OVR_FORMAT_R8G8B8A8_UNORM_SRGB) as the compositor does sRGB-correct rendering. If however the application wants +/// to still read the mirror texture as a linear format (e.g. OVR_FORMAT_R8G8B8A8_UNORM) and handle the sRGB-to-linear conversion in +/// HLSL code, then it is recommended the application still requests an sRGB format and also use the \a ovrTextureMisc_DX_Typeless flag in the +/// ovrMirrorTextureDesc's Flags field. This will allow the application to bind a ShaderResourceView that is a linear format while the +/// compositor continues to treat is as sRGB. Failure to do so will cause the compositor to apply unexpected gamma conversions leading to +/// gamma-curve artifacts. +/// +/// +/// Example code +/// \code{.cpp} +/// ovrMirrorTexture mirrorTexture = nullptr; +/// ovrMirrorTextureDesc mirrorDesc = {}; +/// mirrorDesc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB; +/// mirrorDesc.Width = mirrorWindowWidth; +/// mirrorDesc.Height = mirrorWindowHeight; +/// ovrResult result = ovr_CreateMirrorTextureDX(session, d3d11Device, &mirrorDesc, &mirrorTexture); +/// [...] +/// // Destroy the texture when done with it. +/// ovr_DestroyMirrorTexture(session, mirrorTexture); +/// mirrorTexture = nullptr; +/// \endcode +/// +/// \see ovr_GetMirrorTextureBufferDX +/// \see ovr_DestroyMirrorTexture +/// +OVR_PUBLIC_FUNCTION(ovrResult) ovr_CreateMirrorTextureDX(ovrSession session, + IUnknown* d3dPtr, + const ovrMirrorTextureDesc* desc, + ovrMirrorTexture* out_MirrorTexture); + +/// Get a the underlying buffer as any compatible COM interface (similar to QueryInterface) +/// +/// \param[in] session Specifies an ovrSession previously returned by ovr_Create. +/// \param[in] mirrorTexture Specifies an ovrMirrorTexture previously returned by ovr_CreateMirrorTextureDX +/// \param[in] iid Specifies the interface ID of the interface pointer to query the buffer for. +/// \param[out] out_Buffer Returns the COM interface pointer retrieved. +/// +/// \return Returns an ovrResult indicating success or failure. In the case of failure, use +/// ovr_GetLastErrorInfo to get more information. +/// +/// Example code +/// \code{.cpp} +/// ID3D11Texture2D* d3d11Texture = nullptr; +/// ovr_GetMirrorTextureBufferDX(session, mirrorTexture, IID_PPV_ARGS(&d3d11Texture)); +/// d3d11DeviceContext->CopyResource(d3d11TextureBackBuffer, d3d11Texture); +/// d3d11Texture->Release(); +/// dxgiSwapChain->Present(0, 0); +/// \endcode +/// +OVR_PUBLIC_FUNCTION(ovrResult) ovr_GetMirrorTextureBufferDX(ovrSession session, + ovrMirrorTexture mirrorTexture, + IID iid, + void** out_Buffer); + + +#endif // _WIN32 + +#endif // OVR_CAPI_D3D_h diff --git a/src/external/OculusSDK/LibOVR/Include/OVR_CAPI_GL.h b/src/external/OculusSDK/LibOVR/Include/OVR_CAPI_GL.h new file mode 100644 index 000000000..1658ca578 --- /dev/null +++ b/src/external/OculusSDK/LibOVR/Include/OVR_CAPI_GL.h @@ -0,0 +1,99 @@ +/********************************************************************************//** +\file OVR_CAPI_GL.h +\brief OpenGL-specific structures used by the CAPI interface. +\copyright Copyright 2015 Oculus VR, LLC. All Rights reserved. +************************************************************************************/ + +#ifndef OVR_CAPI_GL_h +#define OVR_CAPI_GL_h + +#include "OVR_CAPI.h" + +/// Creates a TextureSwapChain suitable for use with OpenGL. +/// +/// \param[in] session Specifies an ovrSession previously returned by ovr_Create. +/// \param[in] desc Specifies the requested texture properties. See notes for more info about texture format. +/// \param[out] out_TextureSwapChain Returns the created ovrTextureSwapChain, which will be valid upon +/// a successful return value, else it will be NULL. This texture swap chain must be eventually +/// destroyed via ovr_DestroyTextureSwapChain before destroying the HMD with ovr_Destroy. +/// +/// \return Returns an ovrResult indicating success or failure. In the case of failure, use +/// ovr_GetLastErrorInfo to get more information. +/// +/// \note The \a format provided should be thought of as the format the distortion compositor will use when reading +/// the contents of the texture. To that end, it is highly recommended that the application requests texture swap chain +/// formats that are in sRGB-space (e.g. OVR_FORMAT_R8G8B8A8_UNORM_SRGB) as the distortion compositor does sRGB-correct +/// rendering. Furthermore, the app should then make sure "glEnable(GL_FRAMEBUFFER_SRGB);" is called before rendering +/// into these textures. Even though it is not recommended, if the application would like to treat the texture as a linear +/// format and do linear-to-gamma conversion in GLSL, then the application can avoid calling "glEnable(GL_FRAMEBUFFER_SRGB);", +/// but should still pass in an sRGB variant for the \a format. Failure to do so will cause the distortion compositor +/// to apply incorrect gamma conversions leading to gamma-curve artifacts. +/// +/// \see ovr_GetTextureSwapChainLength +/// \see ovr_GetTextureSwapChainCurrentIndex +/// \see ovr_GetTextureSwapChainDesc +/// \see ovr_GetTextureSwapChainBufferGL +/// \see ovr_DestroyTextureSwapChain +/// +OVR_PUBLIC_FUNCTION(ovrResult) ovr_CreateTextureSwapChainGL(ovrSession session, + const ovrTextureSwapChainDesc* desc, + ovrTextureSwapChain* out_TextureSwapChain); + +/// Get a specific buffer within the chain as a GL texture name +/// +/// \param[in] session Specifies an ovrSession previously returned by ovr_Create. +/// \param[in] chain Specifies an ovrTextureSwapChain previously returned by ovr_CreateTextureSwapChainGL +/// \param[in] index Specifies the index within the chain to retrieve. Must be between 0 and length (see ovr_GetTextureSwapChainLength) +/// or may pass -1 to get the buffer at the CurrentIndex location. (Saving a call to GetTextureSwapChainCurrentIndex) +/// \param[out] out_TexId Returns the GL texture object name associated with the specific index requested +/// +/// \return Returns an ovrResult indicating success or failure. In the case of failure, use +/// ovr_GetLastErrorInfo to get more information. +/// +OVR_PUBLIC_FUNCTION(ovrResult) ovr_GetTextureSwapChainBufferGL(ovrSession session, + ovrTextureSwapChain chain, + int index, + unsigned int* out_TexId); + + +/// Creates a Mirror Texture which is auto-refreshed to mirror Rift contents produced by this application. +/// +/// A second call to ovr_CreateMirrorTextureGL for a given ovrSession before destroying the first one +/// is not supported and will result in an error return. +/// +/// \param[in] session Specifies an ovrSession previously returned by ovr_Create. +/// \param[in] desc Specifies the requested mirror texture description. +/// \param[out] out_MirrorTexture Specifies the created ovrMirrorTexture, which will be valid upon a successful return value, else it will be NULL. +/// This texture must be eventually destroyed via ovr_DestroyMirrorTexture before destroying the HMD with ovr_Destroy. +/// +/// \return Returns an ovrResult indicating success or failure. In the case of failure, use +/// ovr_GetLastErrorInfo to get more information. +/// +/// \note The \a format provided should be thought of as the format the distortion compositor will use when writing into the mirror +/// texture. It is highly recommended that mirror textures are requested as sRGB formats because the distortion compositor +/// does sRGB-correct rendering. If the application requests a non-sRGB format (e.g. R8G8B8A8_UNORM) as the mirror texture, +/// then the application might have to apply a manual linear-to-gamma conversion when reading from the mirror texture. +/// Failure to do so can result in incorrect gamma conversions leading to gamma-curve artifacts and color banding. +/// +/// \see ovr_GetMirrorTextureBufferGL +/// \see ovr_DestroyMirrorTexture +/// +OVR_PUBLIC_FUNCTION(ovrResult) ovr_CreateMirrorTextureGL(ovrSession session, + const ovrMirrorTextureDesc* desc, + ovrMirrorTexture* out_MirrorTexture); + +/// Get a the underlying buffer as a GL texture name +/// +/// \param[in] session Specifies an ovrSession previously returned by ovr_Create. +/// \param[in] mirrorTexture Specifies an ovrMirrorTexture previously returned by ovr_CreateMirrorTextureGL +/// \param[out] out_TexId Specifies the GL texture object name associated with the mirror texture +/// +/// \return Returns an ovrResult indicating success or failure. In the case of failure, use +/// ovr_GetLastErrorInfo to get more information. +/// +OVR_PUBLIC_FUNCTION(ovrResult) ovr_GetMirrorTextureBufferGL(ovrSession session, + ovrMirrorTexture mirrorTexture, + unsigned int* out_TexId); + + +#endif // OVR_CAPI_GL_h diff --git a/src/external/OculusSDK/LibOVR/Include/OVR_CAPI_Keys.h b/src/external/OculusSDK/LibOVR/Include/OVR_CAPI_Keys.h new file mode 100644 index 000000000..e3e9d689c --- /dev/null +++ b/src/external/OculusSDK/LibOVR/Include/OVR_CAPI_Keys.h @@ -0,0 +1,53 @@ +/********************************************************************************//** +\file OVR_CAPI.h +\brief Keys for CAPI proprty function calls +\copyright Copyright 2015 Oculus VR, LLC All Rights reserved. +************************************************************************************/ + +#ifndef OVR_CAPI_Keys_h +#define OVR_CAPI_Keys_h + +#include "OVR_Version.h" + + + +#define OVR_KEY_USER "User" // string + +#define OVR_KEY_NAME "Name" // string + +#define OVR_KEY_GENDER "Gender" // string "Male", "Female", or "Unknown" +#define OVR_DEFAULT_GENDER "Unknown" + +#define OVR_KEY_PLAYER_HEIGHT "PlayerHeight" // float meters +#define OVR_DEFAULT_PLAYER_HEIGHT 1.778f + +#define OVR_KEY_EYE_HEIGHT "EyeHeight" // float meters +#define OVR_DEFAULT_EYE_HEIGHT 1.675f + +#define OVR_KEY_NECK_TO_EYE_DISTANCE "NeckEyeDistance" // float[2] meters +#define OVR_DEFAULT_NECK_TO_EYE_HORIZONTAL 0.0805f +#define OVR_DEFAULT_NECK_TO_EYE_VERTICAL 0.075f + + +#define OVR_KEY_EYE_TO_NOSE_DISTANCE "EyeToNoseDist" // float[2] meters + + + + + +#define OVR_PERF_HUD_MODE "PerfHudMode" // int, allowed values are defined in enum ovrPerfHudMode + +#define OVR_LAYER_HUD_MODE "LayerHudMode" // int, allowed values are defined in enum ovrLayerHudMode +#define OVR_LAYER_HUD_CURRENT_LAYER "LayerHudCurrentLayer" // int, The layer to show +#define OVR_LAYER_HUD_SHOW_ALL_LAYERS "LayerHudShowAll" // bool, Hide other layers when the hud is enabled + +#define OVR_DEBUG_HUD_STEREO_MODE "DebugHudStereoMode" // int, allowed values are defined in enum ovrDebugHudStereoMode +#define OVR_DEBUG_HUD_STEREO_GUIDE_INFO_ENABLE "DebugHudStereoGuideInfoEnable" // bool +#define OVR_DEBUG_HUD_STEREO_GUIDE_SIZE "DebugHudStereoGuideSize2f" // float[2] +#define OVR_DEBUG_HUD_STEREO_GUIDE_POSITION "DebugHudStereoGuidePosition3f" // float[3] +#define OVR_DEBUG_HUD_STEREO_GUIDE_YAWPITCHROLL "DebugHudStereoGuideYawPitchRoll3f" // float[3] +#define OVR_DEBUG_HUD_STEREO_GUIDE_COLOR "DebugHudStereoGuideColor4f" // float[4] + + + +#endif // OVR_CAPI_Keys_h diff --git a/src/external/OculusSDK/LibOVR/Include/OVR_ErrorCode.h b/src/external/OculusSDK/LibOVR/Include/OVR_ErrorCode.h new file mode 100644 index 000000000..ed0be0e70 --- /dev/null +++ b/src/external/OculusSDK/LibOVR/Include/OVR_ErrorCode.h @@ -0,0 +1,209 @@ +/********************************************************************************//** +\file OVR_ErrorCode.h +\brief This header provides LibOVR error code declarations. +\copyright Copyright 2015-2016 Oculus VR, LLC All Rights reserved. +*************************************************************************************/ + +#ifndef OVR_ErrorCode_h +#define OVR_ErrorCode_h + + +#include "OVR_Version.h" +#include + + + + + + + +#ifndef OVR_RESULT_DEFINED +#define OVR_RESULT_DEFINED ///< Allows ovrResult to be independently defined. +/// API call results are represented at the highest level by a single ovrResult. +typedef int32_t ovrResult; +#endif + + +/// \brief Indicates if an ovrResult indicates success. +/// +/// Some functions return additional successful values other than ovrSucces and +/// require usage of this macro to indicate successs. +/// +#if !defined(OVR_SUCCESS) + #define OVR_SUCCESS(result) (result >= 0) +#endif + + +/// \brief Indicates if an ovrResult indicates an unqualified success. +/// +/// This is useful for indicating that the code intentionally wants to +/// check for result == ovrSuccess as opposed to OVR_SUCCESS(), which +/// checks for result >= ovrSuccess. +/// +#if !defined(OVR_UNQUALIFIED_SUCCESS) + #define OVR_UNQUALIFIED_SUCCESS(result) (result == ovrSuccess) +#endif + + +/// \brief Indicates if an ovrResult indicates failure. +/// +#if !defined(OVR_FAILURE) + #define OVR_FAILURE(result) (!OVR_SUCCESS(result)) +#endif + + +// Success is a value greater or equal to 0, while all error types are negative values. +#ifndef OVR_SUCCESS_DEFINED +#define OVR_SUCCESS_DEFINED ///< Allows ovrResult to be independently defined. +typedef enum ovrSuccessType_ +{ + /// This is a general success result. Use OVR_SUCCESS to test for success. + ovrSuccess = 0, + + /// Returned from a call to SubmitFrame. The call succeeded, but what the app + /// rendered will not be visible on the HMD. Ideally the app should continue + /// calling SubmitFrame, but not do any rendering. When the result becomes + /// ovrSuccess, rendering should continue as usual. + ovrSuccess_NotVisible = 1000, + + ovrSuccess_HMDFirmwareMismatch = 4100, ///< The HMD Firmware is out of date but is acceptable. + ovrSuccess_TrackerFirmwareMismatch = 4101, ///< The Tracker Firmware is out of date but is acceptable. + ovrSuccess_ControllerFirmwareMismatch = 4104, ///< The controller firmware is out of date but is acceptable. + ovrSuccess_TrackerDriverNotFound = 4105, ///< The tracker driver interface was not found. Can be a temporary error + +} ovrSuccessType; +#endif + + +typedef enum ovrErrorType_ +{ + /* General errors */ + ovrError_MemoryAllocationFailure = -1000, ///< Failure to allocate memory. + ovrError_SocketCreationFailure = -1001, ///< Failure to create a socket. + ovrError_InvalidSession = -1002, ///< Invalid ovrSession parameter provided. + ovrError_Timeout = -1003, ///< The operation timed out. + ovrError_NotInitialized = -1004, ///< The system or component has not been initialized. + ovrError_InvalidParameter = -1005, ///< Invalid parameter provided. See error info or log for details. + ovrError_ServiceError = -1006, ///< Generic service error. See error info or log for details. + ovrError_NoHmd = -1007, ///< The given HMD doesn't exist. + ovrError_Unsupported = -1009, ///< Function call is not supported on this hardware/software + ovrError_DeviceUnavailable = -1010, ///< Specified device type isn't available. + ovrError_InvalidHeadsetOrientation = -1011, ///< The headset was in an invalid orientation for the requested operation (e.g. vertically oriented during ovr_RecenterPose). + ovrError_ClientSkippedDestroy = -1012, ///< The client failed to call ovr_Destroy on an active session before calling ovr_Shutdown. Or the client crashed. + ovrError_ClientSkippedShutdown = -1013, ///< The client failed to call ovr_Shutdown or the client crashed. + ovrError_ServiceDeadlockDetected = -1014, ///< The service watchdog discovered a deadlock. + + /* Audio error range, reserved for Audio errors. */ + ovrError_AudioReservedBegin = -2000, ///< First Audio error. + ovrError_AudioDeviceNotFound = -2001, ///< Failure to find the specified audio device. + ovrError_AudioComError = -2002, ///< Generic COM error. + ovrError_AudioReservedEnd = -2999, ///< Last Audio error. + + /* Initialization errors. */ + ovrError_Initialize = -3000, ///< Generic initialization error. + ovrError_LibLoad = -3001, ///< Couldn't load LibOVRRT. + ovrError_LibVersion = -3002, ///< LibOVRRT version incompatibility. + ovrError_ServiceConnection = -3003, ///< Couldn't connect to the OVR Service. + ovrError_ServiceVersion = -3004, ///< OVR Service version incompatibility. + ovrError_IncompatibleOS = -3005, ///< The operating system version is incompatible. + ovrError_DisplayInit = -3006, ///< Unable to initialize the HMD display. + ovrError_ServerStart = -3007, ///< Unable to start the server. Is it already running? + ovrError_Reinitialization = -3008, ///< Attempting to re-initialize with a different version. + ovrError_MismatchedAdapters = -3009, ///< Chosen rendering adapters between client and service do not match + ovrError_LeakingResources = -3010, ///< Calling application has leaked resources + ovrError_ClientVersion = -3011, ///< Client version too old to connect to service + ovrError_OutOfDateOS = -3012, ///< The operating system is out of date. + ovrError_OutOfDateGfxDriver = -3013, ///< The graphics driver is out of date. + ovrError_IncompatibleGPU = -3014, ///< The graphics hardware is not supported + ovrError_NoValidVRDisplaySystem = -3015, ///< No valid VR display system found. + ovrError_Obsolete = -3016, ///< Feature or API is obsolete and no longer supported. + ovrError_DisabledOrDefaultAdapter = -3017, ///< No supported VR display system found, but disabled or driverless adapter found. + ovrError_HybridGraphicsNotSupported = -3018, ///< The system is using hybrid graphics (Optimus, etc...), which is not support. + ovrError_DisplayManagerInit = -3019, ///< Initialization of the DisplayManager failed. + ovrError_TrackerDriverInit = -3020, ///< Failed to get the interface for an attached tracker + + /* Hardware errors */ + ovrError_InvalidBundleAdjustment = -4000, ///< Headset has no bundle adjustment data. + ovrError_USBBandwidth = -4001, ///< The USB hub cannot handle the camera frame bandwidth. + ovrError_USBEnumeratedSpeed = -4002, ///< The USB camera is not enumerating at the correct device speed. + ovrError_ImageSensorCommError = -4003, ///< Unable to communicate with the image sensor. + ovrError_GeneralTrackerFailure = -4004, ///< We use this to report various sensor issues that don't fit in an easily classifiable bucket. + ovrError_ExcessiveFrameTruncation = -4005, ///< A more than acceptable number of frames are coming back truncated. + ovrError_ExcessiveFrameSkipping = -4006, ///< A more than acceptable number of frames have been skipped. + ovrError_SyncDisconnected = -4007, ///< The sensor is not receiving the sync signal (cable disconnected?). + ovrError_TrackerMemoryReadFailure = -4008, ///< Failed to read memory from the sensor. + ovrError_TrackerMemoryWriteFailure = -4009, ///< Failed to write memory from the sensor. + ovrError_TrackerFrameTimeout = -4010, ///< Timed out waiting for a camera frame. + ovrError_TrackerTruncatedFrame = -4011, ///< Truncated frame returned from sensor. + ovrError_TrackerDriverFailure = -4012, ///< The sensor driver has encountered a problem. + ovrError_TrackerNRFFailure = -4013, ///< The sensor wireless subsystem has encountered a problem. + ovrError_HardwareGone = -4014, ///< The hardware has been unplugged + ovrError_NordicEnabledNoSync = -4015, ///< The nordic indicates that sync is enabled but it is not sending sync pulses + ovrError_NordicSyncNoFrames = -4016, ///< It looks like we're getting a sync signal, but no camera frames have been received + ovrError_CatastrophicFailure = -4017, ///< A catastrophic failure has occurred. We will attempt to recover by resetting the device + ovrError_CatastrophicTimeout = -4018, ///< The catastrophic recovery has timed out. + ovrError_RepeatCatastrophicFail = -4019, ///< Catastrophic failure has repeated too many times. + ovrError_USBOpenDeviceFailure = -4020, ///< Could not open handle for Rift device (likely already in use by another process). + ovrError_HMDGeneralFailure = -4021, ///< Unexpected HMD issues that don't fit a specific bucket. + + ovrError_HMDFirmwareMismatch = -4100, ///< The HMD Firmware is out of date and is unacceptable. + ovrError_TrackerFirmwareMismatch = -4101, ///< The sensor Firmware is out of date and is unacceptable. + ovrError_BootloaderDeviceDetected = -4102, ///< A bootloader HMD is detected by the service. + ovrError_TrackerCalibrationError = -4103, ///< The sensor calibration is missing or incorrect. + ovrError_ControllerFirmwareMismatch = -4104, ///< The controller firmware is out of date and is unacceptable. + ovrError_DevManDeviceDetected = -4105, ///< A DeviceManagement mode HMD is detected by the service. + ovrError_RebootedBootloaderDevice = -4106, ///< Had to reboot bootloader device, which succeeded. + ovrError_FailedRebootBootloaderDev = -4107, ///< Had to reboot bootloader device, which failed. Device is stuck in bootloader mode. + + ovrError_IMUTooManyLostSamples = -4200, ///< Too many lost IMU samples. + ovrError_IMURateError = -4201, ///< IMU rate is outside of the expected range. + ovrError_FeatureReportFailure = -4202, ///< A feature report has failed. + ovrError_HMDWirelessTimeout = -4203, ///< HMD wireless interface never returned from busy state. + + ovrError_BootloaderAssertLog = -4300, ///< HMD Bootloader Assert Log was not empty. + ovrError_AppAssertLog = -4301, ///< HMD App Assert Log was not empty. + + /* Synchronization errors */ + ovrError_Incomplete = -5000, ///< Requested async work not yet complete. + ovrError_Abandoned = -5001, ///< Requested async work was abandoned and result is incomplete. + + /* Rendering errors */ + ovrError_DisplayLost = -6000, ///< In the event of a system-wide graphics reset or cable unplug this is returned to the app. + ovrError_TextureSwapChainFull = -6001, ///< ovr_CommitTextureSwapChain was called too many times on a texture swapchain without calling submit to use the chain. + ovrError_TextureSwapChainInvalid = -6002, ///< The ovrTextureSwapChain is in an incomplete or inconsistent state. Ensure ovr_CommitTextureSwapChain was called at least once first. + ovrError_GraphicsDeviceReset = -6003, ///< Graphics device has been reset (TDR, etc...) + ovrError_DisplayRemoved = -6004, ///< HMD removed from the display adapter + ovrError_ContentProtectionNotAvailable = -6005,/// Date: Tue, 14 Jun 2016 17:16:20 +0200 Subject: [PATCH 06/11] 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(-) diff --git a/src/core.c b/src/core.c index bd49b5494..fb71af211 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 9120ddc4b..0c9f0280f 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 26961ca9e..1e3928895 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 28c50b8f2..1e77b771e 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 From 97fc266ad461db9da51877341f6097660cbf305a Mon Sep 17 00:00:00 2001 From: raysan5 Date: Tue, 14 Jun 2016 17:20:00 +0200 Subject: [PATCH 07/11] Updated raylib Oculus example --- examples/core_oculus_rift.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/examples/core_oculus_rift.c b/examples/core_oculus_rift.c index faf15d7f7..2871407b0 100644 --- a/examples/core_oculus_rift.c +++ b/examples/core_oculus_rift.c @@ -47,15 +47,24 @@ int main() BeginDrawing(); ClearBackground(RAYWHITE); + + BeginOculusDrawing(); + + for (int eye = 0; eye < 2; eye++) + { + Begin3dMode(camera); + + SetOculusMatrix(eye); + + DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED); + DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, MAROON); - 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(); + DrawGrid(10, 1.0f); + + End3dMode(); + } + + EndOculusDrawing() EndDrawing(); //---------------------------------------------------------------------------------- From d60dc7c2ebf151481e1148a9a6361b9687c48418 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Tue, 14 Jun 2016 17:34:51 +0200 Subject: [PATCH 08/11] Added Oculus Rift library dll --- .gitignore | 4 +++- src/external/OculusSDK/LibOVR/LibOVRRT32_1.dll | Bin 0 -> 964048 bytes 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 src/external/OculusSDK/LibOVR/LibOVRRT32_1.dll diff --git a/.gitignore b/.gitignore index 3a9084548..b221a37b9 100644 --- a/.gitignore +++ b/.gitignore @@ -66,8 +66,10 @@ src/libraylib.a src/libraylib.bc # oculus example -!examples/oculus_glfw_sample/LibOVRRT32_1.dll +!examples/oculus_glfw_sample/ + # external libraries DLLs !src/external/glfw3/lib/win32/glfw3.dll !src/external/openal_soft/lib/win32/OpenAL32.dll +!src/external/OculusSDK/LibOVR/LibOVRRT32_1.dll \ No newline at end of file diff --git a/src/external/OculusSDK/LibOVR/LibOVRRT32_1.dll b/src/external/OculusSDK/LibOVR/LibOVRRT32_1.dll new file mode 100644 index 0000000000000000000000000000000000000000..70f63f7019536c1a296ddf354cf411c63819f275 GIT binary patch literal 964048 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 z zdTk`Ee;^X9I5ffX!xC)wxfh_d?wN-{DYCPUB_PxF1Bm&*l!KWq;DrKsPK^g;P7UgI zc#?&rS5OH9$_k0C|4Y@n?OOkr2*21g714EsI6NNeWN?`t+%4C9oVoe=pBJ4|Sr~eG z{({mmP6KGfcB4scmHhtRub9m z&Jx_|%F`=jV11*Qr`sKrQEwEB2EXRDj^`-i?LG`zYI!)|g&SxO412dPPj@IsXFN-E zFUyJ6ZzWQ_o(!!AO1QeYIyt(%SUNpenh$X_AK>sSeF?G_T#TUlHv!4Nho%te-a`?D^o1ovhz%^n*6sSE)14)}``n9#x-1M}kMY1P2JIk= z-@q6LqQRv%*uHL8kbRwOtp`fj1E34mAZsPgoH-NL{Sh?34whNc$RPkpd59Glko+cr zI8QMU+vqB2w*ur8&Tc;r&X?lHS9}uK!T+l83CxvoIJjO=BuwNz?V6J_vUrGakL&NVeWR|>GlORhF`Rt z0@s#c4}vouBL17-6o9K^KOWHHiRGYvw(E|77mq;mg>|6ybPS*Q>pVbf>Rcy$=FfK! z=yv7McGLL8FX;Orjb9YB+0^wx8h_r2&-~9$e&UZj0h0OA`oDxH9Fm$o@eBC===SCL z#4q4x(Cy0ci9g~Xs0Hq((dh_UOvnh5umFjE;umxTNxOaku|RgaJ^-;KTK|`@heLYO z8yI2B#o~<)VDk@Xtq#)K%TSK)L(LD^5z8(QX}g@0s4(bu<>?GLC-Ip-pW!oqJ$Th* zz5{3tq02dg&-`@`pe3I!=N$OM4}9VmbUEh%UC#;11mK1pBmhC{W8Mgab$|TCFBl4P zweOGCZzY1zg`Z%bf8rMi{m@(|!B8UqiC-X2BaL7GbddjOHtz$iaDi$7?R7zD04=OR)c{)P-@FgBo(8IcgOPy&p#ii;4pjqagHH2415jdz zI0-akfzSZj{)DOlwC$;RUj{-0Xowu4p@Wfu0aXKNwQcjh1qclrP@HrCL&F6|1_tB^ zgO_;SoUJGMTixcfFhB|zaDEH#{@Gp5(tWMlm81C)L>%Uk>YYB`FiWUu=HJc<>=uhb3HxB|?WKOoz2EM~O*yI7{~_ zVs(J*I8{0~J}wf}hK8rNtp6Dmi1MiUjR>|L=*MnQI|jTTq|@~QboTVP>k|$Z(2{}| zppabn0=CP@eJf~Z)PulYUyi`;6E7k*vM_Z2fHoJq`N8Ei%RCkaSV_hKVuO}5gGN)q z%{wYxI@L#3ZCyznE z_`qTCVa5SE7W74sMbU|2nmK|mK|ZytkyWgdfoeIA1Vr2Loo z2OocHexm?g+lFN`S|~^FZUa!C{?kq^&}!MGy}nmoXcjRu^txVwh9_uL)*Uo_4LRKy zydmleXrmEgzwL=`r0NM#M}V4&;4M%V`H+Q^pmtkm_nXEyG0aFiCV&bCeZ0F0NR@7 zF4E;D(Y+ObB0siPqpZVjC zeCCh4`g!SReu23#^KNWk%vC>3y5CG0v%f**t_TN|No!)1KMVT1G@?rsIibhb_bISDM&**XI(ANdGkM%-zT9+0Zf`~pp&WFD;RuRUNEjlA9%%3yq$vgxu!u0^M-MEB zcfwy-ftE?PgF>hI2y{DRmP0_VJ4?U||4l3m-R&%lpcQB!sVs-)0~`Up?k)i@Ou$ki z5UJ1n0<0X_Tmqf#UqDH>9aM#Nwu5T8&-`)ipd%}?{)2WefEGLRZ*P}jV_-<@YzOU2 z;osh_0O7TPB6NGZ3WNvpJOB1}4G3=$*i;@i1_sD>%Ya_+W{E6`fEOD|K;2k@!Jcy01RypbebFB+H`_ys_#5PP>T;9_7fJ_+$1 z)RxX(P(k$>;jQ*3pf>Ij@Y?tQ;{&ZHyU+7aJrK~_x&*wxCKD79U_HHM7LIV;pjM*W z32*}#w9nxNhy`jCyS)Il77e;vL1jSm0nj!Vw;zxYZT`trGq2nCN4)XbxED>Ch*BF; zmxD-f`3>?ryi)nm?aI@A5i~#t9#-p|Y5m2SH*W3qSMMfgRWD$I=aUK^p%xcb!gm zlh#Wm%)Nd#-He@J_kw!HVENzmxloqt}qN)zc0}1Dgv$)yK8v@g2TgJoP7Y! zmaPXWm3m!80)k%zmw^O0TK|^_wjQYDhzD&mh>ksc%*F0MLwsB`Y`OcHA4ev=qTm)%Pcp$eYII#Da-()fNx_&tB`r$w# zmq5Ua^g>q9xLorA*jXju3L~J`jpsO9OdLps<60Jm<|C-XOW^(ysGR_@{mhwOM;=JS z7b*a9KWJ6|#}|r)tPBu;AiEhP-~I80MIpjxHu+e61~Kp@Um-MPAbf~_cOm;%0K0!b zWHG$Z^JE9DOb4X}=%^fMfAeuSPz#UYn418D@qy!R;KMx9I^85X-DJ`_-4r_AR65)= zI^A?S+zde5XuDlGS`UCcC&yi%e7MIc5b(mX zgOwp5?8Q_!&{-)Q*oFeax<7`!IN-+4(CwxJ8qz*c!Wr=53nXrjyXk;j+U=&&3KqT# z69$(o-EJ}v;bSmi@UEh6HxY>NdYCZSKizIT5aAgxVX&XO-B=*PjWA*GSY`LQxR1~53f1-egUG5!~VE9hoyJy6QF<3l2sz~OEW z&~9nw?t_P$56D1OfaVuCL0R3pkf)fZ+mWN2Wkc(MQpMLy#s?ZIMHouNUz~AfXRt2d zDdz5W0Lg;K{EQ((f8g=3tp6E2|B>4JKG??Njc<3xe(0{{X#LOM(#XKTU@2c(nI)1MhJOIL_t+I(KRoIDxW&N_0@&!||HQ_*x5JDj93V5o|Nj3E zo@PhsP=N-;4~KTY>2>4?=yv7c-*zD2#a^&M94P(C;O+KS`UPq2jSDpa=ZEOKATHM$fI@sL1L330bZq~m`Ux21Gz*~<%(Fn(A_W6Jk&k-{0 z6Lu%szAjf(^SeVix_x=HPXz}3FBN#Px&u^hf@aoY5AiU7#(Tl)VPjyR^n#>biLFBIinYaDm(t*zL&j->~}xw1WuB%>w^}I6yN!PZ1FX)dDF`9gx$f2E6I;CJgDw z3(!>P*ftHiqs{jpknh#gg5wDh?$Q0llsw0bwteCa{7f zj_|x@?e-PviT=|0x!C(s!tf|N+(x_#dmpM8-IQVlsn12mrYo*eJXFz^9?g*I^cLX(*83K+mGQ1Fb`2Rm>*Q<+)&i_)5fEU~T z{r}&5MCG`P3iv37<_hqvGef6~3QzYr&^b{7FD`++Tce^PaGdSKJx<7uMu8U&8Q?(Z z_T>QihNs(?=Qvx-X>`r^^sByj(&K=z*sBnmFH+MXUORT2t>Zo?ig&i@go33>iNXxdbwHY~&Wm zV(j%%5qNR;-~ay^3R&C&y)NJlz8q8TgX-ytAhiNXaJ4VCVpo?5Qm28Wt{1yH#|Bs< z1(g3C4M2roH%BL5x8VOE)FxXXXlNYd-s5hdJ{tpc$_+Y^dE8Bek%@ufxSIrMZ0fih zxQ0hP^5eLh2B?t$Z7aM09i5ZK^1>sHm7)6ws6p|+L^zA_g`F)sLnk|^-l#K(kBdAU z54A21a;p_I^TX%oIKsoaf4<01XJt6f4oZF~LpaBevx7nnGVugzA9R;O)Z61!4~lS1 z_53*0LsUZC1UCO;*m1T6pnB?{9jGD20xS81QlUu-T*rbnbTjq_as+idupD<0`0)Xh z&YXU9d$9C6{^)cO{BoQLY)q9MJM=m)Q2ChkKjS}gX2Ci?-hC4~#@Sm9DmgouLBspb zEXUa|Byb5FcNg$TMc1hl*bo$v@*i~PdA0W>%YJ|3!@9ppw9 z_BHWb0^RIj7tZK(vHa70?uBJ51H*B)JuzGY-G@=nayixvZsZ^paG)_e@PrK5^Pu^( z-olLTb1y`r85m%J)?*6}G{~G)L9 z=3^1wm7l>~mfr0JjNp?sUnI1%GJu7$7{ZRXgM$w27|_TBNc#)>c2N3}04-aJMrz-I z&VMN7>1DYJQlx$8Gk-oCXa?sXXub$^Izhe5L50u!`JfXZ>Rk?kCUe|C=Rmj|1Rak7 zQrdD56dE8Up!uGbgCIYHc%bfl%R!L8KJ(Xs^|TxW`NcAjqtqB`O(SS}1f&?GwGlKd z1>%5oHVQC;P7{G>Y*YZ9@CI7)0gHJE4XMA=5%-H>Uq9Aa`{9LS6$?YJKWvrT3!^IV zl6%Hpe*@@hvg7XHKEg3~0fyu5;9kUWcko@i$K4?Xkvrt&v?-dnh*dl$^wOE?{-kXA9=KD1xOeiEuf((5a&2}Pzuy!-49wmoaF%SgK}M0 zw#i}$fVN_fyMc~qWH|2T1J>aNK6l`F8*C8lMQST614v^EfB1nc2GIC~TgZz5@QNde z-fbW|{VSJs*M2zOz6adlVPNR(e*<>u0Vw}?`w=(`bbJfgp7t|vu?uk46*voYybDC# z9k|#7IO_?V1v>r(r0&JO3UHV+_4f0yGB6x({{UC=g@u8kfgL3FgN1>?0_?Oua9IXc z$k~v`+gVsa_gMe`f2^GY6j(2EDp(jY8jKkPG6Mdy2xKv3vGi^iUOe=dIA?%Zpd(tGK}WPe zk7lWF29;```Rm$1rB)jMwPq0A-3H3loy{P!8=MR~n?Z@O8$4m!*$hf?-EE*0-q{Qy zyW2qdzOxxbcDI4jU}rOkY&}q?-+ivP8I()3Pj~wM3GX#w?EV3s=WzPGwA=R&E66D8 z$solwkGo4b;y?4}w}BFEZ#O6bf99`m2Jt|mpdp8PgYYVGX?rCg9LAYOMH zC}nmwgUIeSP}=Nl29f;R+Ca&(qZvf| z&*Sg{7h6%=cpNk!oaF$T4Z7y~qSu}0I6J6#4S=pEKJE@FT-_mst2?A{h0id&;Aj9B zuI`A!)jj0J=Xy{-_z%d`;|-wcC6I~78$fgI;F6%BhY@nw`SAwO+k+ zfR3zSU|?Vc9fuq6VkyKlQ0eWE1sWM|0G;E?3Yu3Ac+mlp^!?L(1XT5cHp7BuT^PDu zzZ`c3&ABjuIti{n_(cwMItoCAx?O*y@n3UPfJFas&{4Jw$DKh%8AGR|#%KO~=Hsp~ zQ$XiEbvl-O=FfLV(heFI5$JRTl?2WTD2m+_Ivs01^Vd0p8Ubzwy&FN97h&)5Mo@+a z`M0wX)GRpO2yY-Yf{GGQ5FBp=Wi*g;jyJ;FDUI-wwGm#jHi9xB$gJayu#)w7Bd8F8 zh=Kd#py`G4kabiq)&_&lLi)24luUbffCtr=LfVYbR0inc6< zfbNgSox!#LacA&>#>bsQz*abe8;!@og&0WS#qU~hVsOp@#TB@wb&h%Qtdpg?IpA^{Eb&-{_B&^cG;7aYON4DoT@hrws#Lb45NS&=F3jIvYVJxqzk=E7=1+-U}#Srj<0jh2@Xdy)RxfdVuK!yF-T@O+vZ zOTG}Z?Qu5_2n9)Gkn`S;xk)g*xcBq_|K81@$<_U!VgS;g(PU&`XgmhW^8S?{vI=^e zL355E`zBO@e9nVqOBXaVL;CMo|1;u=@-L{F2yP)ZgDTMDu75zqV!(^uU~nUmsrlUh z?%kl;w)96q(sNjZ-#~tl- z{eW`Z^vBMvp!w8pSB_pkk>)oXo#3fV(9vp;#pBSKs?M#TNmj^&=W(_@iCh9NrW7(T zG{1o@E${U+dC>$B0Yy-+U&xDMIG3r{ujEAvoXgzX2PzX^1i?jEdiy{geBl5WVeRb$ zH5p#$!A015`#@#X3mLcwdv70TIm8PtxClpYp9v!a!;2pUpacyndcdi?b1P`Rwfp#S zHVx4E;(jdcjIdEJwvuQr&V2xNTt!yu5wbj&v)*F3P@+@yxEIw{_ql)<+c-d82L%@> zS9YH}4(?%q*vG;B3kVC;uYj;%0e>9agJ5K2WPDL9$H1_V;US;E3dT~M<`ayIL2Pi6 z+R5^e50of{U-XxPQdK#Jz>CBHP*KbR3fT;hG-M%iH}8p++ycFB9Gx7;-FQH3hzM9o zrz6W^kPu{*aX0em`0;U&v&Z+lLx#U$lSh#9JgocU3()y2;89P=0&}($q!oN9D*(Wg zNua4sxqug+{lSieWiH4pH*{pV``nAf5(b92t}sQi$le*$eiK_4ku8?0>>0IGW|Ka-Fd(QosKNs{-EtCos6hM zW6-$l2bC(|#O+(m!f?DD#04cZ#8H-ClR(>Zmjw29^sq88yii;J|9`LVk{5BWm>9r$ zJBulcr?(xHsX>KBzza?vR)*gBprW8N_RTTZKf<731-CO$gY|DBQm}&CE5}^_@W1%> z{r~^o?Vuv4vlOIV1h%wxZ4qdbz%kc9d@q`cz++Fm-Tk0!1$KRZ5eq}}eo(5wn#)UGw1IWUKy=FmyeNa|jsfKa z=&ZtV(1ZeLTsY*#<9r5&|K%Ys{J{Eb;QH)f`XHy*yMs@!Kkn`VGNsqwRK9d(> zV0|)heQYp&kkJ~Hp=r>OjKyGmA}{WFfx`k@Tk;H~yv_Qb(T6B+8sC6cbK+{RHSYsu z3xQs6%b|#=n;|fuw-1!>ULh$oS*mSu`n1P=-dYqu>P?V|NZ|Db9pcL zn1fIJk*pP<)8oO-w}3SMr~{yti=d;aK{V(PpBI7`Ko#8|&|1xF_Q>J=QJe9;!e3|ed;0Xnuc zhm`@z7dbIt|GR?xkL(MuyJ5Zvhq~Wg0Om`W3`|1gh4cCU|9e|he3%#*0($#Gco-O7 zYQ(0wLLAY;Z0PJz$-5e%q{Cyp^P@JE67KdFSg__*x< z|LzhMgWeXEC*Tb?0x>E+0lj@SpoVjc8w2R_sxzSegvMhg(CCu8#%F#(7Zr)m`~vPO zh!v)wTew_QAj7jRDxiTc&`n+70oq;{6%)`MPtZm>==>!g6%A11*+s?T#m5-X^qPQ+ zibSuAiVT0$0nq8)I-t#2Dhe;Iz$AG<%QsLY1zv2A0eiUnOqL+3|1#FR;1mEY5D{Gl zUMArHioFGl;2^sK^441qu(v?tr7r>>F)58%>wqafSP>_+Q;|>T#g5P z;ur8aZt#g;Am+HmCw_sD;|`zr1yYWC@N2fHfD%0Dn;ulO&F#+v}TfT_#+>D=Ff+?GL2v4bQ-_N6|mDv()jDAsDOq;UoHim{P2&lG@zkghoQs^ zd@~y8oD$G|Lo2?6;v2M$EV5%e7RN=U1hhh0AdSC%i3+H;OXC-P@`*n}739dz z{Pithb6+R*wy1!H$pYYk*~@bjbUEbaat_#+>IQV}RE#C-U~A9)p&e!vlTG>u>5{U`oN(-n|H7aX-Q4?vOri9ho2C;rHH zpZFtHA+j+S()cwFf8vjLnZ~biACf3O@kieI#2+aNQ4tXXvLo`)C;o^RP&1Bv;*Wu` zkEQWzoQEdC8(=q>eBuYI_5ry@AOw`KVh}P%()dMQf8vig!LM=X6My8f&;0dkR6xVK zpZH@=r19swfI>m!5I6;Z_Ar2jQquTEj)R53Ekj7mr14+tQ316w1A3=`@2uw+@OXJv~vb; zpXjr~`$LUyX0Rdc&O#ke`q^y?zA)fhDf^3}FlL7C552t`e*XXe;_ChX|9e|OOlY?) zptm*QC+O^}J`+#}CDa2vWz5*TH{&Ph_OFQE)-_=1UXZF6+wL=gn*B_@Q&)g`Zw!!a zDV?n#-iwu`P`xMqcW(vhLhiCuzwio0bXi{Kys!>sVaQkjI{p@W3#dB?tp)Tn3e*Au znHvuA4Csto(6+*fZ~p)9{s0>9>OS|vO!V*D>){H+)4{9~XS zz#iXWVu0v}bwm$>&Nau@E!VIBM;o|P3K>r>Lxexp@nrBog7Nztw*b6x)CeXH(mIEcS-DN!Ppq<0$MjSEz_WA(S+CQKcB(zV9 zemNRs`6OsOv-t_=_SUfQj5+3@t1L4Z7z7wPeN-gC*FgLib!p%b=>E|9twc48A?&~C z4A6};J}Mlo2l%(01n&{zcR3Z->7&B)Uo-wH z7g`RKu{{IK9?dAk8iM(}_i2-y&17ztW%)Kd}`2{++a5FIUx~Q=5hx39q8iFf2 zK^GO4&-?<7puMq;2SEiQf7F36NE=E7d^L2`L2x5P=0$=&3q#k54j&bEm?L>#ya{Ax z=<-ov2OS1+tN|443@s;1*p0zE?GIiS8r( zQBU}zPVz_H2CLEln-g^?jbG&9Xa0K7&ix3`3Q`4#w@qH88G?>XE8&EA;}8!+hQ>?K zRXeym(sm!kBjGo|Q2>eo)ZIm3|1`bpZEpmR)99# z?gi~1eIa`T+%uU966yu-3JrjcJWsY{VF0a}Em3=MqmqT;6Td(&SP^)<{O;U>zYvWe z`bGQx|Nmi8#`?lCfSIAY0h;E!doBL`|8IP$cz+sb$RZ4sY+FGcB}l3Ycu{E0!jR?A{h`-& z0ciYwQamdI=nl+oHyO|_B)-r5b$%kCd!{2|XK-KOaZ+9mJ0q|J5gHYv6YL3Gg~Z@TFKSDxh^4;I$E8DbNB95D(N$Z&CRHZZBVRGw5_P z02h>S3$7Z#JlXt%xiqg~k4hh?lr80J*rU=9V)3_tE*=4!30e_i3_1k_bPHFD$^wY( zpoN(EEh?bd9fXCT86VKqPzJ}{3_zVcpAH>2=H-+vN70~UYpZNtr4iRWkSpmAR%}oX5P(e3| z<8I*NDv<4eq>u12Q)xNEqjhNZgO0Lne!!2gz4<{o#BNYc)aj@I`+vvX3_!J1ryB=q ze5t|>09`S~#K5ovbXQzF=$a`mxD+UdKi8QS{`tOcmG6`qaVFsS-<%}Z5Qae z9x>!NI;0Es1?VD9&`yQmOaK4B(1Z8`OTIs13|@oRq5?X78yY7Y7~?@}m%y2ZhY2*8 z0l7@AMMVb611(!_Q32iF0m?I=;;==<1}f(O)(0BT0m%h`c`;Bq(3;2=l^iIq02Bhk zaOZ-e9gbn~51O@uR9T?%5j4X9TGSa1zF7@)UvY?vK&Ow22-5v=mpnoD$94CED;m$* zmXoDk87DxA;tzVFuz@BDha0d&0d5WmUIf*m;2;IrXME;Gz78x%8~=d{J^ohE0h7Hw zDxd>oUVOap|No0KplJsm6_MT+u;ASo6$x;+SOQiHMH_(&*nkX%SDXSFCa=Iv6IcRm zQ31^{K<_%=cpc)L9u?3kG*APj{sOv-?rOta)V)Pz0~6>FnNrUT3y{$nuQ&z5vKYg{ z!g?WN7a5>ZIp9SU)L0*t43L@H7-n|D&HT(S5TnA=+kb=y6!`)nDgt3Ie!DY(TA2YE zIUq|Gpt~QmEDIW(AFsjO53VcrL4_A|CgE}^36_nW`^*v zULO^Sz}}8GYzz!9zT1Ht$O6q391Q$(4!;mT&&1GjyM(FJ9J00zsR0h!e-p|BKH$ar zLNLGkh3=ci2bzDe6vcqjW3M+ycyHC8=3@c}-!r-Qvg`$Qwm+fDU&$ zz5t2cfbrgdcn@H_4HhdQ>qEto-M$>Xo}hLX%R#6lOS6OZp`y2-3)#Va zNl*yE+dq)Z0&3qaT=I%jAULf1W~b|xw1q2PaSHVMZU_(T^%gni`kCRl>juzXptMfc z9miaEF}#@V&cM+9quU>J^0a8Tq4jzGsfYNtT?+ai2HKVa^3QR0n>f&pybYc4ES>cN z3%9%i4aL^6u6e~N(CNA-ZQ+hroC1Np-X>7vK}Xzxnn+vHIzji9A7Xf6PJ|s(K$8}& z8UO$P?~G^Z^)~6O2W^*N-Sdi5AmEtmYKG%rInd&R&;0eRIiM5$!H3N=ytwH`*atrG zTmrpd6HrXQK-lzZB22#k3LkG1X!yK=hR+j7`1HDN2!MtRXe|mjWI%V!y-*~=WR_$u z0Z?FoLw>;@sL5YmaSC*}?m;pcbf6H_K-24=`RiS`bb#(< zI?C`uj0lr$Vn7ZKfdujblh>d`n9r&LcJ7h1g$iH~fUh~|1-Hjtw}952zqUA7*%Q(V39Lv!sr*hk)}LDF0-5fUJmT0XZHKBvPQw z7GmJ}VxD8JZ48hby#jl^OI{QZwBR`VlO#|ql|W)?VF@&rQb0Dj9$8QU_QDAyFNlJA zcc7$j%=IM03qB%jn38~OLkrl3I@TJn4SN=JfNeN{WCQ5jEodMeWO%X0iBKRNXa53< zUGPO_5O08@qX!fV3#Wk7aW`oA9uZ>5i72fToC1%vLei2Q5w^_%EnCS$DM1-4#WISskDP z5^mN7s96&*%;F=$ED=!r!_9gCHOmFVtV0fj!|MnrwZhH%05$7}Cb}QXh%n0q#a%3K zI0Zn3!WxiSU>gE^yFrsQFSLj->kUepkbs(%pb45L2yKp{H}p) zk+(>|i&D5+X^`3&gxb@nYE1%Oc*51ngVdHF)Xqm$8xrtB7Oqwqq_zX0wis1yNx+Mb zb}*l+gVfGJs0HmDY<>d|7*O^McyS1>Tmz(h3qrXBiqYMm8MA;Fli|uWLCVh{l)qF* z4vlW`T+WLWxN0v14F+K?~KQQ362E?G=K*rb1NcTCPf-7LpV#vsU#3|5y{)K!yc*R5aaq!UJ zLpiW_4k0#ULFTiX-v|VE-|Y4M0cw$lcQb$H7ihS^2I|2?G=S!|y4_eHiv(PMSf401 z>gMYW{b7BoT(kR^_RoX=nXTP8N;$I_yU)F705wznSXxh(Xm_)H;um1~@rhrM@wFUC z1s_;NoI7;!2;|%wmQVbG49#vV9No;_ek>q+=dgj!toQ)6?}PQhV%u)E-p~)$hssU5 ze`)^!+2;qdPXKP88PvXbkcA)vVLKwM{WwY?RzG%wSp5ObYP22;tiPlJ3KAa`4x}&v zEpLT~g^P-S^@(ERZob|S6#=ZFQ3Pt9fN=3)Udw|*gC86k0T3s-s0g6B2_77v zl}WuWDiVwom+mAu1f*r5vC`G(h`! zwp)VC5^zyr0f~SX$8?|j#2?`TS`8xTqQdiHnk9H5$pN%hy9>hh0I};J>;MqE$dZ8p zefA78-u_0Rn-QE3K<jKXIfuIx4I2#Xw>Obgem2QD<2Nvx^2Y)aJ1ig?1 zt^4rhXgO*kTNJJ@4<==P*#Qb@`WwLmms6j z?1d?Y)_&0V_J!?Zd!d_!7NMZ{0I!!_fmnjm{Kf|5P%97Usa*#)?+d|23s`b8QKg0?UOgul?958n8y z&mVr^xQmJjXn>Vp(?tbz-ae}YBp52 z!Pe={((T4_@r4RwhdXb#8_U5LOe&1W+<6!}-1(sUV7|GrFqUv1bLW9=jOk{x{r~@e zJ%9f&OdWw##(zsteSUeI~3kd2J3Crc%} z&%cm9{Qv)d^KS4Kv>3+M%(Vca=21~lN@3c4({ zw;gm4M`tT&Pgt+JLuV^!@pbd@gkCp;&R)>9Cf!>>Qk|_4|NsAg&E5++pZ7C=K4bTk zsUT-$ff`EepwkBG96_h-x(jqWg6}zVvg!76=xhTW+t3X*wX+X&b82@l$fVEw`Hl}j z%LhPfTp2+N3cA5=CtEkzd7W-7y{%V3S53ayV+Y!$2X=oM z2k0zXkZ?Enmc-tAnQpNEK<83}T`l0$47OjO8Egd$$Tmn2fOLZHVFft^)GloO@(;8Y zyWRmb-Oko#3#81W@xYCjOq+|Nj5)1}BFX8`A#&?*{Kc z1#M9KVSM(5oFKTMKHLpDO%xV|pq-eV;1hMBQ5bO$DGC>WqVOv#14FO7!|_%HXyWQ@ z1w~wMKX_j?IBt)(s=(zy$-6f!0}`XhTP5HUpc9F~Q7Uk}RR${hnLoc5qyiG*y>15G zTS3Z>gF_6IJv+fW20N#M(g4J}pmQ#J%Q$-LWj^!QyFUS)uMCdxFWn9jo$h}=^XD^l zgSGz$lb`wP89(#qJAqDQ0=K%IKsnSA6tqqT-BZAOFhBFxI~sIDQwr!b07y!K##d(_ z=sbY#UXZ6jmP3+AGdK{yratHl0JUAa!Hxu_8&HC5KIG61KD)Tn?FVEhXQ$gAm{w32 zu|Pa^9OO%eZg5O~=C9}M279>qfK2m22Z)E8_kxlt6C@<~dqBNULx4?G1sXEAS|3CwM{zq)q{J(m!|mbkStGr&`c{Wr!%KOo5a|$6Ga^39$Ki!tqwnhHQ`$P-+B8KoWT8R8Wy~ zycLx6KuZp~|AYJ^lLa}`gdOB19neA60^M#V;2RY!I-9^-h1_g9n?OsuyWKdtJ#4xi z96GtWdqI|WI)P4Ub>o4Q44_o^02KC4KOhClagZ(GQ#d$ZBwE3X7EnUZ2bVbAU>AW) z6i{LW-4N|2OR!`ixWto@q_a#G(vKd&?DqF4I6_x4^Hopg1y&00aBeb9tTwiy>0@Xy`Vw|QYduxf(n^V zNO{o!PHu;k`Jj;M?1z;3AmxxO49ZfV^7cVzASmy` zaxFB=vO{yMI}4=H?d_cd+Rz2+R)eCSUjTgTkwCYD1ixS_=t4bEXhUf5$|`Uurtx3% z6X5~pnq+W}@2y9wH$cg)w@e0FvN$$_%P#?Nbb}lYsWHI81+wl5 zBr}7qp2^2iV>BOt6(K*F_Al=rPO44T;$do%fsq8FSuo3Uq&jEaU-^8K4D2 zVJ~{NF)?)e{%Ag;(tXVMY<%2{(_9c;y`BtCml*__PcsN;oo5jEah^dS`7(om+gS#I z&Wj8JptcJLL)Kq2vLUU12c5ZvbxZKg&RFn$hNS|{4;WcN$DH)CIP~%~gU*Qe<*+_h ztYQ5De1`MI7uFw&CBk0wS{H(@hdc(lb?#Weiv#AM!B~#YLKfryt>5@tKzj#_4|KW; zbW1Yd0GLt*MYA5g&18C*!sUj?N~E-!~bj9?${T-p>x86U^e^@P=Gn2LcP~_ z4s_-Di%V-kMhLjGwy-iVbh-*y|0~w(_T_lV4?5Zgp=>o+*&B@glZSX1n*RwDn?kIC z_#rH)n-OH)UQh<=?FG3OW?RZyCWhAk6*6wk{{)Io8>3#;13trr2mN?Bs3<5EATT67 zXdu!<^P3o~iQ#8=smKliP(;NFSbyMm{}2`oI;9qLbwld`{tj`_N-*%I9M=~ww)?R# z7+<;@`v4T{pc6hoS8P4_#4n(FAe&2|n`d(C$&$csMvoF9j}rdo7tEzDpZEnjUobE* zyap}L>;x6z{NcAjH%^u5r19%tEK^GZZ&!&qlE$wO+PLHTqD%tBEE586)e>}l@tT7_ z{Prh)0oNB!*4K(=r}66_E_3MJ4(+_~ATIoJebF7u(R~=X2V)&`PNEbvEC;zp45S#; zcX`bWQVHIf-5WaNe<@FJH)GKM03BFTEM3t0twNyJo3XPW)NSZK|3Z&}fuYxT1}u{H zuLiCE!HjAF26zO3`eSb#;GKy-Vc}T@y{>1ve}b0m-ZuuXem(Ab2DJUI7j&Vw=$u9l z0njagO&kKP2TG#5OK-G(D;4f8z0&%vl;^+bk|yZx0Y}U2pra~EEIYw;H!pZ23+Tv+ zmCE2FCyq59yu;7HFthtt_lNMX7mF1c7THYi|Bx=U09dVN$lUL0Em@;Lff0LTE4{x>Gzj&crY532y@ zCw_rU4d{NXLW4AZ(3UNMN)FHltWW#`kqT-2;Xl&&!*6`z7p#5rnZMrm4tO1|0BCiQ z#x;n>$m?nR8lZhwk3rk^K#INDg{1boV#ZUYKo)T&N8b3dQ_w_~Af|P-FO}W1L#2;}M z7A=9$H=p<; zZ++sAIF`mQ^7Au)e(9ah{Ph(IpZFu6rSXe=`plmn3ffQz+O&1`Gk-m(Hya@Ei9hBr z=$bR|3Tu?vpfhJ6l_l2m`5Nr8p3jFeJq8-D1P>K=|HQbu8gy%Hv2eGWfJ2FRKv?*T zL>6%Be9hI(*2xapb%lIMRrhh!F(UAl9T?}O!}f1+2E4H22bsqLF$uO~tK0Df=%8O0 zju&r0C;d9U=ni1%b$Ze1!u15~@WA7Y3qU6uKYz*wK9V@ByU^q~Ce(}%7+(S#3`(qL&YWpJ@gJFc2JGJd0TRtW{+F_FABa2L z?WXgequWm=u3NCziLsNBe;X6B22gqj)l!LKE1$45S1ZXNj`yWV^^o?#u z9ZiF7M;S(g*V-TvP(>rt{NsO#ezz}22cu)Ni;4har!Plyhzbuw^YQ;6HO-g*x8COO z&-(xWe+|gJ;C62}Xk^w!MF2V(!^6-G^#EJ|8j=u-P+hlc?uJQNrWUh9JV+Fi=gEeN_<;eQYhC|I;Wf^LvdDTRj$G(jI)ZSdKe@uF+#S?f_ac$8g*MRPi#z9ui?7O}zp` z_d(FD3Xre|k;Vs*Q|Fm8D2e~fnKRvvKOp%Ha`?C74{(0_(dokV1*|a)bQh!hj9&i@ zU}Y9Fzz1-<&j2f%(dl9}<+%HXJuzGYFCM8fFm#tcIqtrJU~cT<07VT;xBCpJp<6(C z-F*i5Snmg&E|yce-B&=QR)EhWcV7XP`qAlPxdfpLTtYx~y#VQok2~D$_yDYt;{n)A z#|L1CKInAey3-r@quUAMTP#PNcRN7}9sx+fHDYke~D0dVDO7SDy*Od7R^U^ zTK|_ibh`<3hyLiU{nHs|(J9gGrT`)gIzdB}-`s3iKs=ceUg-FWn@*?1>r#-I&T-H> z3x?Mj-L-$Z4{IM}bh7}5O7~&yi`vJ#{REgVGctCc?sikqKE>?&17w~-CkM#H5>e1m z`k;e~kquRV=ysC<1tgF5dFIpF7o9*B$$-LAr&HjYn+;_>6r}NP|)WH1&Ya-z${q7Hhp! z$_kP?9Nt~2)6LF&$ofJt8~-+@__)L09Bo)ib-EoDxwgnYtui3h51-eUlTL1I+a4|A4)N{0c<8K1R zf44JFH%GU#h4#Uj*1!1s-!d>T)NojT;BS8na)Gmsw(lS2bDA98&N7S~-&`e__*<@l zB@{rnzJrhEI0oj+bPIGlgYuBG0<*7#_Nh(~x0B-~sDt?JAQOK}J4l&OXQ)K$rINaC zJYF*dc})c5t3yQls>T9TAr~2;_@-XDhQ<0rxoo$yfwr#%#1{&T9Iqun#vbdg72rNz z!h;-2pgFq=miSJCIIJZNUXXPoCiJSc$OiQW54-o^atE z#X?ZIUpKx1osxjm-__3&2hKyje~iz* zc>9Be0kl6CdZy6_&=A;8Ar{z~Mj(E`3t?&4Z7JaL1k^s%3~xUFA9UB>anPZorIMg6 z{Qm`d-8eq*AGGi<r-J zPwh|5|Lp77_t}HG>MX6_Dn!Eqd)-+&%>!OMmID>7JjYz@SQz5EkH>>bIVc4+8cadP z88h`r4FBrS0`)7A4M`!7Ryl%xf7k+geNVi& zyc|3aDt^rM4@-0H4uK-O|D{V_H2h})9XRmX5Hympr`L54NG)i#e9wzTy5M6WSh{Y2 zm2-oX2SSv$+%7eTj2P_%jbFbA_xb-Hw619WEZ88|aaZtF(_n9F&IWs%{iQF+OTH&w zc!0fFVgoUv`@{=zsQ!4Y`d@-XeNTV}*Ivv$#mMl|n4ss)%K!gIxO(Kq{-60|nKTP(9_~G_UY<@^Za)ab4Mh4IwS&6a#|Gxx{HbH~!#erH-5SOfk@i##D zGrL_cSi4>+o!IRTD!bUi|6gc6!qN*K4DLP`@FH_26T|DC9iX#CAr9(3@q!iV8egog zxjqvdqO9Gn4?tNr;J+wn_z0T({+Hf)@s|OVIauIH7MwhrYZbs(ck#UF`U?&av@6Ix1I{=MpbT^e zl!0J52a@StKr#?G3-*HNoWUt+{&cXvS-ROl2W4GnVqoa@0B0c3Hc#+yRXNLxSH~e4 zXfHTZodIW{w%4!>bO)M&=7Y9;gENr8an~cz47B06E9e+!hGVW97+!oT`Tsw-*LMLZ z2fa|00p-vQ$6Wt#1oZlzdC|HA6xF4+&9z6sVY=ak*&lG2g0fe)>jJ2mNalfD3_4Ce z-~|sv)`BjmoC#3{$+w`XN=TZY?*U2k&!>UXJV^XFwEM)1c&Ps6SoIrDXJY8}1$m3{#nWSq3@<^umj9Q|0eShV6az!n|6{Iy zxO-g%vKRt-eK%kR*^B&QP#M;7%=Hg%K(FtD7xSeU7`j~-K!W1vFSMZ80ug`&MF*yF z5N&-BRlVRP1fZyl+5syJK)!+mOq)9-V9rg&7BCSY??OGsa|~1%2)qc1gck-gz$s*N zB`Ae}3Ihm#F@!&}+x3dI>kW*;0Ax3)Fo>CoR2YB-PrUfy262r8R@a=G3eFU)-L6ki z3IouwRSf@2AH4VgNpJ9q3!K%OYgNDrSKvkMPjEP5D-0CC_Z?>a&$x-4|F?h+s5>x$ zTfi7}9(FLwf!LthvpbgOcFZrht+!*a6@Q_S9iW`Ot(A2Gz02&%s56;4!cxpru3{NKG%u?Jp)D0ck67>ORps z6=dy;Bv(kRteOl;BOoD&uR$~9plP2MhEqTiAkE+@pGSuo8D3^HGBC8>E;a7$J@D)Q z{}=zJ{{P=Q6~qLUGQAL+ey(O_fXIWgVb_fpHx~Z?|C+!1GF1NNYG#J68xU8t+%6G? z3QyV!PRFhg2}nBL=K^sf8!k8Yf+gT?v;(;j)YI*4o$w2Ex)j7k&&$AR*#%YfB1BZL z8yuI`t)O@;ZA7c&K;Z&P*DaHn7+zle_y0fGVJ|@wr_dS?tm4EAVW?B1CxJo@B#0KA zk0voO9CroZsniWl7Oe+L1YuPlSO8Ra{ND;nJ1_p=NYuU`jL*K{cn5Ceg3mO8v=4na zkm@&3DGghnb~K>Z^-IcPkjdR2p;g*3*CPzaT|uY9qqPasz>Pv^#dh2kT?f z$6dkMv9}jAK@Cf>7bZYcEE}kD2t%Y;Z&0#xJreN0jOB&&K~TEmZw1etyB-PX^%Hrq z{Rud&@*Q)%0!^rLARWF(Uc3dXF7fM~3bLsC#EU&npe-F70WX**g2ELfiYVimUi5-Q zeUE?>sN+FK(2de4(?_7;2@ZztTAp6tBdz~SH5zJx+OFM@v8{ zq*MjuBBKMZ<-qD#y4hb}?*&OO151}Y>~?+8$-aRR;<}atB|^QvM_%0A1WvdD5K&0_ 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≫1Hb5=$ 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

a|0PP@jNPR#I@v+e?kv5P9O0ma{^=kq+*!JP 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%0Dh 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�lM0uCR>Oh9 z_&7MEAxjqTb)c_?15JK{Hj6J@1|D%ho$qL{6#(U3{?=v&28OWkZrdLX90D0nc5{F( zX}jKSYSO?V5b*z6>w%pHeyjo+40|{P_+1WWF)RjMsrmmpM2f+eRUktJE|n9oUm%Tp^Bjbd33)UsaRC*9Y&4{BfN zV(j%~>~P@%T`vB)*Y`-Th#g4yH5+t16F&$dVv=V2-e^Cx_%$Fqgx;_Ya zA^rhj7pRMe%Px7aT~82pDIt6#4t6}qHy`*98u-CIgOt=EJqmc&2OJA23w1yPP`m-j zyaL@k9mWSN8$qGQKmPzk9VC9XA>s#1`=t9L{uauNkFY$LwF;aEp&o!&$>Q3-|9AU= z8ZMxaZarDT4O(;pITnHgsqJvzAEo{URh@^>HmpJ1`xD{b#y1MA$n_`2`64%d{r}(V z?hw%1d*#>v|1Y|=e*f=|kAU#H%TtcK$AH^7?hz0Q+*v*D4mxXr;f0_7-~X+*`CGO! zGBC7$tIG?^=m2GL@Y0YBP+c7GV)F)&mj!xTAN>0NKLAoSXIZ>>z7izN(%E_kw3OHt zbi*-2>wyxv-d>P8P#yg5|Np=&mW&&_IRv^-ya@UD|NmsR8V_Lw$cbmUOn2`ZG|IzJi(t4nT2Q&iS$RY6ZAm{=V{(NTzj8*~2bua#b zHgy-XfLj8+TR(t!#@Z*Cj|B$2Xa;TVt2b#rqS0+`{k^2L*O>#<9|6^C-C+VnEZrQh znYvGOGl87`>;M12|HUlbr~VuN58!C1<7Ftd>vn^5Z=||EbhCl`NZKI%FkZ>G*V5f? zkj|5Ubpb~yclQTa*Xcv|hhAq6>+hwLy7z)&tGQZ6pu58S|bDwENJR`G0_(#HGy)6FQ}fZoDV5~!TAG{o*c5_ z^$(8q0No$E;SbfzauwtM0G3`qnNHUafxW&@UKnWn{@-0^((48uF6nfA0SZa} z7SLJZ-F^bSaRS{S4c)#Ux&*BRN~KyZl?ZhOGFk;Nmhv?pWNJRZ)N-lxiSdEgtkMUX zPcXI~DDgrKS}|B)mTJRTCEs4l!-7==6yBIYYyG{n@wI%n?~7j7H^BifezSwl6Zrt< zzxZGJCg8> zLcohhYQO(?gZnYi^1t;Pf6Hc2uzRy~Gk4o{x?X8LS;E!L*c*B!DExl_WPIigxJl&- zI>?>jnClIOQWoO_uZ6ph_XaRR>o3UR0*3;^dwp-bn9KV6|Nqh}y{Aj{&l9aqUuY0_`s2IPQvWJ1AlL z{s;A$FThgeZ!her^6?y`R0&R+U;+|;E0Dua1rdHIorRy>{w&?>-K88TArl4)89N3{ zw?PN7&h-Yu2eD2ChJga5g9R2S(2&O$F4nTY|978%0UF|Ju6+X|ZF zV2#v2v%%g3Ed@sM-vea-$sqiPTA15{`f*SvfzF=!21*R#m_BQ;f2;_$5JHN z4H}RUXg~dnXa%3!(YX0}HM5fD$$;y$b zl(+fc{}TQ#CuS>0<`Q;rb_Nyhtp`fQx?NvbA1-EXKJouGhw%Z+*cbd$540ZOpK=&9 zr~+~YBvpkk28SSMVx!xgrQ27blcT#HbmC4c*Z==u4}jEhywHcJLu&uL83t~w0wC6Z(G>6)bRWnCFB$|v*QCKmIt<;>ax%!f5dTd;_^%oJ z_~=K758u4_t%&Z!5|v(vn;6O&7_$EV-v+Y$zvzrc4uM{XL#_+_`QPj201lzuiogGZ zcO@~tc<>EW(m+P%rnvq6-|GvS8v?Z?UbMPlaVsc3!osuub$|RX8Upg?f68e~D3#6n|G&%z>X^x8-~f8meeOlYxBvfN--K);2d&otACSQMV&nh+|BVlTPXz** z48f4_IE)+~NaYu5{{GnQD$whDrMs5H=ys>;4Ui9yx!z}ZaYF%=WhEG)S-(W6u`b~S zGXp~n=YO}9W3KlZUq^tN+3>bk_5yG`ce-8x73!@ANd;PDg{+%$;r#|J@Qg-D1ECD=pm;__y8W_q);S3+jD zuyb1v@VD$MVPfd@VCiINJz2uk$=K@w+I+&)$(VNBfrpV1)M5|IlIZ^Uq7&4FxzK!s z1$=4_Tdx;OCsXUm5|(bZPR3p@kR~v*`%v8B7g;69v#{XxJ(As*yPa9OPk@J=4Z=W& zN_5*p`hVSp0@mM)S-U+sUh_9p@iLUKTL0sBy4ZcQn-iqE&DW2@;|ssCkY-z1`R61L}0_p!7o(jffoDxX+FZz zP|wTIeZOQ2^vDbNTo}j^p!6Eb5!PMA(aqNB!~t!pGJ__`ome{ESh^Xl16WFVLGz-Z zsc!IYk8URxYk^XpP6P1lH(02%05TO0=77wFVVLjHSlb7fbd37lIar%?GWeV*`yvvUM_a zvvoRfbhANMlErmH=Cwg1?mP_Ehe}c*@eOLJcb_PA?hfDp$E!3nUiG2z(R~3TQ1b1y zOm_eaSdFl?6Gtgu_n}T#p6(#9P|4fQP@ceE*FW9o0$xahDgjp>Ygd8Nh26d!pi|8c zLac?vKj^#(SDxUo?wg&if5Jf%>gCV={|B8RVFYULmaukLalDr6b^`Y&N?5x8y%y~D z<>~bO(Ot;_THgUGoxo9C#8S%KS<|H8W_rHM6BasS-$G z2}}36*J7alGsw54T!=ZHZstx7kaiCK);7>mjCx*%687$MogN&oE4$q}y3d0(aCe`8 zPTrJ!?Pdl^#&r6zbTf4_T6=MnvUGoZEd{csyAa}@PP=X=4$$zj6Gx{9+;twHwG>V) zmI9?LogA-0rgS^8bULzhIq`Id{^;`L=>ReQba?SJRPiwKw}Mt`cQad8u<*CAGBPm0 z#%CJpL6V?DBf9ylf0h=2m!I%3lnR3ukaV98JLbm2@IoB4jsdbRg}=2H6djBW6+Dck zoM3P8FqULM8Kt7#jDet~8{lOvr(f7XGcGSJ;?SS}|6f;u z7JifpAzQ`;(gRsRA__BB4m4@T!&oW?HkY~kUw0V`$SbY3|NsAgZ3>kIDMz+F0kle* z56N;ynBB`jGNFHtx$`h~7m0v2ilWRlNx_Q+w7I6xKS3{eLCqj%mgXZY-M&1aBZ@pa zomn7f&31Bt(j}~`0?uNP`syE|zJfMJk)|g=^Cc@7OC3SuksvmB?gUyl5om#U%>)u~X|M&&bTgD1cJqQ7z}>DKkO_^GCH$R^Je?jK&}og> z!^a)K8{^>o*q60WVGGT`rh(@VVdj})pCw_3Ye$|X`PdDfC5b&8`_l3ml9`b3BELNu zbN@edc1v#tYS>7Co0R`cMIg)GK!LO#bd(or^Ach|3Fjq%q8@x+f-7hx8roKTKXuT6 zKk|7A@>mbCP-0|YKt05Qg}?m^0|Ud0o;Uyh^KU!Q3qHi+`wi&>%?DTlAO~B#*kA-2 z(8t`EKjQ^R9CRWE{78$`LlB3wf=;05g&t{9aN{?Xj58iGiVr2V&MnSq6sUEudANMh9XKR|K*OWCpSdLNl%WJk|`QP31o>wyxx-d^y^boe6K!2cJzKR^_xHaa;CF%D`?44$+= zaQMJ^XTaxq)(J3_D!wQZ1D!|xB3qJy;kX-QhTjc*ZozRk3DBT-vmHaJSogUXS<+y2 z%AjV$xwx0Vg%}txX6<01cjgReO0fjA==ozt%@YoR|JO4nJOLe8A@l!w#u6|~;s5oF zEnt?)|LYk?z$}gb*E6nwSvvo(XS@Nk4E|rwV0jACYx4hkh76cx@&9^;37BQ`|9VCM znC0;QdPWYIlqiotdRfLGhTpM5&y4eFgyd< z5%d3gh6tFI@c(*-2AGxd|9XZEn3Vyt4a~~ z)qs2nVu3r)|F3790CQRx7#RLv&$t8Tfcx>+Gd_ShJrEg|=Ntl^ZJ^s1{$J0K0CT25 zWOTqB(CrHUuV*-bIddQ~Az%(@So#0;j0`Xbw9NVc^^6)Y2XtQ@C?dd|H4r^Zz#P!= z^`HO(b3peI{=c4a2FwBN82^7g;{lkn2cqW-m;;)R`+q%y;|0i}po;j5@FbC8!2c-Zo2ej20lnB5a(AEJ^ zIskJNK<$g`87IITPzel52Vf3pd&B?h86UtL(C%B1LtlX$3c7wCln%fg6NmviV2%ZZ z;{fK^KsX^_4(NVEP&xo}KsPaif)~v3fGC>+=J-H3YrvcU22hifR^xsTn*+lK=e!ib6Oyr1z-;7I`#k8Gd6%ZpbO6bU(YxI=1hPny8z})fp8vx zIWr)f4`9w52#4Vf$Uh4p904$A3525n=B$8l48WW<5RLFoF5QQ2$=H+!bt&h zK*zZKzn)P7=CFXy<-eZM0_Jc)I8(qJ9tdXxm;-9?fg%gc5rN3u0dpiEoDX1*41~jS z4CGJ+2uB9YQGsv_z#I(-#|6yMfp9{=90Ld^1I#gjaB9FD3katN%&~!RmVh~+o7X^@ z7R+&h$Q%K4KsU94%0w{72O{$Y%n5*SIF5rH8Uo?SfH@Hmjs}<$1L2r}ISCMs3z(Av z;e>!W84ykmn3DtHw17DU5Y7xRrv$=T0_IdeI9tG+8VKhAn9~5^TmW-gAe=j3P6veZ z2F&S!aDIR}6CfOp6CnRgfpA2?oEZ>~3Yaqo!Z84I7C<--V9pW<#|O+=0pY}eIcp%C z3@~Q{gi`_LY=Llkz?>Zr&H^xJ4}`M?%sBwz907BVKsYzRoD&ev8!+b#gu`$W=U1LpjJa6W)J49wsr0m~_nLs=jk2{4BP!qEY9cpw}HFh>Bw2?29JOZz|t zKA0l`k*NW5WFVXgV2%QWvjoghfpB(!IT{eo88Al&!g&DZ7(h5*z#J0@hvPKJp%xI1 z447jB;TV894iJtDnBxNBM1VOS5Ka!5;{)L|fH?sW&J-{w1j1PX=0rd^2f!TA1&IHz zXWRgD5+E`kz#P!^i=aly8IapDATkPIP7Z`)0p=7yI00Zz351ga=2Sp99birkgtGw5 zX@GDxfH^G?&H*r|1H!og=JY@~55SxW5Y87cX9|SFau(#a84!*Dm@@~$kpXiSKsY8~ z&Jqa62h3Rk;Us`LYapBwFlPgV(*ovffpDgPIXfVnHDJyj2xkwNa{$7*0_GfnaNdA9 zCmw18fN(y5Ie#D=hVvkYf>yEqzn&og=CH7UGm`?C!vW!# zfH^!6jt7_{0O7=dIU*2F0hl8J;k1A`G7!!TFh>ExSp(*%KsX1$91RHP3Yen<;k*EI z3?Q68V2%ldBX9xaY6}QQ1h7*E4*;92ba80+{0g;gobIcEw)Mh488 z0pXZ{IddQ!A24SDgp&Z~EP-%pz?>Bj&I~YT4TQ4+%-I0poB(sSKsYzR9MCOWpq>Pn zvj-x>av9_t&@I`ZE)SS<1R|pY=A3|V9Kf725Kah~a{2ABg4gB@TFGz_kQInXfp0Oml$fae;> z9%vY-fH_ca+kiPxZwG)mP;b|OIZ$uU0dt_<-T>x6y?q4Cfq1*K4dmmD2iL%!`vR7c z0f#{b%XN?oKnoB-DFn<>fykJEIT{d-3z(w=;e>!W1`tjPm}3Ir)POk_5Y7}Z#|FY# z1LinDI48gy7YOGGnBxKAaNGbn#|OgE0doQ%92YPr1j2~{b0Q#|955#a!f60=5+Ixz zU``5zvj)t`fN=JJIXMu{6)>j&!g&Galt4Itz?=#QN8~2RZ8Z>%4w%yb=5)5Ture@Y zxZDH>Zwy$b11ytK0_OBUI6Yv_1PEsdm@@^!*#YLvfN;)$IddSKJ7CTN2@{F^0GPcN%#HxF*MZpy|NsB*Y|Q|RtOtt}fY}?s>hEQoz)b8ZfnH3Yglm15E8X1E!9=08?ie?trvkQ2g#or2AhIYKwh!oq^AG=Z~P55Kiu8&6%#4 zg#~D^x%r=X(ROERh`U?8K@a}Gc_9CtYcI@^yxI2vHi2?)mn z%sB($B!D>=AexaCE?&FA$CknDYa|NdR*|`<4D*%cuZz7}yvX{$Ia6-Tw6$mE-%+Y{wYQP*F z2xkJAV*uf-0CP+roIPNU1%z`2%&~!R-hep{5DvowkaJuh91$?b1H#b(b9^8i2QVi9 z!ifNLLLi(1Fed`S=>T(LAe<#&P6C8;0?bK)aGroU84wQ3Ly!w{ARHAirvSpS0dqViFb7~-*3NWVu!s!8XS|FSyU`_{wa|F!kfpG4CITOH~&h{y63=EJ(afs;= z(EL*48_=jZyv6{XXLGz2R3UtM2r5lM)d9~V5DQcpsDN3Zs=(zDhd}c_P?~4xZQBbf zi@`;3Z`(dF8&nAQw(SSALB()y+W{~eR1o*J9R#yMMR9N2Aut_Z`%nlV@_||NibtcZ`&y_V@+?{X)t3; zZ`&C#V^43}Suo>BZ`(OA<4kYcc`)NjZ`%bh<4$keMKI$@Z`&m><4tedWpFhEs`)a& zfdH!gTEHw&-M0YD0@ZwbKrGjW8(^yA1(=$^@EBAF%#Z<73rxV&iU=^Zp#)6r=mAp) z7J#V}Tfo$X6JYAb12FY~;R(o;7b0NlgAQn3%Js`}*B=f~I0Q-r|BDthaR>x-w}B$% z|Ap5)-EE+Z+IpZw_Wy;}10~|1N<}E37aUJn5&@a^Al1-b<2XPnC=hY!~8%~84Sl=LDL%y$6Wt2w0jKcUuwV}wAFyQPp9(M&3JIiJ z6|gVmP{z5GZr8|}* z3vvx}0C-;M0) zZ$Qh}PQUmv@jsLUIq|ytFt#Q2cG-~704HrQ0SS*Ei15I+f6i5)^+07_04U?U*bQ2v z$Y@3H z?TDjUjSe6=7qoBg@CM}Li@+jC?%ke;)Sm&(VX#NU1lbb>0=f76tB(CtAC|NsAg;mQk2y6%Cj{pDv2fX0g3|ejeMxfXA2I$h{9sHoP z(f@B{`TrkuSrGI8tsn~!mj%K1yeusQ2S9HxsJ6n~lmZQy7qc@!E&!`(1(A?l-5lPK z{AcO{THf-lgb%!;F@U4H40PP#r)E4}jp6|r2=yvxZzt5NPKRLP875$_3SxLweiJ^g zvf}jWt^%UGx*;9p0+1(AcRFVInZP=93|go$TFfc<4T z8$Al$H{$abJ5GN+$|uTSH_|{ZK=+rcC)i)zyx=H2St1PHZ`RG&UC8o3fT#Oh>$lQR z$5}y=pmOa6^M?QbUxJo7K*E5Lza6xt5OfI^QZlaN0@(x&1JK$|Xc(j&fQe_+fWyFa z79oXsODP!6YpoP-`I1|Hx*0ha+d zGe2ne`-|You#!X-Vj(ocU@u8PhnHY4NkA78zF>nJb|V+;dQ`(eB?% zG5p{9;~(h4G1mhD|F^pQ0~a8?|F?qdKq^44fH%z@c##5eYH#lbu*FwEqY1}dK}%^E zj=3HH?SBH*0WYFbK#l;bX$6sx0_34t%7@oSn1|nWf5e}B zz}ZP;A}skl%f=Gp(0k%RM`3^sD~Z6F8o^c3(Fri)reiY>lz?C*G-5q6xR%9fE@!obpd*{9@_l|v|cv6o2`qZw}P?LuH|GYTfFgsxY)xL?D72j z4#veE?mDRQAlT+WsbiNs|GtaOkK_+NVr#k0-vU}Q&~;elfK9`WzyBE+_*>^Pfev?L z?BwI$ce?qZJ@>`NU!ctu(fm#q;=2z)O!{E+pfr_#-^DKe=12SoAMv!D^hOt?aI;3)gi<2pD8-_a9HE-|LhD5y93-6@xVsXq9Ur{UxSu)3F^)8s+&@(kso2zjA~ zlOMqHuOmQ`|Cx~`B^pltfJkbCCF{$R5IW@=PW}N)b|3!F*3EbDg@lSdPeTWb;D5I6 z!yvv88lMM+5Aw(hkVg=r2!B9B20}r@2ePN{e5Wr@>+K4w?&F=V0(ENLr5qDlztu_i zy7F}T3Ix2^06JC4mj|>n=AfVUaqGi154&9jw9i|gt~1bvoXg!^%F+6*P65<4c>(fO zH&}V=fl|;Z_B?)|?KG|5>K|yIkB{p<7#({UG~U%6%42*WxI0#$Gn6N+`S*YRmP}>_ zhVa(g{C&}&Dm;B5O3|*%i9v*1;*}&iWlL=H#oObGt6#x}p2i-M_&^9@B50u*!Yg_xmh+%mE(tOZ?oMVDrD*Pa2P)s- zN$vw|M^=$>z_df z(>XFSFa#SP2UjO_5KQ6laczo>PURREQ7wq6W)x9c0`!vQb$*D)}3$9{0{4i#uV!ejlfXh*m28|zq}VwPhpk_^`WiW9qi z1$Keb3IBGM%H|)iMEBYWInli~u?3xTSPn^auhne-|A!~K*Ak!|q_9Nyn#=kEEWNoi z-?08yw7lE*Pxs;YIMCLZiQ%wL4>)8X1Sq}xigbqxgf;*CU&_~gs<#k+{K+}yQ^p63 zzjgWwSYPaP6#?xMY;I>@Ua4X=Yo$-N}h9HCBC8r#+GI)V!eBdSM zFcXAn-$A|QeW#tk)wwOGA^s9{qg@xYk^*gIfjS6UNr4=6{NMlo2qU)qLvj$jh&Dd( zasi66USws+?yf{pmWHeh+1)`X%IwkHt-$b74Ws~C6Dfe$koF9;CIY#eA0!G7p+A3- z+zqRRK*~UaK=+$9AL8*V zec5gPBB=l|e0`i9)QOLaKYXT}v76(+CkJRFc_j-&3Fm*q|DpnKXN35l5#s-YJYEq0Bk6?r zAE~boz9ts51PS8)3?%nsKRvNC_Ct3y?3DY~|0Sx>@~ZoLcRdR{bl&A5eAD{B^ilWe znfyZY)cDu>69w@Qu4&|^u zRKnBk0II3K#(|E;>GtC2c4C1XJHrAxc1EV#i>2EMbYu(Y%m}cWPB#TG4e~#@J_mJk zgTuRTf@Xia89HOXbXRb6)`D)zs0E(1D91LN>kolJG(=V?71KkGK?X1vxphO6C zpSZIE=-Nv+P_vEUwII~HP|tT3%LI28D?l&hapeG=SI)w4+z~X~%uu4z`oBc4`+oNi zSbAdrZve@W-ldd4w29Vs@?aI@9@;|7h=W;Lrl=MI+7X^2^@<81O zy7sO_5M1|_aDgsA1KoT0n&p`5e@2jM8_-^4XNgWX7N|ReJBuYCu50~YBHb+uGOpW| zBkO;+!GE*=ms<~%GXHnu@GpJc<@z6b*irTcT%|IX4k z-E5t%A3)v&+0=TVl(XCQ!+!^kZt%@|;1mkF)J>?_f}w=B+n*!rfAEXYfB*l#e$mYb z%{fRVm=vr8L&@EsI72DYFl9lpf96bZSa|o(-Jq6n+HrP9hTd`x@CNu^HwnCkU85tNEUYlot_6mVc2LK5Lyojs<4H)wv zRCKNdox0Gu6jb$s_MS5Ix8C{t|9=K(e`pp%Z?DXs|NjGDC_%J!PX);tALyJ467FnO z_ybxosPX6je`Zj)_JRyCzSP<4^XLEn&Zz-l*$9{{_;?57lbx+LAlY6Au&f7E_P=Nh z=!WN3jz9nZLk{TbY~=x+*bO>yiWAhvKE&7=D$orM22j7D8FYqC7DG4hns{D;z;4kM z@w@^-aDPJG-8~g#Mo>4{*nkZ1wop+}@UPAvaG8AwaXwbJCr3Bq{{#t0>H+sBv;JrB6~N~UpeYB`4S}o@S@91stGvD=r3cntw3z_df$Iu+R7lT6hXNtzq#Q z&_wY8{+6$xR0clAJEP$*_$=>?9*`4JrO`CKx=ix2+78U^)W92?l@cK_d?|#sTU-dVpiG z^+0_s+~eTT0|(M^R!|&)%QIF`+(1~MIDxQ0Ap>E70t>4vaCVGdz|!WzN?g)@i+ zIdJ1RD<~m=_?V%JCB=jL#~h&LDE~`&Uhpw6FhB=#K!FKazt#8#v}qR_jNm37=rFHR zj^4STPE2?}XDet;jq(59)*pZW|L+8sfB~IbL5reZSWISM=mv`igmpp=WH}67&9mzO z=ytm1BNDCOD%JmQ1)bdTAEL=T3?c&>#^OBI3bKU()L!__(D)Cu8=1ccbbi7M!Ic01 zyHE6nF$Q%`1?h&Iw)>;|e(V2|BFI7?h?9#0lMIsuNxc^pw@zV z-v9rt|4VpZ#3ld#AKrbUTi}0?K)3H7$hgH#H%K7}Zp1*-ZxXz`YkY&cJ`PdvA(qGS zw>vX3Fa$srMnQwO_};JopphGo|BXNYF)}dlw_{%qhx=%wjf-)whr9an*Zv=O%}$c5wm^SB=_O$KOScW*?t_dUaGfR;I*;w$qB6|OKf@zIaTyS81*f4U?u*w2C<`3W*PBB6UoTky|NsBZ zm4mTFuocwP{1%U7*D-kK3R0ed=F>ra`ff*o-avs~KaS2Yo=(PYrcMu*PA+7%pfClS zU&<5S{j>F3iNgO~0J z!L_~KGM!sNN&-P{*G~EWzt>wKu-8xFg?!5Y|DX5;oHd#cgYLC;)99{dvHo4c+4{eP zwfXpu*G$HsV#}-7oul?L68rA+FSI~sb@~Z39~0>G;OGqi-8j_E))~OkDb`)j z)B3+e*!p(~f9wAe?ryN9Aaiy>n6EdWTwDi=N^mB-;RwlO(D2UspOJ?zybvW|cPz&X z?l?T*6&H;bUOSRu;g!XN2rhNd+Dlk)wSFtnYq?#*^@(4AwIiEL;59RU_<@$&;M}(} zft6EWM+7S;=!TPCKZSr7I?4b4qxdQgx-W(q$x|SYK`|sf=;8Js!gntWV)1ybISS2d zcaz{=V@7z*=lB2rpc~0Q@e8t%SAt7$^&T>vod?9TC?2;7|AI<^vpE0#<_1 z!~6pntpY)Z`5$0vK8SIczhAd~uO~yV8;AAr67TLZ9#j*%Pd7jKL%eCF+oQXW#l?e0 zl%nH|4}cj^3YxH>6l6UBPwVZH^6>6jj@JLBGLXRO_2%ew=IIpdc4CQ-?&Rq7VgVIZ z-GL%uy@dkS*Gf!VFO{%19|HOKlJSAoOC>7c^^DfXYmK{ucv>%&h*)1M5kOMp(0Zx# zVK*Dd++tAq$p$Jv`QqZi=l`}|DtXfF#MA4|5f|Uh(CN$rIwF;^+leC@q{@o}WH;Ew zp!TOLM{fXpzJ&vNUVm^{Zv^8D-KhWngQ0~XXeh6g1vIT0{J)eV?1f_rsOIPCJ_Zs3 z8wM%gv;Jr7K;$nR_d9^@Z@8e&zyK=I!IznVnujmsV*mfo0G-{G#n|f#I#`=A0HpA_ z76U_f>4%mBpc;#R%Hif`e^8fZw?!iAo0i)p{N3O&ue{?78LXTFuhY7H-+&sY65T&u z#6&G>_5D)C|D`;~SnL?WUZgRA zyvou2zu{apo1w zoC3xNUhB7hD-i_UchSYxa-f9WMxmV9t@LwnSoirCt3((WS`Uqsd7h9*n#g=>Pfs*I1Z@iEW2laZo z1zP`?YGg704`KmjixQ!%{~1?UI0dqp!(Oa)1|=4Ocu>aZ24A??YXVwN#t`;Dh^5o@ z59r`=(C9)K=qhxdbOwg*ViwT!?Pruy54r)V^?zMXw=0K3r|SoBcz`bQIT!FEm4kty zJM>HUiEh_FojjmcV`8r(W2Y+zY`>~6hw%XmSDx-N9{#BZm=AXQ{%AhP#C)RD_Xnta zw??(A+x3G}XXqE}>op5rScm=p|G)GHEPtHn1f4ct>eB7{$M{?8|2l4_WJb5^5A9>j2Lr-h9~OpB4s(o zrr>srjp0Qb#7>ZFWc!oKTQ={y@AV06K;^?KoR319(US)Km=Ze)EZ6 zz?Y->4aX;b0nrt#oC0CtpZIltrt#+;|IGjFz$gBggK7LBtP66u1k(8RFBEx$8YVkf zIYGRGMYd`D`n)GtIR%Q0Uoe1NaUx5!TcF#C1$0;^=mwR)3=9n688xh&0$HMAFZQkm zt?d=)J_ea^dT}-cl$x>}P_&$4U|_iG3Ubn28I>2SCNMC3;ui?zXg&gRqAbWEpZEoM zK~B9J`vcUl`0}c$l)}8{S!qhAO{`*wUIPVrSXTHPUF` z|Njp@W9mK;1{yqI>HYzp4=Pc7!Hr~Zr|XB-1Emr#z6T+O8IaO{SQbP0i|AwqhA_}Z zmk%!jl0hk*qxp!01IRy}u3t(xdJEV)OaHuP-3OYX#q17r`~K*5{h)oY)AvoMD@U&< z186Hd=#)utAA!GRDFXw8^KvM0|C+K50Ern%y1yqV;y2b$96xP}D;1Cup{@V<_Q&u{7}i|Nka-&}`fcy8YqB zM35Nhc3;qFPV+Gq@6t;zYC&S9AE4@9u1lTfo@u%F}Y7gae!~nvXGc z$G$km2D-Ti)D{6PpL`D*>#hCKS^MHO7i>NbtVOxo^-Jr4IvK2Ki22j!Ro%5Oz*A=b zP1w6#|7ag$c6|~M_F}RvG{ObCdDweV&lh0+c#O@;&BB$Zgyk3;ryHbPG>7So1nJ~& zJ|cipAUgkN{%Gm?2BZU8BEtOwDisR?KqWB;s8r+!mx?dqKwF;8p`p|5`=s`5f_9CK$Z$BR^d zq;~9$*4w45;HA#Tn3Z~q85`^w_*+10SwZJLu-nL&@!2SqaM{F^uywGxxxY?1#unq& z#qQ3(?L@ERkLDjCK`~tgc*Np{=vrIz6o>~tV(OnT2_G!5f)B?7kfX0JiyZZ0X*>XiC@Q2 zqxC?kNQMkZasi5Dh6+fm2Sw}?zks6#q;g?Vc~S5KWEcn3ux>{MSn+lIFGvDr3-s7+ zBT$1CVlPx=!B0>(7VMG?9gt=EuORwBBTyU+6T;WB3hZ3NDsXlUtH8fCtO8PNSp|&O zvI@Aag`DjT@^bn;_0ssGJOag70 z;_G$gIOh5X)FXQF;;JmDN5p}&Mvr zA69;U?DqW-77Xeosr353=>GBIvNQw33q2orwh^%Y$3NxpYbK-H-QfNjyqEJT2Gq-W z0qr@w*d6o#Kg#S8Xqf3KsN)O{5m0&pO)9m1i12BA13Kat*ZADQPVjN) z-Qa#tgI#oqFsP;nosN5)*@lHv;AJEu1H*9#&{0_oZYBI6{~`5P8th_AIeOg~Uz##9 zFk~6L*blm%{RrsNNbn9Y(6Pm!OCx!+*t$==nDi3VAp(uTLA?g5YJY)hgsGsxyk38f z=0l)`o=lyLo#8yt;ma3iI6#emmhSTbFD9}xFa*5V4Qi=>09_sQjlX3#s7Yd{!`}*8 zEDLV`zBuiL(szTLThj?Xu^r?L=+xE=7O-oOTmo9@-VF|n-f)iQ0|MO~o$frHT-^+y zt98KQodE)FCA^p&wx4XEnUvOVB>|xF4!J+q`mMyK!A^(2CGG$J{|$Dr{4M7}Ylm)w zI)ZChKpjD(;crm9g8Owdb;13*LmZ%f^PS_&9W0yzudlS;F1c`=IR(T%fjorj?T*$R zUFr`R*$1Tt@O*Rg8v)P|F@N~U@a~_Tr9XCpc8GoA7xevLe5up-PlKIq8o$QH4qxt4 zmX1(vw+1_dQbxBfwom*5svB521#Ap!Ol&Oc4IuRe|Goom%`Xf-@kgFXtJVgvDu`Su-Lek8iUNR(JtY#(Jf_fKKZ}X_m5i_n~gz@l#OM*F#o;-y&{v` zdV^l{iUfd!YhQNz{^4JLDve*`NE(0M$d3V(|z69dC>h8v(9#sy-!gO0*sKu=x`cD1GAy>7@m;X$bc+y~AwcoAR( znu%iRgip1!9w>q2H8s$ML^obD8Q<=97wGloXg)5`$=F%V15NLpwH)2-pn)s?2`I@K z)EPb<_5yT%G~`gHJkaI^_Lc)BJT?mD9PXu`UxJR*24!5(q1(O13Sqt8GA~y6fY#2u zFbw|xzro%L?ngsV(ZTQs}$ zpyyAhe?e!*L;PC@T3-+HFQ<({Ijei==hykI|4XuA9^LN^_NYe?*rTPH?j^ikAl2aU z8~4)BVDrLXfX>?mk75|1m6xsGO5{PFYf%H22etey@}T+yJh;YooWX<@OOXJMY;dY6 zd3>Bf0@QuH4awSI65Rg-U5ynM4qEyBqrpO{w}P?zdWkqh58H8u3Q*$@bnQ3Ts4gZO zr4r$m110=!B|J_xF{O-7AfeK?!7nDbf@bLuV|h0^WB;_?F6E2{cdid{Fm$nZf3{KL zZ|Mc?I)wBmS`P5HR5LO#*u<2ucd)%o1|=AOM(_^01M`}H2=ljtwifblYw*|(Zr|x_ z2et1wURr^UEn(w%X#}RZUTT49-k0F%TQ<&@QXnhb83TGpcIzLstL4O)j@%)S#;pTFj7{0&kI-hIOFbfVYsKl8`t zAI#;J|5aLJwzCR!9rgq5h&%Y2t%D6ayEB%fgRQG^1}mq4AJ^dyHs+77nLGI0y4)Gv zZIt+1YeDHJ_Rldkh6a13Qbzag(jURSehM#AJ^%lIaljeT+KBExe%uXoSS$l9GQ0mT z*~%)gW-F_}maVJ;d$zI)9NEe$aAqs3z>{sP0t{?yY>aFWz{JMJ#>~dTdUYGCz_D$t z0=u@c3ar}(Y2$&$8$pAOJl!{2|Cg{q1{}e=?)Y0iftpz?8E2R|1;So97lX1rPwRnF z!T4S`mgCN#W(h+acyv9BHRB3cksMr+TE-n_PJv!;h2zek)fx;hCVTw<9}ijy=*AlN ziC@rJ1EP~9;|W;j6Yz-}Amg<&-k|D?^Z?Haf+xRv-B{w0w0E)DD3uC?gBEdahVDN) z#KB;rTjC6@%B*doq4J>dT+rYrNWK~>_Wvhj&l0Gr27CSsD64@6=s@!UAX969z*T^= zD`-Bd+ZEKq5`omGT^ubZOE?;SDwH!jlzxf@&EGV>0iFH3@W2Fa0pp{cu75z2HNCBW ze*gau4ruWCGoYc)#2^NS?(d*A5q^yDW~cF`?(-JnCH!5Cy`GFVT&0Xo4VDb09~=LH z4lyoc-w8V3{k6~z(1iom$D~g-KTK&n2)YMj2j~!k=3gmg>|nXqV$HuK%h-2-Zg+Ui zWqk;=OC_cGKuTI?FV~;{|962@cb`s!Ea)>nkk&aBw94-|*p&?oCmN2of>u5TMMQEkg{>0A-(m7b<7}|L^S;2Px%o>}~~F(tO}f^TR)B zpquEx>jsZI^2jl8F*G0ekk;wQWqjbcqW~kr|NqAsL2E^hJBln_n>Tx2yt9(!5A4Rmn>EU&`@cw5N#! ze5q{4Mg|6kfd8U1nm7c&i$P)!2{3>zP8DDXLsI&`RHXYu*niOu(EV2zK;xXCRo2+> z*Z-nA4WOgHN_esu1F{UlAZBMVWHEs4g7V|wmVt)*IR1-HKz2YD!wdOTh(ca+553{|7bl~!WZ~oG^3G20J?_6_&{eJi}eps41jiT zoH?_Bv5m3Y5o8!U^p1Pv*Z{`|=!V_ykD!KFsa3ZhXl=bQs3GCX(dqi5*Y!shLqHZ& zr|+NtqB)?;ZTVVGmI~W4F)}ce@U$L?G8tfW0K9$%yyyzzbubBOpZ-9!PqA$u zDdp&9>-J#jb>(0_7w|&!@UQ;?u$31z!N31QMmnKQEU>QyK^(#qjv7aZLi;`3ktyX4?GZ#GsduS3V?$i?B3&y87O>+ z`!$N;{e5ibQ-RheWr(nG3S@y!837eD$Jt8QI0cTofsRyX_%F)P0J<}Y1$AKqXgvMQ zjz6rN0&v%yIkUro4VABf$_KZ%5I4a8>2?(e4h!#ez0vI|lJ&LI^}&BpgGSIvU;N<* zK;@$AlTO!fy{=CJ!awuZyFU9bY66n=3XO6Cri1;f0bUF{j37JSs54@UQ6u; zjZ?oC-VHiDBZ7@nAgmYc)Z?y@iI{*F(ShK|33w3%V|YRsy`UqzK&}jU5uX10e{+S1z%kc9 z97Rmspu+V*1BU?OHg!%lP~(XO97u0KN#nRHcwzrB*BhV|585~Jf=TxG|6W&6C_+xu zDgDpL0GgmcY-50}HL(BfPJ&-j3d-{v<7h{#1b46oC73h20sT9MA$4c3kv z{7r_SL(D2!82DS%L48J=yerH89S#lc0u=d&^TSMANc%W zHn)}or9ZVlHvWsRVPN2I0-a(K-s^kdg;C3||Hhyr&X`)im4xgD$@Y3ObRX;WJ)nKu z7R2RuKO7JaI#KFH8XE&cuj`Ftu78*VdVOcSNMmMT0EPB3*FQ|4d+Beyn63g2@y6pI zjn@B)ws*(Q=`NkoeY!h#i}tx4t5>bk`u_6ZFQ)E82VclDAL?}7z~2J8EUo)ocj=B! z-zCkJA_7G$-IlMJx_|bDuIQ{?VSTOG(E3)nZuc+k-v|FQS(ol970zM=c^Pz9QFrN% z?$|BezDq#MYPwl=cd~W6Zg{N-QY8jab%_x)LZ?Yg1$TM1LAUGp)P=7SO*onT8l zT{o1ry=Lw%-O*fo1(cc?i{$^89(Zv|8SI(YLcOjVz=6yLn!keB=sHFFa~4Bz7Q?}R zOkvbNqcrBL#w^I%YFico@m{kCVdk?Y- zOgjkaXMigQ`1r3v3A{eQu^*~4^+Wg1?pO}vZ=I!YT5p%AflmMUZ(lCi%L1CqV+eS` z3ThmIh8;i(zLm1RVEnu}WRY|KK-~|J?HLY9TmmnOzca#bZij>@X#S}CBgo!v zHx}z3#fIH{*5}K$wSR(=s2fKqXBK1kxffyJHIksFiB>mTH_MJr#%4Db(A?4?76xm$ zDsT}DZosf~vm+~kSOq2_^+^&U{;=+6{n+it(p}48{j=Dso6Y)oxr_D>NS1pK^8c@c z@8y|)S^L3Ux8wD{|J`i8JoUXSC%XMuI(>ASnb7 zDxEBm1}O|b?g&ZIkefG;F*3Z6nEC5}vm1*9O40?jx>y)M{kg3F850oxX?_!cZ3GaM z9zTNj<{AG7%@CG8=yqV~_A#&k?LGswrdYb!pib^~U}>%~;9)2g?DjFR0VOo+b0w@V zCV}cfP&2K$#*l{rbY`t9XekuP?JWmNx%PwFurEOy3A%j@EkFfXx1$1Ri=TFPpg}ii zhF-~|ld0QNp2~4bVZPXWf~C32f}xZd#CRay>BQ6OB*5PaI^1MO+i_Nb!`-ECx@$pG z7$Dby+m_7dK%<7BYaY8DdAN@^S0ZV5Y}3|l0WbDgFfe>O$W)@4A&`WmddG_!+u*8q9CzIT zQQc?3z>uMVtZ>PT^$3Maj=L^_C``3rfY+(9KN%TX4wSNYpL=oH<@f(?Hnd3NKxt7z z$7Wf;eViAv77PsF`ZX}@f2lxsDaZd((D*B;r4R@$HM`G2cRPY+mp4uO^&hnP_i5}Q z9z-UE5+mR) z5ep(T!SNB+{qZ;($n`JcVaD*jn1W&iV%0o&GuHnE190JW=FAx|zuUp({{x6fX!o1O zH>l?ahIM}gB@~YT7g`RKgmn9HgoE<8%L_vTv=A@xfCnge^st=+HB=usfJ1cyBdFo_ z$N21vdSOUNcKiM@0`>4;(Tsxi27P7^rz7 zNcyw>XKj=`=>E~o4=t!cMfVGB z`~Ux8*+3t}?!5yVlV$I818sl-wamfFL_kvD+!BEZ3*T>t6-pelG+wkxfI0~*kjYr+ z6eVa!*8eh&?h`LS`*yoQ3z3nl|H8bE~!8)OU$060GXC%{iofRrBri1@_be!#L}sk;^wA)w;- zINJ<1PJ!0{CG6ejUu4^Y!w?$i$Jq+lIR##{>HPnn@dMO12JdZS>2%}iJ`XLcyV<)P zME+msbW`X)))}S(-Kc)tO#);zO8EzEB7nRB#}M~7AiE#h-9l`X=mw2vKwQ#X#{sI0 zKt`9azPJw>k*nhYE#P{h{r~^}G9Fl=2j0vMD*D0cVz~`+VOePdEi8FotkWh`P=X3C zKhT!t0E6xe-EIONC43&G?Al=>l}vGmyAQ=3?sk*Vb`xPf1R34}-OmkH#pO}T_re}D zguxCACqIrjP*R5%mEbT4>;Cux6jI$#S$M$%mOXO@bpDFFfJcdWUKga)ak^kj9 zpz>2?CZoH;ad+^I--6*P@rS#^CAv>_yNhU_D3R>;=g>YBHZzN{+b}4g+s)?xg-&;c z&Ty5u1(-^Opn?L-?jqL5`29bCmXsbo zb0)a^W>|Q)HwVZkGN3i6-M_leDW7lt`M*S^xmtj!R1PXB^8W&}vq*!KGj_((e0*S zeZE}0J4{9Uczp9MhE6{b=7Vv~ml&c!1z)$Hit%mj(R8x1U7!;qFk5?w{Iq3es*W%)dHo1-ff_gpao#D3>Z?we%Gz7uNPu=sv`J zs{49;r=JLD8it1fnueh%`nBkb{D1%dzvg(60V>d91wba&@^t%g1cwKKg2U$jh4@Z4 zh0ZV)h<0!chIM}gd975a+fBsylD3rE2xWnC`bOp{k-6xb!fkKd{xlVwo zl#SU96mF0N1?i7~j3`lP1|@aR7cW5v>Z9NI4$2YTVIslZaT4L(wLIFltnb%2bo=py zGoK3lU&`^~ixH@_=IK7pSSJ!64PL|4?FVXtfvOP3{{b4^Ct6R|vCm|5QxFVO={^Wi z;l>lpd?)~} zgv5(jtZ$YJLQ@dP42TKP0Dz?*p%?mp!088cm_&Ci4=DZkae&g!{{V}bNJ$5I%o_D$?yP(p@g0{lWSZzwamJW7^j`-9=h2m6&$>bAV$&r}@YK5_#qi z(5wzBCc2M7Gd!rE0Jr6uPyBEF#_#t5w2A}N9fk!LsQdy)3U{}gg0`CkvzrJsq5cmL z02#~)PNK|UagZi>`eZ6G0;kWM7oMPFNWoQm0w`PXfZKhc$K62pN-#hJ0~$0tKy`|? zn+Pb$S|6_s>OS{^`}hC<&{X9NN>$MGse+O|<6#LDISHdGfvezQ_7e&JU&;~q;)6a? z9snosGiRDD8A>?+7qa{pwE-VQ1*wlVBiBdam=zM}e5vE?7uY!k8tQpK6%webDPeuV z2O5(q=V(3w-66|>v_IBK6{)T{4{f%*cw-8$j1*N7tGdy4xFBjy(D_V|GME`sbQpJ^ z2JPAZ)mOWdbjvA-lL+50nJF=mne1RLTRk-RMB4pG4f@7v*44-V&7;xnLG!iPVc^ zu+7N!LREw9gtCvh@i1&)gjTZ9bOk9pL9PJLPjCc>WiU7}Fm(F~z z?M~l6t=~#~K(~c5goE}Ub%$~^|6}R?$M63myqhVo`xLlnG(OOJvW~CY^+(|UQs`a} z73Le-AFPkp@O1nB0c&slR(c3Dj}Z7`zYr*$u^?9WgB$|Iko5H(k-qS^ziUDJua1LP z>w!x67k`!h|Ibo@v~s{ZgHW5aehO$!+7%iM4A9;$9VG$SPc@XfUY3!~Q=&0JO)VLKQTP7M8`7#qdAKqMN<@JV*jG zv&InI{Q)F&EG|C!aD4NL|F9MXsJ+Gp>sxVsa}!}IVF6878XbV732=Jg2?I4LzkqtB zBL6RRpXzk|0ZIrbYi#RTS`QSNgN}j^4hLDA#qdAC2E>JAHnVQfO-kLjKohQi{+Isv zA7;~iy!&!|G^k^J7~J;)v!I@ZjL(8bJ3u`(P$>^;uOKAPK-*LQiv?cnOJ`u137Vhy z)%~IMe|=mHOY67dh!+XgpbW`WD$so$oL%C(k9B%W#6=%|;RcrBEzx*k17+#JNGTq1G;Mo{QW4mcBN{=rzn{l8q`#e+C- z6#g$4IPNY3D%}2;@??QL@!~`x14H+X<|6{uu{^aQFAi8i-3NAE_u)=|3CIr77t6ph zAotAyvq0{fWCd~`$Z>}eZiDFnyAPzl`!IMd3pkuW^`9$GSh(^3?vL8XON2a1I6O-E zdMlV-3xf`YXL!wH{J)#+e}I6cD@Tb8sGJ8CH*rZI=kv54DB%Pp4sclyipBo{0%%+K zv6QF3K;`La(Dn+(?lPO1K>;Y`stBxH<&M`r1};z!u`tBPfs!Dilm$Sc3z*|b zh|jG585(8q@rUL&2GIJo(-r-&gl=b%ojce$1y-<>2(Dn~@A0EG6=wYuuz7Dj2OwMY0%=yPg22XK;Pr>3Zfh-*H#a zf**$Cu4h0+EJPo4M5FltN7ny<7wpTyOGc7cWUmCN6|g>5teW*dyw~+YmO#LZu$BM+cb6Uk@e~5WUi<~`Y?kSC76467 z9eJTHi_|o5762vNfESWrMJ&zL0u2094|F*5v>Yh)dJ$j_i61U-{B(LtytaK|0~X^g zQF>tnW-*pXywEU*#tb6ScuTw%gyb=AiP!AVCP8!U35Me+r$m-;{x3ZPX%3U;g?)I3=C(&!@5gU1iF1xM7nEKc)AaEUt~UJ{jZF} z`Uihg1~UT#|1Q-f$-DxL#q6J#ycB0VYZT z0*w4kw^-o182Fo)GcquIKMq=t%-;&C!oDAau&0BLz}fYjshGE$t@$NOZy8G`dv84p z|E}lE#e$#t>-d^qa`cvQr14+l@2%(fehjp%pd^`p*E44RX3(yaH2!?QFTG`7()jb^ z1e#wOr19swDWvh|=Na^t88rU{@h_+GTk+rIN#n1VPvg&j0OB12@!SQ{`18+#xNkt* ze1+b6gWB!AWjrs}gXit@{eJY8{pj^%AZRuRirF9@lGz|G+-#25VIUX(=`H)y{hy$@ zEGXuJcu3}gxNvh>ntuw^2!H0!=WBi`&|4;u#$V6hTQBhX1^=#xm|^=6TiAB9^sacw zD)9dSB$`S^558n-e#G4TlcPxM^V0t+Q$ey5x{vPyMO^bsmLi_!2h7YT{;Ra^c>r1x z+q>f-tH1=%Di9ET<^ij~j|Z#*G7nh=lrMI%b+C82F?P5!cDXSfe96?|&eVL2x%oKQ z^fPeNdp#N8YQd@)n~yOyA7=u&VHsT21c;jEV~ijd9%lr}cEDwOJsIXdWEJRn$STnC zkX4}OA*(>iLso&DhpYlA4_O6b92&G;((Tgsqtm7TN4HDgpH7$lKfNryppu691M?4PaCH9%dHTRZR)I4Q zSp^<|%~s)wi$6R86Ri?T;W)P9aHmra4d8nshj{atIG`(p10-Y}Xpt$4dbm`~mcIo5jbm`~lcIjj3bm?b7 zjT?}+yZ?tgW)+Be%qo!cm{p(wY&JAL+?YGunV}&L@o$GaGsG8AQIOx@VyJNkSuY;m zeXRKbf9nDM)=QwVuZztO>kqzSFG+=N2c3|{pU(!$>7X(u3{)V+8Km*ov#0Ub`-3uP zxI!9#eLSdiN^<~}Rsm`J`DF=d{P}eSY5eu+4r%=L`2lJC_2mg^{Ppz(z1u*AZSQ^% z=~cS8^<;^E_r-&+SXwWYh(p%jLhP$&?=2JPtrzerec$|$zeKD1;K7$nCA{5Yo#MS^ zEWPzCo~56=Pc%PdF5w3yP&aqa((e%c5pnT{p>BW8eCEuVU7*uTwJ&I&3hX`v(ZSgz z)*%koaqtC-nI5H|BVYdd2Rht0<3>EUz>5u_enjdMhVEFN?!(=+0{rWbcb9U2cK&iS zr~YB^@2nN5;L-lvS<2CU?tiGr>vzTn96G_1z@USvUx0>2Uu;ZZU^pbe&|ND4GNqKG z+ZD7GnEQXJNO*AA3s6hoaF$5M50G_^VC()c{Pz{8u44tkIx?LYMS|k_eJ}BWn?s^B5mAhT<9DcDVo`In|6*S8Ww%#0Kb66Hjmcont z1O|r4$ZpX3Pn9MPfyD)%_yiW`eBu*m{Z`7FB@q#KxLJ+C_(0s@ES?OB1a5&BTjCiQ znp2-Jy!Z!d+^7Bl9c1!CnSp^J5_F5~ljE*`z?Oh(<6|#Q$1^Y-?k;`u;-)nN18B{3 zU~pKssYVlrK=^-CkX`?;{Wk?!*XjD_|F!NL-L8MEZ}2yPcCdH<*8b7!&(i#prKl|6 z#Wau~KJ>b?L|T6+cHaS7yKnuWn5p|%ckCbLW7fxtcmsl87=k?m+K1WeCSZN6$SxrG zg)CI8#PHyMrhs0V9sfn)9tE$K1@U^lSvr{mp)w%nbh~oAW->kini_cuUh54SYW(@{ z|NrkdBBc*}zu^&k_`m6fWL|;)q9D(-9w=e@e*v`U^o1+fzL&8H3=A)~GBGd&9%q!{ z;1qaak;}jk2?~K;N6vt5SB~ZboB=PU=P)pUO^kE^4R%4stX`aiohim1_F~8X|NkSq zLHjsa7{Fabf!Dksw}_cAFhsToPE8iN$pqywJ~MU;sJqaB%m{@a`YYzy6mBYTxT( z>tHctFi$wS@M^E*7~CX6KdzC2amB%wDA*S}&C{bqKfqkB=^$2-3sb?aGrC zaLk4AKSRXpjUX!+KvpQdo(&2U&`{gQ7nuwU49D35I5-7B79IkJM_8{bNB75o7ra>H zx?MRygWPE>49D3FI5-84xp6T3H+ZoVRGh&BwA+>AI3q~5o1xQ@rTgG9M-B$io&dPD z%_#c8DIIEkb0P~v_d$qmkha4R=F4de44|k2?E&EE{%HNZMD|59X!~P52SW+Z|8kb@ zb1zIm^Dk`O?kt^dEU=MIkd2@TZ;)eN1Tio$fRB}94|}oo@BjbENuZX4A-MZyi7u#5 z`NB1qfuXm8G5m#;7z0D6GfN~aQG^G)IF|$JTk#xo=3oSMeOVa7x<5A5ae&4Z%UHmZ zJCPvYfx;#3FnH~ADeDdk4o(43GHtHqU?|c3U&@ii@Zag)&_MN z|BKc%g042r&}LwW>|~3JJ)9+w5dbPA`lA^bKnuE_be2BoEd66$Do`ub4KA{}U3nN? zIovu+pS*qvE)^dfhn5(i6|^sAM>8-S5@F~rebVjvp!Gm0|Nl~nFz7Dlx4-`XKm2m} zpa1_uyWc>LW6fe*tdq9-ymHZ9zf|k&&ewS&T2HfU;c%Ckw-Y7h;7B z43Xf>-1tU?nSmio{Dt%jM$o=j)-0yTvzm(q5_ttWd3ivjCPXez% zT92qkB8cLZ0aLO+z=Et_z?A9-Fs1t@fmdKoKdV9_uRyme!(tII&9Yb`kyoJCm1D6A zh~Ih#bYL-SLISSQ-%Q7$=XH|f*vRERr4=@~W zP)Xngk6J_c-Qd1Xrw{9oES89a4;Z?6k4)ee0P!;-KxNMv(7X_&9LwSWZF*yX27?SF z7(|{!f}z`&gWkdLAq5E`WHN!NAab;{R*)|D__mt`Cm8 zKKcLufBpYbf#a@koIuA9l=5_jz6j_Heege&qxpyc)YHAL5}^Gir6Q1}7oh4uR1@TU z37FNv;l{UnYoBDX8z1P5eGvJ1HN@)q>Ts*GpjP{WL#^aVSf}fYPS*#Z!+C@Mm+~N7 z699F~3m5POwgTNB{`)?uVDI*Q&>{I6q%I)%#Vt^d1C>|t;F0^#?l--zB48&9Kr?bF z*nJ{k_r<tvM7OH|qbmoaD-XEzc#Ng=hz)08 zI3$5mddPs*bb$h8{kQ-Bp+mXg@vm+l6^?Ef6_)Veux8r@pq@XZtIyvKI=F~`n_%~? zgO514FY~v&1b3G6Zhhh}xXr*Xb~}y#{ekX}&FBB~ZxzvOfp z|Lap}{MTz-V>3bWit%UOz^#L9ORYEtPLU z4b%V3pU(xg_!PwQk`rnCuP;I!0otwKd{E%^QT{!*nJ+V+=HDjSdb>oxN{YWV>Hq)# z&4(D94>G=9?hzLqf7ti{h-|QADEZ#~6Ks|8O{g_&pZW6{Un_z4JMeEaY(B`C#&4x? zj6aRP_y(hQ3FzFycdwr{A7D)5uR8?M3iWQ80K^}QtS*;GG#_Am{jm9fKpMYQvcm_S z@~g$&Ag>iLQM!4=1nP(H=B)%_4~k6IH~gNOP~Lsvx22S`-vU@ z|Nn0##}8iS-+YX*`4HplwOxYUKUyx8A;hr8H7LdQy9_SXIHN@QwzQlbG8VzN3?y06QTx#d8KL|5AX=7UUD zM@sI$UJVYku0t<9EEyPj-T#9^u=_ZO1Q$skyL~x8GeNB={AxWoe!4!QHVut+z`hUUVzN%Y-n{DBp?yFD1b{!bN(0-@MQPEiQI_ z16m)tn}LDBa>EJ+28L1%%TfXUHqdrn{%tIBX`Sp1HgXL7EudbbTk~-y>r#QDXD^R{ z3owD^bN|D`g0ncmtJZZILCp#NR?yK+kfucQkE+t3ZeM}!!>_eGJAMCv_gt#?y1ohE z-*zzIMQbCtncMBk5m~|pI&P~(wcGcP19*{l>G}Vq0@{be1G-(`1ZOcKSx~C@Vv7>U zTUrcI@4mK#I-NWC1#1ep=ki)DEUfw5e>At1^1i5qYkke!TkyZ3_6I`=d$;eG=EQ=( z-NzssuEEWvHv*uWC_y320}A0%w$|Gv@~>H1ZZd`c=N`6X;+rB!_iN`~-w%NSp#I?t?SJ5*+~yzuONBs3 z=7RPwvA;N{$iUET@Y>3u^?!+u_2Dwb=30sWC1McCjUYq76<2K%1H)_4tbp#raiG19 zKJNdzK_}gnFm*CE)cyhc?gz+spmr&&1P9e?6919w7*0^paRgGwbo&Z`{LRt*z4c^? zW_Ku$_I3X4ELLfq?9InPH@=lHdzQWfEiUvd;Wj>S@#W{$!Y9){uLfBFt^A2S;mHo}w?Yhl9KC1O_%g0WJLx?apTD%u!+Ke$)I$BP_hTn#cG6|91XP z-ydn#2TM7+ojG2DHq0&r7382>4En&g6&zOu6}wqXakk)M7gU6?zt+qG6}<=ex1WsS z-+mBOd@-f*A34Bod?3yGUx4XSLvY6sPr*?eeFF3%E#$WJ&0mUskpZW7S)A;ib zr}38_Oye&-lg9u0U>g7R1FZ*2SwZf($iL@6r|XZ4FM4?#`L{C~UrMvSz~AzUfq{X4 zyLg)Qh0>z#i`|fLh6Iv3N|0H8=Fb<01RL0nQ)&FAhtl{va9Yznv?s^=)4C3;#0NCYC;DOvQ#oacgKXkhypFIF6C)H z0y>fRqGcRQy-*E{rCc%33lW&k*C(^sBP`umYPjlOHQN2pcbHuM=tWsSXb;qnfEVxk zz~vu*>r>E~3$9-RUa`hlzkLUG0uz>E>&_U6WVO(fG6B3o}DmO1JBu znc62nMXK~I&^?Wvu^(Qn)CY|Lfrk1#|NsAQ>H34e#fFiAA^e38)UXy^&>V>CmzkQb zZ$MflLqCMSD2D42{{R2~ad!pKnAJ;WMh1qk@E2il$#4I_MwaM?zxWGre~D7J>lbF% zKQp^eKy`JqcYm7MeM9@E^tH}Vj_yyd`McR?cHij!1a|EW=}%b zcb4YMU`@ecFSf%qaX>UlfHehxHE}>RNi-jO(do_s(IgQZ_M!=-=|tC{Jz^=qWJ(jqdyN!X}3E_ zY3qUdi_Hh*kGl(i2FyC$d3qaj85tND-DUp!i@e?$3<581$3Vtvn%_tShlT$yl`*~z zI;!e-XY8Nu&o8EZ2VIs4+T$x|8Ou|`(;;CQD^S8}87opM`eK(fsOAIrFIr<57+xL* z4Su-32oBEr|G!iq_tuTo1Jb1Q`ebPLn^;gU z0W|EB#RYN!$BVc{piUSMxPnXT_T}64p`L*ut@~h_@}V^AL#4WRT{!{+LC2iR1%Ps& zM~R3>36Dn!tMLJc*uz;&ubHw~B4Q8k09`v0dzgRw$;O8a4GavR`%~q(HdU^lBw<9i9JP^qTy^apChe7PdhoC#WdK*E< z34q$H=I2RN?Bhl&u3s*m@t7GJcJcyd>{Y{ zx9tuW>Io^9sCt02&-fU&6rf`ef^Y($s|@!PWzHO&*IuEKrM}*>*xQuK+_S>kDIL z28I``N}z>gps`y17y3&W7+!3yWMFu)Clb6{3OqOux^eF%=#pv3kS<@dZNO}9f&V3} zFFGn27!JQKX#T-e8u#B6B>G}{6vREz8GAsZMT{?OJU|H+bZ!!V3us6@463jfq!3g} zNMtdDy%4PcsroMpx>d20t=W&||7*#x7mHv2{~!7CFep?0U$x@y-)qa(EN|Fgthq}Q>ke;ZvqFWKNPMSIa=9R%h*#=6{T(8m<3JRf53_k1s6)UDyj6TDboA|Nn(x zD-M*f2ZM%X|6c&@4sQO(T&e{zWXoUB)PeK?xy@{x21P6g}>LL8T?A2&otM!1zf>)YC)$$rK@P7#32)eoZfQsYS^1j%g_kG;L#MbU=dffjF>>z{LwU==!Hv&@4yn;V?*4f+sjCU;h6eX?)d?8PT328PHN+eHxeM#se- zez6SH4*LMBV^)iR2d`g0deMg>J{cn3efae$@VtvcSa=pkCOy!q?5;{E{WGo3Xn<;(vfbXYCKrDZt-Kc)qc5l&~Ln{lefdld;$JOThoq z5C2P_{4ag*UsR@%LjZin#vu++st@}EGSZL3_}mMJyZ`@ZF@*gu6Zu~T9#a(fUnT%b zX{K91<);E9_yU9ffNnhZ;4t>(dBJ-Z+zJ3~Nqvx3BG~Q9bKC)Rp8$jL0f*N)ud}j1 zXa4>#kmz>h`ClLcCLtz+nP9_jYz7++D&{Iw7)rT88Ksoxg*+4J@<-54Xb|po{S%O( z%*ep-0#w^HACc*H{R5i7OqS`+R`~zG_<#efDsFxw0bW1V>-(ZP^#z0RLD0ah>xXVv zo=(>_f}zv(MX&1%$n|>vOChj z%b;73x6Qgg z$})Gyp6Fyw=>+p$b9TcF?sokH3%$U=ZdVS_xJ+1g0Z+FFIFw5Ngm?dIyJ0=PrMB=#tvz2Y*44BG!ry(OxsrvU^kZD?OE=J6 zG@yHZSzccX?SAv(JVydLceCmU=%S_>x|uJvd)KvAjE3sOAc1t=Ui*#t~D+3>GN z1E~hN&5aqnW)07JG>}Trnk|^R4tFL3>(M|udOaCBIN1ayaIy)^;A9h6z{w`Cf|E^P z11Fon4o)_K(;%NwWjz|mvhM#+IN1c=aIy*f;bapK;6jR<(e-FFS&s&(Ng!l*hzd`) zj|ynTTs{9b7Zncpf@a=s9~GYP?iv-2&#PX?g48ws0yR`>kk&G*tY%;c@BZ2Ri>1i$ z`_1Nu%q2Y97dzOSk25yEWGwyGed6E)4(5X(N`U!b_o?Pb%%F95Y@b)RUMk^&sCxxc z=c2+9e;72a3aXS}fM!2Ijr)`WT70=Evb2`ruhRx)EAx4?X`-Z}HQ1%$y$7R=)os0M3W zGLKsz?I0VZ+uvQv0ou36zm3nW*KvRI56N=o=7S3S+r-^_ouJ%93auwgSgcQ#+|oV; z-m?dCZ?o+Ka6eiTt3LK{b1e@;$>Z3Ulm3Gm>5vgD z=xje^w5R!vK(Fry@JOA&iyx2w{|EIGKzrE1lWgKI)DXsg^k87v2b$)8?bhx3p?L>r zLXDx6H#qzS=U;w*K1T^Cm32`3S4Xyu6_`nl^pb0Jk>vLs7FRIz$ zA>ii0!0_4^$(8(p!Qn5&wt-y0)BWMK5wbfQx1hMQ2;6NEaQ^QrPy*^QfgF1Yn`1$1 z?m$f>(99`lfE{$JW4A94sO#PxD$shVR0=d&$Nu6m8*H>`y*p@Z2($vD`+FMbdK9+i zV@#f?@8-qeEkeEXaXKLWPA|`G6lR6P8IAD(9Iq2m2hI(_xQK7rFF6x z_m+WOpz2@x?zMvUNB-@gnNsH7Xs{?`P2B6&OQozJ?=gdx#qqaRgJ#%%{VxUG>1KQ> zDv&qsZ{*MQC4`YO>l#!TSz!Q3Jwd; za*WT4(!LnYznz6E&H8u|Z<_Vta*pN$3jEtYyk_eD02=eOK3>EP5@rJnA80a)N*RiFp3)$KtdPM#mlo4LR_D`lgTtFQ{1n)PMW-;6Lab=+@gM?2zug)C(1a z1K+zcFzf>5fS28%K^NB#;jmobl;s$i6{USIihnzcahml(kTVZKo%!Q6Q}+*0&{`h^ zIrC6C%$diS(pvwQSfyG2C^_-kn14GnB;Rc20jEd)?I2CP(M*8>FBb4HFf<ecs8{A5Hwu|2KKuC2>37B)5rn3N!j=Sv+Iw= z9?84{%@;wNPkDWkdBIC_x?NN_x_wjxxKDKZsPL3>f(pg&4-W}21b=_neFG%>Jw-)? z8NzzVd^!4%0P^uSXTZmNeBu|-J;A{#@LC3ZOf`sm0mS9q3EHCo;(}z;`0Ea+g2K?2 zfuW(EzuAY8f#EZM)Pd%oOr;W^_yt5?aBzYy?K)J(1zz?1!WKMZsehEeS&BzUP5fZF{1a*X#UB~d_=_(xHveQSu>u+M0HWwrxlS5?_@y*{{Zl1M0kdz~sHAnX zsHCkFV2CIc+6CIf^#Zi^*!TeGfcJ*OY5d{e()jhy@wY5v09z)zfP+&2bZNl~uz7j9 z44fe6<$w6Zf9NAa4j(`o$g-=^{ZewoI9`&=6T{jX{KuRo^o z*F9+d!BD51#{c;mx^DmAPj+UnP9Gn8B8aH(XI5`D6MO2QvsDO_7V)(=_=%T^_ zCIvcOR3u*PwP0Yld!zY?!eR6X2B`iL_&3wVAq z^0$BnFVpzJs-Uq3im)5t0M1g z(7~G^&9K-mR)@tle~ZDt|NkK|3|bBk(Fr=c=%x6-|NqnY^KUf&WGNK_>4rF4|5g!8 z8h^~KH2(a@Y5c`sl+*Z&uPB3Jg8Kk0yf=Wgf)eADfB!+Z0*gWu<01a0rhotczuXO; zNGlcn#IJSm;7j>W`~o~@CxDYs#KFU9{CTPz;PjKH%LAcJSs?VmH2%C(Y5YkCcYval zfA1-6kjRBJ{?CU%PEF%4{%oAaUwqj(jX(c%8h`Nx-ZcK=4~%L2X?N22lWwQ+|2~XJ zTfYyc@&Epm#$Wu+B#r;dvBTX55B`w1K2*vIa@FD1OZ>f&|G}=e-N3;q@cm}} zUbup$?Zb|P)}6hWn!o^>HDKFeGl^T^aPt8kP?IC<1!$FDw=YLvC&vqrGb6h{fEyE? z2B0yEM3^26h#n4*o^H?;ht@ntFHGPTC{cH4{-Im+vDfi!^AEvt)-2wL*u%YzE}*sv zU!?U3=>y6Kn-6fr9`0s2dSwDPWH};iib@~ce1MhM3eBkx7>o~ugO>_|R|$%gO1!89 z&FwOP+dwW3;01~=CxZ&=TF}UhK>$=3g+qA!9F%48wRUgv?^OP#JytUr`9ca}a0 z1}$;{t!sp?W|Zixeeu6kq_g%x0CYj)4ba6yt+y+bL5m7Gx?LX}V_%f9xtRZFuylRGKlecM3#RC}cxVCrzf=NLCm{{OfU;6EbgfEY zbFBzNsllNJI&k9u%Uj@<5v1`5y5$nImQ=#Bl!w0+bilUpftR3jxIs4? zf|^j^h7x}Z=or5jp`b|>*kq^m{W6_y3D5-^VHxL6u?f7G{|~fSN22-1zfzwUS|E;v zQfc-Jg@6D5cS^iY>ShRrDC~6o^P(6eeMI7zi`;((kOt}I|Nl#+UVH%^3~ZrPYWm_8 zXoZmPpH7a~nym*aH9*IB{`gla`{L5y|NoCOD1nxhbH6wW=78gDf*m-{K!Z z45gwk79o^?Pc=C4A3XXFYMfbu8n|V~u&Gy@aI);f%AQSJc#$_TCAroCOOymHW z*n`tV4nih=zK-r|@Q!sWoF>9nV&U}lLL?IkHd7e)!n#)qIj9}bs7 zTabd?z8ni9=5h=0Z)fpne!v20-Eq9I{0EwLhom3uN||6v69_8hfGKS!sFV?=bRDKr zVPvNq_w1OE_7=Rk689dkF%d#PBkDK2>%RJD$6TIAO{Z=aaqUjeXKY>%S zFKD0BiT|&yEnNjlo`t=*Y|X$Bxf9gfI_~<$lYxPuv-AaMn}hEY>x1RYovu&*mrC@y zK7g#2gBESzX&z|V-FmV_3e=<$eIbjm^PrG%eF2^xdDH9qqSN_Lw=++t>yPFi|M*+p zGB7aovN-gDj#h1F>1Ao}mgsc-(0a0@y8GG-;|mN78yP!%|F<6C?*QHOQgbKf2M!!m%U zL?8p?pRn!|FT^3@oe?|`Z+=2I8T+IAaP#kf{H<~S|Nn0}S>pa$5j1-TDp)0& zt9kyFm_bcAy$e+8zqoLofdOIwB3v2|{{P<{4ht8f7lk0c>lbJt3=h62kT6p4d4c%8 zAG)t~dvd&RI}cg&vjcQ^dGi~QG)q?w{ua=D1ZX=9Xf^J<%b>0MZ@Sw+g9fb!N=3VU zIeH!Ur-8;hSkgcP9@`JTmfHnd=#j;kW*N#+tN|(?T9$)nYe9=>OF8(rAK>49;I$V2 z_7mN0Q$UOQwy|)$mhSca69_ubl_M}H;05b>PykDSZ@LDR%3vKV{M%jsfEL5XfqF=g z)v!+?2?;VB1xioh@P+lDCH3949OdQw+d_G|4}lieUr6IeEUDiK8Yxmf-+bc#~Hy!B*>f;&X8^mQ74-l68> z;PvJ19~^pp_&@MF9V~qtfAa8-5C8xFS3V9}`k%&M!T@zIsN?$o@}o5V>pzr#m5M-R z9R$GZ+pqs<{a^Bif6sO1L$CLC*K!yiXg>M>)4Jw^jNflIzh~@n<@x(*UGs593-%Jw zjuocvFk^ z?>4PS<`po$-6;#w0$K z@PdRQU(_vRV8~d}!Xc2+)50O};w)$jY-HWo!a3P8|LJ|2T_E2S~x4CJuoY zWuSE_wi%!J1Q;SCOQbVEtQTQWgL$$TK&Sfr7X^tzrxvpqzy;cir$SgH=x~q9541C1MOn60}c~6|`IlRH1aa3M}dY4V~2TFz~m6E_Q@$3Wn?u2JHv#j0N4NSOVE2{Qp|_ zkIvX9owW}-Ywt9_XX&iHWBt1*Jc|L6dMw#XURnPxa{q7s|62D4m}npFd(bl>cZy#m@u{p0nVj3c0^+X9N)-QX5Q#u<>n36Q`l zumEi5BBaJkARCC+IpYju*VgLDhCC$BURh|Nn#JOE|JPUVI0I$>A59lo%Ke zFHHHwClHn;5(ipM243p-n$7xHEqnK|#UL5bwP)v*7#J2OeBu)TZR{+S%VG)ZGzH1M z*oGp(nk5wxci8ySPKQa{0-Zce%?A~FgIF4Wf{rSwWnTy~;Png8HtrYGL>U+wY(b&U zP{R76=`;hwe^Ze33yx#||2M0Gm<*AJcYw@+B>}LZ)*p+M8viYr!YxoP)qM36$ppioW(h>n}bp9byD+X3N=?J(gj%@S*D~~-4 zT556trUBgC>2~FS*mkf;-WF_`L}LQa|N8&`5jJi;3f{-r4A!}%kpt4H1sw+L%G3N) zq*fTJqt{U&;6(>k#h`>8-hBRl>$g&o7t=n#+j@zH3=G`IU%P&D<7qCj412*U!oU#L z{o}>NGoVcM=@jS|M1j+wtR>KTppv!u{QuX&&2=&iCA|O3WL_LQ^8bHxnhZl^a~cmr z_i@mmbQVv>2T+EnQ($0dKL5Y7_KEQU$favjK}+l{x-;+a==NrJydY6;T|q904VKl#`H{_e)Z z16uxlzl62hPvSM}P6h$cfpvdC+kh^Eh62KP8Xtj9J}xoqc4O%TEhH|{;qN#Ax{&=w zF>CkX&e$KI1#|z+UU1w8EmHc?e1u2SjYazgBO9YD$Lm<@n?-T0mr8`fUQ81L7qk4W z?I3e~|8yU2Jz2sFa!vPP?L(ceKVCCK4GVjb3Mx4RUbvkB#RljM{E|S>mW_+n2g{kd zFEEC3Xy39vSY+Gn`{%U=XeT)TK8Ao7cBZgF1dac$9Nyi265!+2>e-A>I)YfY`CD~C zI}2O|UcLZz#r=2`w0|34>OTIxl;`C&$O#YviQED&*2zImK>+oYOH{y_TMiVnBCX%} zp)qU!4j#%}`k+vLu}_YH;c(cCWq&|*XzCvZ$ks$q-{gfi$hIQ_C=m<3y6yPu6WygE z;HbR|(g(_u&2JxR)&r$tFRs4*{~xj&f1w^|Hss|$&@I1^Z3h7_9)qTMT*2E8 z4wPID?w06w0Nr-q{NsN;SB+%jZ-?;z|BD2(*dwhE)=1ZLH2yxX<~X@b@I^h$)b3+1 zL6^dWXE9_n7(ZkT2!7F!#=y{gz-=e!a=K2}A6Y5!y#@a}eLt{jGlIKAGr#}L`rmz` zv-V5(v6CP3(=Y!2 z*FFZaB#@Co`g%~ni=8jPEnMas!k>))ySIL;cdcP*y&9#3R zN?CV4n9nWH9WG;hz`-(*rIyXXQlzowmq(|&0MsmPkw(zkvv3~JMm2*M`XEEuBbyJf zfP#)8Lx7KgAuPBvT;hc&Nala1JIBn746#|7hgd8^wJd=I^9{a z57=nmFh0;J9}hY9584ukP=UQZDlFP3qz`<*pnRhHh$_Q}|NpH|6mfMQjGWTV(8;25 zSQnJBTNz%z1kH%Ka)4H7aUh!X(6)S0JU?i1x%;hB3n+D1VRK$Uvu9G?>>C+u|OF2jc%^}|Ns4~>ps~1 z-S{-~2j-v6AOAOh_-}mP_*nBHmd1w+jEs$?imD*0NusU2K+H#=ey4B+nww5O)=U-2Ziw7(3 zb@~? z9^iMm;ne(^vCQP#A?DH-y)0aiy<&g(85qiMcC&CuPEIM~^e4@rS5_T!(J8OlyKDNNuDJm;tgn!lbo866B9CRggbE@ke|};}1FW ziC^F{Xyji$jsNIjhBSU5R){Sz4?#XRaN-nD{SWF3fV{;FnzM@3X>Cvhn=Jxnr13|X z9G##EGCAbvC;pfhpZFtwec~6m@rgh3;3xjbv!D1Q?|kBqx$ucU^64jjfn%TeV=jK; zkNBR(F9Z(XqX(Hk@yA^L#2<4kjbBI>WPKX{(Q6>VE1&oUo_*qvIR1%0=GQ0wm``c^ zBL7uEyGLw61b?#>D+5F0BM@8ngFOQS^Pyb}92gk1FX$H7FfedmXarr=-oW2{g9GI9 zm}j5(W3Hs}3#mfv2)UWY9|96P1e(>^mEZu1_#>B?Kk*B^hC2GoC;k|a2X1}hk9?QL zuOYg?672PdpZIkTf8vk)n8vTcy8$c~@g|MG;Mu!R{1NYV)&FN?(7wR>{~;p-_XS-L z)%=TrzwbRO0|WDk<_Go74;vZ}HvDH~_{1Oa;1j>V;ZOV#vIoGaEAsj${umhh|0n*K z!^{UDFpXbh#sN!EIBS?PIDzQM^J)AM7t{C)PQClYA9+2EKm7l$278cKL83=~F@NHZ z0Q*+~tUT}JC;rF~&=g$canO{eZW@2VNtZN!4O;C!)g2l-$B+LPvb9m4Pt!$#2@(>r0WxZ#IaBO5l24p zM;vZGB5)WM!9ubhz+S66@rhsHVj6!4Xol&cLK=VFNl@YkP2SyLU|`@r*!+Wmzr_i3 z)%Gt2{$9{%&G%c4hd_A+G(lyO#vgWh=VxY6Ealxy<1fA_lE(iFG{1Q}jsM;0H2%*Q z)A-9Sr}1Au)P1V)(f@h|hQ?o@q`}|3h>?K-oJDLwS(LwZE)&QQNb=LTxbq9#%n)9P zQ;RQ}K+G1B4FHE7!fdcPI~o5oGcccMe8|AS!qEInpeTA*{XcF{_K^i;$25LOVe!)R z4`?n>$VMfNU*mZif88%o)&=?eM>q21Wz%*h1_u6i(8wYvp|rndWMFu?7*-&p@rNJS z@xdA7@7j!*oNN7DG~9)YG4K_)+F{>4xdl*SJ$rb1YuUb=uNuE2gEuB58B zV_|ri_xu0%yG0u@{!+YAmq@;YUtMMTy z)*63;NXTF+xVUWu?*eQ7$-v(N+N1*Z6F7cLb73hDf84&mjhto>`b%_S`i~xDRt5Fu zntw2q@PNujP-1{OmDR(EQvk|_m18i){4I&#r32vya4K*>Qt*jC;>jm|fg`)#F*7i{ z1f7xz4m0Sa{3TGVUV;QZ_aSf<0Sda7Z17~U5U&L|feNt}fHQIA$z3uG3=A&=!R8C8 zsHE`=g@CIu@Nie z1t@Bvz9V3AX>uC>(LZfX2cn{)kJT_yrDu!w_`vW*w-Cz5)unN06}VKEZtm6o(*(?~(!yB>i9j zMRnbSU7*beh_wXe5=E@dKN-peq26N!Rpa1LZGIz>#xLxmBG3t1VR)ta5QqWVv)vh@ z!qWVTqf^yfc+-*wQw;ckdJsEWoz4gZ)K!uNxA2%y&)-JcrYf$EYpehTW2 zPy7*}N*TGfIMw(HWbF4_2Y<0QA7bi0)cin!`2wht*#W9#()f@3UX*Nj)yij4t)aEN>?9pgZb{lp)6{u6%$sCn`MRBM6Sage093v~4gq;b*02U_7F z2}vmYEew!u>ESr2#^ayB6=cLQ?3yqB{r`U#T=QY@bTPO}WX%BQS8!!~09p-)9Rw?V zIR~T(UxJo*r14(^HIc9RsBpYkaDsv1u8hiO{yG*FkXg;Pa~|>uFz~nZoMK>Te#3#K z@mf1Qg83#hp@0UTBuC(`&eet=rsCTaY22h#XMSPy_D zeqBi8zkF&X=mf-4AKU-T3=B23pmbtu#KOQ(&z;79%}0ghu8RuG;WU1||J5qH-ZFz6 z1j@BM-B+3qiFAgjaDehIDC0&S0S%uBfR)2s@cC34zs8L;{zC^DZU1vKFw`j88u2hN z)NcT}p#dB>F(;6$x%uvJ8vh~L4NjZ_jA{H~U`85$i0lHebFalfT?6hFA&B6xZWk2^ z?gOO~pd)#@T~q|X<2<1Ca6I2Xc3*z&*nOfqMnweNgK|;fx%l$p?TfE2-rzo2`sMrQ z?hoHnR3y4jbi1gCe1FD#v53z)L`9&Sqln$wMTMt~(a-o&_pvz8nmW)@Qt*gdDQDP= z-=IPI*ZN^EbU=*O10}4W6Sw5QyYYZ-VJHy^d%?FIG{!goB=}s$Na+Kh6{(P+Oz8M| zw;PWNvkg@Tiw%c(d49Z+`H%(~ajfd$S*pLi6eW@u1^-4uekM>*R|At)ygp5e;${=%`Ht&>)j14+8_} z63Qn~_lLi*2Fbrx344+B>i_@9&e}g=FJv$V1VIPsbsv8bzym&dlLI_ z;At)i4+wjq3^FYex(yCIxZKUM0W53K{F|{zd7(Q zmGB3=$b!n1GIP4#0S#om0Bs6&d)?X{3vz6C=>xEl|4lZ)Y&r}ZX$MWnH~(hrK3>Ay z?Rw`$E;q=FU|m^^FXpZXO+i2whk!=pAS1%TVd0&=e>z=%lt_2SinQJ?5otYHD*0mJ zE%@kMjx+-U=!g%{X12rKr4p^*N_ZfHprr!VH_B9+YkB^c@PUtp3w$y40%$c4=md{F z2sPy!z=y!%8Y=w)8Y%@HkOUn{EwKj=lzwPEP-4p8@dIg~^h3Ar59@>c?fV!Q7y|yA zfiCrUp}Y|^X!@b~hyZlZ^mU^3&7zFflO;;Vm%x|h)|c^t*IIr52&P`Mbszrz5j0}@ znjb6xQB=;uvs4S@6)Q$jgnOS_2el zpjAJhDCCG{m=z@OGp_|P|M6eCW9_ucZ0B0&6kWSEmEND8R+l^;MbE&`! z54b&`q9qS>C{*)<_nmG$;h?M`5cc98Xl%Qdhxv!`?a0^6-L*VnFXn-|8g4w1Ee9$= zcLRV539%K7B|&c;f$S8_0o(T+RPM8|MErmEH<_ z!SoC|MjZ}5xkCc97X1hhN@zffnV0OKJXi|KxnVD?K-xedvO`0Ff#F5R>;M13yKaq- zcDnunE$Hvu`{w=s|E-|oa^w*%c_j{BrS{T=nE|vn;YH_0(ADDIA0j)qzIgxtzhyj2 zEpul)OBQ2r*o)2J^&UK(tzSR}9pLW(-CW*%toz)-AFRy}umk-{{R2Z-Usjh z|L+!QU6H~o06J`?_0IeM|GPp2RhTYa__Y#Lba#Wz=$QKZ{r~@^9NO+IFAsvQ+cxj6 z=jhz~1f=_)Hkkef*2~~d?AsUVpd}>`*MH~+ z`vr8`BMaCg)+LM@{H>s+!`2~;I{dBc85tOYd#8dN8^wBaok?sfWaeWF;R*O9Tof~!=Z`^0M={%r^N_cbIe;1*y$;n@1W^kQ!-NVE2b zUKYcbMIfUw!{?g|BTEA$G)g49!H$2;-eAR5%INN7eXZzg7dS>*50ol&AAhOG$iM&z z|Ax{xFJ4`NCEu5z8|onvjQlO2ZZagWK|#$6F}(Zt%jclXHWw7w+65fU1uR(%-7IrK zVIB>31b+*tq|IUqh6YR683u-Ka7Z;D;jungYTrE-6oK7N9L&eMPiT8_SUYh@gGSH~ zcD90&SD9$H6Gt~Vu0SEe=;q*TeY5DxcPAbO1qO!KA@K123!XIO0Z$s9`2RWv;?|v@ zEN%U}KLVN}EM);T zyh^`0dhWQVA}X(r|%Qv1K{0T5I=~&$hrg%D^p>R4_|^h ztHuW)%Yi{Nex2LQ!BfD^ zs-WZW7@FV61RLLW=9C332FT)iq1F#N?U%m=v`xhLWTz}hk?{fkMPc2hAQhm6kj>|q zI@vqpSvvhWI>UKD$IJVE=yd(k_%Smt)wA36jcHyE_xm>@}uY?8Ya1OP@sWFY09LJ_d1q zX9P>92S>N>kIn#|Zr2wpL0PPXxA{C1)Bq;q1K$raFbFV|_%@$oInE05J!sDg#5W)* z296RVFfCA`)qIWvqJ$Z=oDuBd6$&N7&F2&#!l0$)5S{UH#s|PH$SjTwizIG=7oh!2 z|4moG7j3p4C=mlC?f(~Evl}09Ksw02C{tTC1_P@hM+5(z<=;Ep~WD}!HYZ3oH>&*L7Gh<s*FVNb13FV*{4f2{?Fu?V9<;&{a-2oVV$dke;cnj#DV?CR))^w>A&UkA zLA5<-;XtYA3*Ynb%poBFE=Xbz{|6oN13N(6rwO`PBP`tb8>nFjp8Mvy2Fm@QWAXl% zs#>zHN#+$OlMQ>DOixX`P_fdxfVwuYb!uEN`-}Y+k)hbzk$|u ziS7LVzxzgH>+MqI*8e5)VJ}2Q85kf6U?zPpgPC$J9&~OPc-0BWInZ`rD#(Z*k&&(c zOSLRrc}kERbV3A|gAT(T1ThKJ?ghE$_!WfDv_Q*;kxZ+?Y1)3cY2Beb3olIJ7WjUt z+m}Q6g0e3U_r*?8kVx#|7ju?^_LG!wWQo1lwUmJ&@*68if~iC?OZ|670qj_TU#v3qjS& ziT|Jr5#x-{M!&c+6;erd_kyhHb^IR?92oTC(L7MEK>&0n;u6qNw{ZQB7C??A+TZ+x zsnpN-8`wjg=7BF>gHkc*`nlHICF)sB!7oJr{{P>}4qCQVA`Ut+3hM0_hpvHwNTBsV z>5l*AFD8M^>ok9v`Tsv?xpQmc|Ns9L!J*d+CbO6Vx?M#;SxzA!@I@O;FMo^0|NsBH zz)CvUUuOUR|33@_UaaSVtQ!U`?grgY0iVEce#3KDMCC>8Ee3`cAmf^k@Eq<9QDJ$Z zaf^W=2(+6GbXG!1U|OS%Nx&0B85mZAhR#amZ~khwbpdUS=5GzY#lWx&RONl3}I>ArF{I` zkF5kvd6m|5`-1MS{eBSa5YSHeta~^2GynPjA9NU=BWQQ6186+wn=79{sXX(^PG6qZ zOOqA2S0(9B47TMLf93 z0WHrG=yv713tm#)+X<3a|uz||58rSQLR}_5wV9srwl@l@;jAgeX5iti~03S$gzXgr%DB3r}}}G%Cls# zygmnAX4>t_u|lDQC5!d7_zDi_`GYH1N?5X(UbC%WEMd)Jj)*BcRu{ zA>ajQUtxE#Lh}(Bkfvl%kJC0`A-4cSWT|HBffCib&JtnGZzS%xc{sE0WaWo&{VP*IQIv$VXZs?br?`+Tg{{O$0-T42#lkTs>@7*-M1j%5G zPTj7*c7ifo^8^0o69Q?SuD?L1O&zS&1f9D3<(uml#uC=n|D}xX7himH{lVDj`lW;e zR2nsOx_-Hs`@^&J&Ry3pt(QueZa(OC<+&^Ini;h6>wkO+N0z{gKP=!#`3rKp;5SzR zg%a*8g%{5tqVJ6lw0?`@p8{!wfkpu#si#!+f2qh_R~}H(34tda85K~&gz-f26mJ z|eO<@*I= z(51BkhK?Mdu}?PU15gnTn8?K!P!SfG$iWxPP$4Fe5L>q|$H5n@U?JthhK?LB?lUtm zbYJ*(h!M2WgQMA#N8sBbmJ)W*!d?#^j&FxJU~HCehXi13rf-K7O4zzxIXEMDy4hga zz!Z`Vlpxsv)W6mQ8NOtR)L{J z2V_8k!ozM?iJJ`Ft{gWb1i-QhAZ@WS%?Sw)L88nzBLZH7ZrF}g zyC6Mx;d*>Ix?^R!9TQ+mK&ISfz8ewnf{h7ugfm9~Xrn>+e^JoMf8D+u-yAsvN|>9~ z{(W=g-~cgxe{E+0|G)qL=LHopooufKK>Y6@J_`fG>vxJ`-HZocFf~752k92|C}H;~ zl~NRYE!NGZe25nmpszV0OlHu{1E9c(D`CIs7;sbiHS1l+fVG}qAMjhywKpD`eD)^{C1!%t1=yd(j?WzLWZ0Gvt z1?VVa(B9w|Mcu!^N5~#1We1q>-r<^wKPoEi<#h4J~>|4{{R2~uB$@x5gt&j zn#GY30qSo({`CJpba7)%G^jFkDDi5x6_~~?z)<1{>ag*z3*~sN*X{bIo1xKym4V?v z33sD~EQn?{K5!V?m1|Z7>u65p*bh<<9b~IsO-vYg#4Js1^X5W7R5xE=tWA^O(4?txN*KJ*vY1{%J5l}(GdGp=P7xzBiy)paS zL4^{wo3B9z^*NzZAjoGC1}Z5ssp+O!-*yEh3?e<|0DmG zvAj?LF+ekJ(D-=)T4Vh}?c@Ldhr2JnKAOe%B4R3Z5~=Zx1~YQcsJWKoe>mt0T8Inj<&(t_@S<|t|Np(MAmQdCJe{pK{(!g!pl$&8wx`b42OxIu z9S}M728f({1w?MW03!FE0ZnZ8O#K0-df$MlxhKF>>k%-u^Z=MzyXWu!|8x3VKY;o; zt}LCcFaG}j-wR@ZHi{o_1z8EYRI1zIPiN~Bup*vLu)9F{4D8@;km@&o{{M&Eqt*SR z7wp`C7i^%`P3wVD;nx49{2)I=yzI*a+FlA7R$SBpZbX5SGN_laCz%(r1LMCbhzY+C zk2&`L1LRHQpboJh0|Ubu@Ii?I0pM%yKu6kUiNBa!1MRP}MxNCS%VOLo&cbjYEQ<-e zAwKLy47hnG0N%s}DivD4l?Xr%@#gII6=*$KD%QdG;`~0?D)`x;F+I>$SnvtnU5p(p z{EjULK=;ml1|8ka-68g35lFGp>x;$*US9_%_cNfgv%Vh$4fB+!bb+qKX*p2h2N5U* ztzl$ffZiSnr9kEJzkhYi7eI@Q4>ccTSqWZR{G!|OPs@Q4qn0NnDxhPa8A^mfov8mM zOs~)OI{pXQqJ8jiuj4;B>o1)32g>>{8qmZcV0>~h;em&I0>-SMG0zfq&<48;v4>;-t4cI+2!wXOS$G64`@fW< zgysK**u(!td0-<+3r}E^7J*BjL6QcIHo*)KfUCFwS5X2wLK!j+1h%CVq~X74M+1j| zG3ZowP*EM$ZK^PhTcGt@rRqYHM|=Xt-ykmUEd5i$8wT1q`~L#y8XHEpPOw5qt91SW zP&peGo-xCjQ{cboj|L8bZd1@c&h8%>Tbwxs!v9}`7?W`T#9Iss5xCF^un;I1;6hix zLLjfhg&u%~K;DH5{Q(Ps{0A4}ap4pQUwq{up8#A)0W5R_S;zt`bO%`|04($XSttc8 z^aNR`1uXOeS!fPe=nb;a7O>C-kdN_bxwgXKVt#Mh64jc2{!qg6A{oqf zu>MfW9sXj=3GjX~P`mFhhzVPgQ`H^D(aooQs?(RJ*NG8yk(PuOzOVSUDAHk##Ij31>4TSYCtrMf}?iM1%GRf`)e9 zG%z7IG`d|mdV44Q{r^8Wtg{u=GU#>%tz;1Bt`+G7SNX;Vx^Hyu1=Z`Ft!qHF`-jfC zpcX)9E2w$U*$Qr1w1Qd_ovlkiEsIvr>GPefpr*u&jLHB1zgV*U|NqX`6(GG}8$hc+ z_Hr>Wd~@J&C`}G{!8r*OwI`Z?{x6Yi{`s#&r28T$NFK=_e8k2KnNfeux(hV#_RUG9 zp1-w`i-7@2@j=iG-4E7-582SePo;ssHH3?Sp?fN*?b3RQzr~Gnol#m ze%$a&t5m<6z4Ui15!N34AS{q_CILWjgfH)Ik5r1a^$O1?hyi5Tb3knY;V?o@Pc3_h{OI#a% zWt3PzOlbI(QzFvvtDL`8hl7Ek@ieGQ`jY+s|NjjZIi)-fji*5i6<&fa25LSn@bVp~ zt#Ml6<(Gf||3mb5G1!=u%5?7qrIChuMw3#3?&Hk|m>N%mhG1Xr`}hC9jWLqE5lsFu zXrJ)Qc_8@|{+3nj3=B4z{4I+>bUuH}ED&AF-!chASMaxVf#?YSmL_&czmC54@V0h_)?c5vbF@(&v%<@`wD?>`H=z^f&YiGiW{M=*as=#-R_n&uad zB?2BEC1D;OB^(|e{H+qK3=9p26pn*)H>g(y$s*n0Xzbkz>I5{Ob^tFffF_P!Q2zmx zYK)i|7>Et=m*%8n?i4aNz@TYWK0$lO_Ddmps!f1xnbP z4=}Z!Ed8u~?Bb7?HlRH)FCzF`HZU7Jn4*_df>5>Uq$PvLC7ZJ&|DXbpAf@rr#f#B`M86@=8>jf8_JG+A@RU z2UHY-RwuOFu8eLx4e}o(j>>i@i4$H>4? zD%kKVy)+Dxa6qB<+ROT29Y^;;NO58dnjEe(@7)m#zBMf6(f|Kl;6fWxfP)Sm;_Cj; zxfhfOUvoiB0cn90!Js0DqqDUGR8xV=r`MKgpi=DxGk!^`0cPm2^;@@_dl=sKxzLq2S|Xc+Z}Y5TKBKltlj>9 zy8nU1WUT+yOVqGfpDPynepC40_xljXL)`xTFvA1}hEk^Pe~_%)da07t_>$9Wk>Fvtld zW}wyC4R!`4x_|)Slcis^k3n=d?*%n>82DS; zK#kAC4kf1F4}+qugcB0Zy04|a9cF~_v|salJIquf2$55Oggz*Nckcz&q1t;vIk6iY zC)z*09p)*OLn+C_vlL!1ftK@uRWu(F_`em@sOkl`VFDqwL_jY%egj^xf=cxxBA|ID z*>8tgK&cXxWucWxc$UG7?Vu9kh(PmRP=Ue#3D%O@)&q5w-RC?y!GX!Yow4~KQ$QA5 zuj`l2UQi$h^tLYe`~QEyi>m#g`UEtuY;Oq`DlvyT2f5Pfb^Y>xD?~#HD7%AA1ub+1 z8`gTDblPi;=98e+lYjsJf2|BP0mVaMFRZ{073l^Gx1Ov}2F;LR1`TNO9cbwySXno? zG1q#aL^R;V+{XX^jSoaZiU)`((3)QWQk8W~1=XP~m-t&HzWx8-eXwCKXqN~>d|Y%1 zS9k9W(8dzb{i~qys29Rzkm0Bo=hlEaAmA~MnQ#C92Q9xnK0Sd=V168%z~wkL0kwEG zfs%MOfyQ_?fz$D90=$WApaF*NP@Zp2;L|p$I2cOw|9i1i@O3kF`Eqn{{Ac3dcJMWS zw<|{w|GonOFaCc5uTT2{I)BYopqb-;?BQ-#f&Y-()Ir^%)^Bxk;oY?&;r~ko{Qj46 zyqE);#yrB)Z2!N6rS)6=b7-4Cth-bKbPstqTc@kUH+LR~5`pG=4u(>$ZeNjZR~|;j z*M7}v48h=4WpxhSt|9^5t{mRs{M#4;UU-5=w_HV5iy%vpoFK}uJu3E9QNkAFAOET-F1JEgpLV#mtN{_ z0-f-~3c8i&1OGt|N7yMt(2W)0-EA!lpbD)d%{Bvcv}t^|8)yMkgr!7jNOv39aR*Ao zEhS2Y171Ye|NsAg8%X_&xqCpZvu-!gA}FY=Ekai2AV~IqS;Y$tgrICaC?31pzd@T=n!?uo2U>am;!oZG|BwUG_Ji!zJ|6JmC0Gb_02_#RyAEVONdJoqb>O8U z-EAP>*(QL(L)vl%$d@38avo-2_`eM#^D)@WG~_yO+CEgU-pUdTTK zG^n3^^Z$R)txGRrKpnde(A)g{3QClk>v9-MWL~&{#0zp-zm;-iDZDV*^8bHi_puj+ zH~;@XoW=9Pwgx&G@ZS`49bm6pPQVLA&^DRK?hl=%uuIjz`v+d{=`MYe#q*-17COcc zx+S3Xe~C5Z9%hrUZUgJ@B^u$K7B4PC#K)S6$glt?wd z;4R_vC}9Duz*zXhjZ+}@@WL+;>H~y&1ExT;*x<_qvKU^hZw4LDbSIft05s_cIviH$ zI4g(?vgN<%gGLU4*E-EV{+6N$KLH7gHvjljD$wov0imJW0d}yeFXVW0$my`)Dnrvzo>DKxZ{*9YE)98PFDOkc!@Fp4F>Y?*|>Yrv1B%#k_;f z&9n4-Z#U@1aPYB%T`ZOzjE-KV-(l&o@r?p2@=ymj=l8b0`1SvPc)b$d0!ZY~|Nk8=e4wCu&E7Ew%y6_mUv%(wWY+xNX&~|L(-GQ- zI$Iz7`v0H#BJ-in)+fKf!(h!nB+I!#<_PpUD!dkM-U||!Ea&TG;cM`aROoel(82VY zsY9w8tQBGw$mm`0C2tS&AT=gvT{tKQKD-KQ?01$vd2tiellTG6g8l_1GM42zCF0%X z8PLqPeFG@nAA9lTDk$^uzBmB7kOM8Kcs&u6PkCRQsRZTIEP;$0AXi#n z{r|uD{QnoGAUEFVjD7IJ22>LkXMpP2OQ8JP>B?d4#=_r{0a~P}z{J4t;^tM5dvCPf z=5GPrjlC08nsvKA=q||U{{4BW@wZOnV32M{Mo=XITH(&o`k%j*9n>&#ebDWZ(R>Qz z3&B#+ZjX${pJ0!01-`gf0W#I~L1#n;#P!VGt`ELB6fp6(zGq-y_{IvlkCc(W6?9fW z7VnGMpc^hhf#l4x_z36-MrV%2CqQ&FD2Xk;0b-u(^nKF&leJbLt=q+$C#{pk_e?Uc zfaB{I-5{C9pP>9!%iHB5DbdkrFpV1|(^>kY@gFFo)CzR9$bnK!N1MfTZUMK~Pr-rQ zd=lh#j#6PT&lc=>_J9|PAjfyg#?0adO=^7LKgf&{^oF4Gj(A@Lf+F_tYvtzu|4Zc> ze?v3}zj#vq|9|9*)Wxud)@vr?|J}!5JiQE=*=~NLfY|N>zS^?8l;?#RXm=BMRW4uH zi|N0?>nC5X1a%dS|977U-Ie~taz?@|ZUO!l(ADLR%?AuReV^EZ@_x~?#@{dgGBEJB z90QF`{C){$gYFgJ-+nmYzbH!+2WX9E3+M>cUe^}^!H^OJRCF{kFff1%vR*fd@PHS0 zXZ-))8OPFmgva=H=RQ!tJ6p!SDD!WqeaF!2`mRK=%Y(7yWQi32wu}7RI9{`XG8l`a z^{KLN%?FqoEEr1f_qs{#{0CaS$id;@S^5(+ovZ}Pkw;iM+d$@Z#&Nu6?yTc5KG0hS zDi~kx0WBQ01r^aH++i=~{rdkOyk@ca#Q&F|1I3XX=P(1*gy6|`ePYn*`k=R=U>3JP zr|Xjj3x@6!C8k}DpowyA{%wMwGEThl7bwz;g}d4#W^oH}xQIzQ@o#fvw7yXGwD}-Y zgC#@hxo+1d?#%}{I$fVM|7R)M5!@Naa@-BH^|33O9RCu6TClYi;Quos@cz>yW-?fVD3R(3@eq~L(mOaDuGKu3Cu)q>ZE@oziP z?fRj+0d#sd==f+=(AYvl?H}+x&B%2OXzG&V1!(vPw6H3RBjX1scgJ1?o%IFUsMZ1s zvX_eofkg*o0Nz&{s*@pc$)1Q zO4-9-{QrVvh#Y7=>x(9kxi6+%`2YV93qyA)M;7mkqa~nX5X9zru@lS=?S8WmbT=<( z?m-kYf?)>$*05TeUC#*5-zTdfE<694ufbaVSE$oeq z{13kG7j)ZiC);bzuos()K`H1PXw6d-hd_Myu{h8UA%$daffw25!7+Z^4IBZ@X&em3 z|J^(5L^|sVvYaE*I@@-DF5>8H+sDYjaNI2eR0K6I+X0%O&*FXIUIdFFw~X%dpzZ{$ z6tjcGg&If!==e5Qo=&%%)&r#+3qeuP>6Y`qEa$~XP)81?Llm^uPwD*s|A&qLyMuz6 z_eBsWCPA%BPcY*})2jdfU$7K|dMBkEFOnHRBgTg_*h|<1URXc;|9>$kG9p2-@i+_? zVqzfgeE^4;E-b{dL3@lq!(q~(862M|FZD5@aY}z>Cih z{{L_01zGby@?~8i=ycVL22d!fp8NlQA1F~-f}6i3T3I|VvyMk;dbo zk}u8DyhJQK;{&n+&`QnbBO;*QHE0!l*ozf+A+~{TB?Xs4BsSb1+ zBL8-_wAKTlTb*8l#@Vy@x+@`AnZl$15gtJRPoFO9c|9z#=l*%(-*X=D@!M;^<=3;^A899 zX3!REuthgZDg(l@9Kv5)HUDHR6>I+CP@K{HJH8|tBnkAtYkg$RbV3f!~dPCyY$4Z35v-Bdne|%ortiTZPV$b{k z|06*`44$<7z=+(E2c0k69V-GVi^98WWjb3${{8>oxmV!d|Nk#qe*gd9+X33H+1U#k zNA2wZG+Q9-#ov06QqYFiR&^!@ zhSvWjOr7lA$6n6}d%-e;fuXZi29z6Zn;94wigm*NZv{E%Mb4mv*g2oES$LF>7DTLVD*ZC?0JXJBv$ zfb#yAN(8?!nhf%z2q+PP)*QVAoo5ZPF6_naCE%%Y{uWT8!XX!pp@soD5&$;3Fh-}KhVkEy%!Wl?%`n>Am>3Hw{H^2PH@fuo%kOf z26o8`gy>EN28QsktkC~kL2>q?4+}#R_1>=)xogCfZ1lIb$L@X@;<^tLL25)mJ1Sm+q7GJgMMAer1smTE>;7yR zD^RBt-diisThH>}99l+sg0=F1j>&hkE)}SG4DR%T-TXodq&-U{!vj=e7oYh5-}rWC z?33nN4%Ra97veKut?3t!Zh*!`!SVLO?+2*H?JRxp;_|!y|C{{^1QcWcWHDxd^3IE$ zCqN}SsKasxbhZR&_j4A{3!`iX22h&>JR(q*6aGRS)GGqtKm7uf{U9z4e-Q&7iRS6P z(HZ*$l&Us?)@*=oHI&VWn9U7ZR`#OcHYDYja2;oT06Myxfq@~5=f#CAhz+1Rpw}%Y zJmAH)cmMx~znB0TZ#}~E&8>i`)CSuBDK-9ImIJAPCcXnZmlsq6bvJ@W?G`6Y;1=j^ z1T_{Hr!3?a=yohw95S0*0JPrrg*fQ81-`dnlJo? z)LW3%(OPAhm1uH4@61cw{{ch6YH#=y{7`{Tu)Ob|Z!t@!?-$T6 zaz)o4{|&oc|1=-q0o&E-`scp^+^SyC@(kBM%|{e$k9ctk)XZ$I{lQS`)$K3SeC~hi z$r3@x_+2UI|8kiZ-dUi=oV!Hpff9iap!4uS!V)h`K*Gi+JL6?~omo2lB|7~DI^9L$ z;=vnLgI|b(q_G?LD-)}Mk0HV)#wVes`O9?ri@aWId@>LOUKm`1)Fq8?&S2CJVcn$y zkTW1mK&AYF5_!-%&ai;+7a@=Y`BIaKfr0rzx65&nmvT&?HrDZ0hkyS;M{zQA-{_oc z1Jd@5zvVaRn73v-AO2R*X$5J`bxh9ut-)ZyI+l3;Ru54B{{pyLcANw%+buw4dnBk_ zR0EaRC$!I9{Mp&-@(*;Fg9vDT&N?#9l7qhm)J5vv3liTAierTB;bH%cU$EQ+m6D(w z&hy{+#kq-~jj2CM1pkBG*nF6$@i!=*>MnP01=-hpj0v1B!d@iZU|{Ip3-WU}*bAMl zAR8hkkI^8s7X zUQGUG5D6*_dssnQAQ}VyZv`0@4nFS)w6XR8L{ka7Gb9vyP251c)Y(dSnvXH1S+eoB zo&kmJZT?nJq5N_oxPki;bi!ajR%mal$G`vo1Hi6kf#Rfdg3?&PC zJy<{*I$KphB|$65t)0ClAa+ap0?-6Ps|1MS&eGW`19mqk0R)5vz7Q-2#SOSs&EGm5 z+%Vb;l5_5E1!?beu@)(nNVD7uT7gr_-#ry<@|Ni!Gha*fwt9ek{o?KC|NkLUk)17I zx#nL?{H>r(Z{4k+5bAVi>23uDSZAvR$Q>REoxPxy=iMGEP-mX&>~#RiOa;rkvsg1h z4CHSCU6#?^3l@e*&IRdg1{=iD&Dib9(kazF7wlMwkHH2xc1E#ug98>~PA7P!JH(Ra zpR6_0x?92a^@3d0{DYOh6|~tci}8OsC{{qe%Bs%@0QDOf!(J@h0m{uXphBS))Ga=? z6I9NmDfYO6R+2b0|EMo|n*kb%_;1=XmsfIZaBapk8DI z?O|{)crDlbixG5$3?$?^Uh_5oVlCx_#RO0GA)fI66DD|Z3V?DJD8WRQ*n=Xv8=S`f zZbVEE4p;=x)X;4b#*eV{Hj+Y82I&=^h@PsRd}c?BTzQlBtnvAw8+ z83pPNtAXaNP^PW8!AbK)3&3 z0RMK@IZ%2Ql%4^i(=25tr0@!q%JOe#osz;U5DZc|4J5 z0CY!m8Vdsh|8`cd6kdVmBRU|B9v}_;+gaV9v6@e>*F(XmD`A|1y!_;1{5i5Sx$ay!Ojtj>uw)GQOR~?Hu3yGrN{2izOn9 zE8h507OPWq76TYEfykhMz%0fr#uuQ)U*ML07E?e#aQOc+5zq+&pyO$pk3@8f>dfO7 z=(e>0k$y7P*K4J$Pt~YdpRZT4K2@h=eZE%C_<#enLv4M&=9BfQ`ghjn>o}}W)q;jh zo@Tpo*f6_+4(DfP%lz;Hv}Wvp^{G;BYf}SIRLni_`jEA$4Tw4C!0YXh4#Uec|No!K zGRSxUN-a)%pdE(J*gKuEpqUTQB{i{UI%AJyvA?j5XJCi~rGe9b{{IJ!9=kpXcp(X@ zL_q1`5NI&M^-jQx&7dk1Bm$a-?RC8o@B*YB)Fx^LE&O}&dou$=r|XGMaGGcar;`88 z;6(F3!^DSE;Kj-Npf$liI%|)#{x7MpkS{4&_#zp6QIl*y_=|I(yOuyBTN*G?_J9}L z;{X4T41clc%>Vxm0WW;_fZFMcA(~2gj=Np~^;2HTf+hmOU(}xY|3A_p;J+zI{)NaH za1913od1F*uR)>m;>zj&|6!){2E2#>ncgW2QlIeye9FoJ(B$DaH_&-#Euh_jou;4! zp3MuAwdwSIlGbbsN=FPOJlU*1DZBzU%qJkCpajfNBDHWq3fMz}ouzlQ!78#3*mSzy zc+Cb0`Ciux0l``J-L4P*8)W^@_>;^l5d6RN#D7tiM$j}wi9mDh1<)D}*9YAU9TE1g z*+ElH3>^|k`U+UG{$~V$Qa7?jL9j+{ka7nWkWSF$r`--L9TJ_TSGr4|ym$%Pd~MKO zdgsMuDC@?H^I#UNw223`t7@+>@V9;hb=8=|vmClhAN)6aArS)#N^t9OD`+PBICF!& zZYjrcS5O0;!9DziNB;l+k(nnzS59>LKIvk&(JtYzF{qKUv8)$!fBoM0cK6{<*E8L< zpu}bs2P%9T?5#?j+{0h+fplgcu<7=F0uIU7tTvYQ?CxFcHU_m{L5gJE!(Y7219c>@ zsc5b}!%)Kd{br}{lLmW+5{2WgcR(p33*>gt>`GiT)a50-FMolSlf~ZYc4O&~00qd6 zpa1`Nf&=6bnDruQCu|Ce2h@jbuH|6_9lh6mI4m485r=%?M^;Lw>z93?t^JXuoZW|K ze*f8esZ_eRIR|`U$iLQ0C4AkkA_pHZb?>+{pIhKH4~!?U05mbfsx z8blUw3t0cC^VI(L+7;P{DCWpvm;>@qw@oY9b6nl7BHcEvAg?jkDrCE=*f6_lWFN3$ zcGbx|04lDST@9LRIT%YNI&DEk;bKs+)hP?APoSmVVo>P?y0oqnTuQzu{PF)ksCVO% z>G}s`KsPT)0rQDYFkQ*lc#t7RjrBh-s7QS+xC6woK2gJ`ed0eWNC={=Qx;THy`BRq zs3G{p<>UYVLpJN3IddjFEZF!z==fLe1GOUV-61Lh-*0@s)qI1Y(?tbz#H~QLi;4_P zP68n((-{Ikc2)wU-}ut^kKha01)#^y-stvGk?0Ol5$SeO5xDsJ;!W_ev$spXeE$eO zc2)*_?5xCh*s-%B&|_x>pvTVom$HAq_5DWkEr#g0c=)aEps@##fiNfWAe;m_niqT; zZmlrLVuX}LXNZaj_kmJrltXe|R6s}M9x}eZX8fjO7 zZU>Im1NSc263GD)N6zhYTYF!%NW6e>X_21V}9}SS=fWKMR`L3!vrhrYsB$-M%7Os!`pHX`KSy zt`g0RO#eAvs)EGf?m7t?jrbwX-+ur!;LHQfj7;4Zk=z*cauX;RUik92fbPJ`VvE#1 z$ln6$H+y)L1bBFq=z8$CP5`wDVfRA+F9pwMaJ<+D3Lelc%KWWsnHd;fW`R5#D$wmD z0SXi!CI$xUgZ%w2ph4;bC9=I9|6faV!=-hh(yAa$C%T;viXPg%V5w34Unja?UWz?|MT}OU}RvhT@1Qarhh7E6eT5c=J%ifOBI?A z2>&mY$Ucw)+NjFHeCQ?k*6Sa+{Qa%qmGGdY7|k!D_*+1_z^nY_85tNn_*=d(Ffe$O zWO$SqgOf`DXs`xkA=sBjAlo3mREN0O0h(f%U!DYYGhGFmD|i_BdpJQJtKgC6?+1;G zB1PK&0-hJ3jm*tQL|%e6LNwPZF#Io-DRBTF=qeHx4vHi2&CF7uWCV_*meZg_Y{$Ug z0%}Tivu7zp{x6kD>*Q!=XZp_<7XA`6j^14>0XjQbBpf`_3~I^W1f?N}0bQVF0OtHH zpalut%n1F=O#k`AgI_*@I31kUD*~H;a@YI(FGZyBH=uM|3k?VliPn=9y3Ie?>NSwn zfW~%TMncs%2(%uk;B5ZE&ELlZntj>P2=6vE9|Db!fXAhqUlj1SfL2(5gCBHPn+Jaj z=$r(Pk|K}NTQ8VC{|B9kYWywhe`hJri~LWZ3#SbjONV7Ao*hJ@nsXLa!^& zfAjyw0WW^Vf$D0|aF9^*4>A6h+n`YUp~T+;nz88io4mkpq^5npq5`^x;^2ug)7!2UVHV|>8j<(_}Ao~!dg$QVntv~DK;?R+5VcT8!W zT+N4=tgjWlg3jo5`wBE$GL$HGhk_533FqH#mDc*dguk1u`4CfDr$sXx(|^v=mr&Ks zZwwGCeL#n$gbH-~%5=J3=ynwW4Y7gl&^+83dZp9%4rr}&XX%r0(7_|Z9wi*zJ7Yj| zr+nQzBS17;_s$SdhTXY_fq{XMzoi|N^H5R?0O;(YUe`B4;Q>Ma zHzt5=c+6PB^P;#Dbev6R=#AH0FWz^6*{(O5k4S*_BJwaZF!b^W^*VA`A1w3e6$u6H z>}dQ2I=iV{qWjQ`$jb~2-CsIWU$lNJQ8~_b<_rVFYq6jg3o^hnHLfo}7v=ICXS;is zfuZ>rM`!7a?$8^rS&hGSmcD5H#@|xM$iNU37T)XnruBAr?45uthX0#E4l7}Qakm3J z5f}${Q1cN9ukL@Xm+F)ua~{ps3}vF-d}*MKGE8ZmjG&m{_G-OU|E#<8Mc9jtparMK z2ON4+kAT`^;5G68-Ts5lxjGEG=l6;6x6axZ#s~PfpX$Efe3;20&62z1JOB1mov|;v zWA8NoOyTbr2A9iEL8n_E`yOVCNgpiOKg z94}L$f*vnHLy8$LU{m#Arn2?Avvs<@$SQal4myz7#(f22i6j4Z{}OxXgWUh0E{OP{<1)g54WN_&)m zoO&13U2=R0Dhsm`UxKEAjK8^MrM$ck3XGQ-{4LwS3|9UYP(Qi(B^!SW=paMS66NNX zto-24vxi3sKWL8{=%BN#$d^k&CRV-#Dev~Z(p<^GUC+@y8C;^Ubx#HrC*7q_ntw2s zN;TVoVz%}{S~pWSKPYBFb;?UnMZv$FE3NfpNmX|&$d6@3-OS)z$kEIU_7h05^x5lZ zj}lgo64uu;ASVaE)`xO=L0sS03LYgA9widpz7Lv@Gj*3f0k?TT4IaMNsvs4f5n zPe9A`9{ex867awD!VAuCpkiDGv=Y6$_67fT@wC=U{H@#m{{R1S7HCJ;%y2@Xk;PP%rZjXo!C{NWCuy|91J#*dP4cZ-X)mPf1>P?2okO->TiQJSEcI zu0KGr-N^_#>dEy_^Fbz$PG62r*FUcvEK5a7YC!%ymey>qT*_vAz@hm#Q$P@?d(!L5 z0Xn9Ve>;0XFKCoR`YX)03f;aOAWg1+KrTB_+SGcWM9la=_vf@uM(xr+udOUg|CF&B zA8>fh)P1bm_lxnRv`)d+1EoTip?}JGUxZYF>R9mhc7Ye}U=Da2iqP)={~KyQFo2HE zdefX(@E5cI3Ox4)8m)8%9lasc{DPy=0#sy_vIo3q@%#TDa@tt)8hJ~a;?i0-qSxPwh_qqOWeqr!hN)>eadWlPy@Bd!M`8JaL`wo^fH@{G5K5)|dc(HD` z@0aFN9M(6BgiBeiT|boZfZD{TKnDqlzGmfLf1mkA7oS_V>l=_a=XJXZ_;rT<=nVbw z?GQ&Pck6)?=I&A+ROZ_u#!@TLWkF0O9F3q$MjFaFS`U<}Ti-8J zeqmPe|9^MrkK+uW1OhrpjkWpo|JU5#4l!jhMDtHQ%zVGw6%@Tpod(|yF_j2?zx|pI zBEkxeaO2wzwJ*SF=m|ItfsU;O9VY_HhPI%|c?QsuO3<|Z|5A=p_Kb$P+ybwevKU@K z?=S!##TE8K^aiM!0#!t=pi~hS(|rmw8*6D>Lcu$9Wq6gDk6g+i2Oxz;K|uE~S*`xLZmysHqDoTN^Dwr`wfs9(PLt zEtq;;+Gq(n5DzQ>T0HPNrO^^}WFA-mG;;DfxY4qgf#CpH091Uwc51W)9kK@&02%q( zu+ef7Oa-V#{#v2Yaw`*53uveFYyL*dEg%8*<8CRS>Dd2eDOnuDHxj6TMr7K4%@BdPsfEWFsvG~Z?!=OottdtCf6mEeR^~?VM z&*FYD(UXB85|k7FWI1Fh#D~B5xC}HV+I^za_fG4{QfcJVzioUN7@CiOE+Tmu&BVa4 z7<6cTr|pu5d;+YX-N@D_iVf3_JF+lvHFN&&jO1uYRB7mPR8gt#a8yYW8iNASBkC&Kqa;cD2h2i%g_(7bh_SP zKG^B{Uny!s$qRBrtwNSV_zNRs=kvFMjuP$$OM|Xb|J_-8CF@^w zx9g4W&|JPSqvEq_!$^_-FO0CSndE7;ynM|IJ!e0 zbo)MW@2tJj?RvwZ)AdI4A(qb22d|qudA5T5&j=2^ZWb^H7Kot0LJ367z z)!gC#MW=wyFXC%H?$CG;B;D)&#rj~;!~bS4j=2B-->k+E*?f$p@!yJ6UV)k&@!(Ut z0s~=tq*z~^I|Vx1Bs_zKk%3`9NRjdF@Zb*FHEFy8|3!Cz5`t;XCq98r+lFLbf!1#& zEEaO5Ox@pmU4I0CYVqLUuotnQaF6}dd_)9%w~c+VYq#%@=AZwIZF@y#T3;+O3wm*H zF?4-ui6%^EFU$OZ@URyOAkCnKH6k9Jwgt(&0*iB!c?FCQykxz3F?3MDKyoTV#U|Cg{I zbN|oqn$fR0Rf3@b)Y?78z`)SO235iA_WCne6f^_?IT4Mc(+ZsKK|{R%8H_JE8J~R3 zR|96XI{s3}Z>FZv1 z#w?bA7jqVZV!qS1BAHhpGP3o5$tj2t!3}l{C3ayigf{*E-(Y7O*&D%FqLjrL{33fH z{G@J&u;73f(>8*$QR{(HkLKen%%Bi1JpnNz?8QSD&^|nnlNg%S8H^7cXRY|e2dW<# zBBSHu4*xd=S^Hu)SQUuL0NRKA1U$VM5b#1^BV@>+`He_(>KBIQ)E^Asesoy)e!pi9 zyZ13L{Qqx#yo9&)SPAF%3yY6T;1+nD*6aEu;J;`OC}+6-Fn0X{S|z`iNHv#`eTR=I}_XB8V*!PXG?;qn6*5^yvcltkb*!^0d^;{`W_d#AkcLs)o z4+OYRbn=4ET>E~plNV%9d>p7zVSK>h5Dx=rdO7^R=oXNbKa3Bw{x2yF>;9f*$zCD= zSuj-k14@4g4hRU){vL4gpIcaX0BB1NxI6=GR5cHH5xD@g#13?fyA~(}{+IphrsRd|Dqc}wjF-W31u1|h=v>$7Z$$n!&NSU{UG8scQ+g4vV-PhEY{zP zKE{LgFYNmPk_Qpkw%w4%E5KMPmhlI)1psuE zcLu1meW4DThX-Gw(e2A&e88IL=m*dq5iW=3AL2zHK^1#9%h4}BpnaR*wa}ou7{Jj8 zK0_Z|VuZce2kNDQ7Rd9rRD#x?XEDFnav0(a{uX{v&zSkeVvs=Vfl^+mQ}|mzt*OR; zAouXMfVQP&ObFu?$Pi&>V93~!#w+l`G#H#Vjch*a0q}d z!-+RO8~5V1DP&9pG?yIwqJ1sWToPzf3DlZ?!x9|W?aI@9fTz>-Pq!;a=>JlIZeM}! z+&?cYk1{ZXh5x@0AJ=_1w%b=AwEK1APtf*&Qr4ZI)v$pt#E&vC#70J+JjBD0#gQ=q z)a>h+1M0eg`cXxV7NAyQX;yQE0CQtx9ip~eakMG%9tu|h&X(Q?m*D__3EIx%%J}T5-+$T|Nn>1^}bd$K49U>!$0)^=njz=M`r*3|BX?ggumNC zqMHM}SDP{Le*nh||2dE;(J;_)1s`8%+5i84oGm7tQ=t1;Tl5SKov|mnYk9ie|8%UnbG(dLZD1Llmf8+v$4cMf>Uh|GOJN`z||OFTAJ(^FR%vPS-OpvQPj2-?;%K z_aXr#;VaPD0hWvXV|>7&(^UXe(1GTKpvP{9zgQX$PI{fLPda1&yadfJ{V#p<;t6Q` zCO9l4PlK0A%vb}OXbKhSuH|X0VgczIUv>c#4h% z1Oxe*SEXYaSpow+RrsV&}T|tMvFuVY-M?U`I@GQ`Jh&I!K~X@2-8) zTzi6{RI&AciR}L}i5He2qd|*-!AsvkSEfcrf-akTayW}+hi@5&zze;@3=A(`p8Ws6 zc?YQ7&QQYo!f7UGC;lIX7fWaU|Nr9bNszlZKy$C19UvtyzJx$4uUZ8L(AN19A@Jmi z4EUZsWj0Vg7HF>3VE}bQnZsW*|1Z^f@h}`zg_o-QH-ikrhrgJ?!NAb%#^R6x%02%} zH9FlnKtt{YJYWR^V8bT<1;w*YTgZxL#|B#4K*`B^O7YvFB#*`OA^f$ zG7P0cFPKk)HkUYdc7T(`K}gpOoZoFgeO1t4x`grVj@UaLvHu(E;pxQzlwKS-I$eJ> z|M*|SYVFQa!}>yQ25A2f2P9_rTS1o=fMSQgm6wr$0Tx4IjnEk4ZG^-Sf9pHYEKr;b ze=BH^^+n-{|Nkv#fFc}n+|`SO6aW8rL$X5XiU0qz7{iXa-eK%+0A~kRju%f4K-ZA6 zzL+!p|9^<}rP?5?OI2ak3c;-9gj!q5Wf><^%K9R6`v3ng{vHR}35v*)oEINJYu_6{ zoKDv_FCHBS&Gx(r>zn}+c`*w#q8!fEnjo zbi4lO41LoZ^`SHNN_Q-erPBxge$ZlOYo{;#{h%gew^e8Dm+q=Rt^Ye~A9UAB@b`fV zhHl?4-EK174m`a9EZq#RmH(H?bTb76f(omZkOSIU50q+kyT0fSec}NcH#)@9>H4BG z^hxW1`pey}51J1Ocy#)H>2!V2dZ2#mYxV!7caFLKXZ&BP0?r#({+C|(U-~5+JT=4- z9QI-_Xe#T7PIu^=ZqNmr9~?m!^7?-041ELgOcQ8JJ7~N|hM|Nji!toQrk|jKw4wGt zLuq9m* z*Qzjp?h1euETuL7OL<;bb-M~!#`BcPTg1wg8pE9Y1LW8M@U@SnprP+03NH>Fg(n@> z7cx`-!}gE8@R$ltt1r00&g^xSIPNNu63!_Q(Cd5TMWx06{~0Q&+ycF>M~=H50aZ2u zFE)TSFO{miI2ru^f7XAHRsTzQUbKMc#05Y*8Df4z3Yow_(CAd7Ju?GC1Ahw>s09`F z!t&_<|J|_?%{xF*$57${I-pdgi9?|K!wWf(8#jQ&OAH(Bef^yulxQ~E2RS=GC{cuX zEf^dLpmDPB7l#8u1q^6jxfL{A-(1bZP|6D4PX_8@f;x=J{Y&fr65;MJmhKp)FWsSk8mc)M zx??3uExPMinvZ{AKHgo+@r}WuR3i(NK6?GW{4Z4q%wh;YcG%ospuxgF%|~>)eSdVj z$~ZP36Y2E*VSTEoH!eCJ)ItZf%>zLvXYho#ek;i{zTN%XQm!tx`*de4=rW0J2Y6}* zjas_?X+2P9+U?5mzd)wjjpe@)^TB`@=RxZoe0jh-14_lZL8IP3JV3oh*FT-1KUxpe zpMTA?nbE!Zpg^ZDkF{ORiuky$!{Bl27jmHULjx!O|9|Gin!})C)v^QB$OAP-Kz(NL z1w3KhjNOGS%!gXPRq%Fua&(J`b@OmBpJP427rmg1k0S&A zmq~=bc4n{7&>mmN)oU+$CxMn&@?>zNatpk;KMB-s=msq# zVF8VI&SPX?u!!Vp+a zYOHX8c&!IY_`k8SK!(JfJ7b@`W__`70zC4%55MMvUbXPz(ge^th8Ou0A?;gen*fs4 z8!fI6{hvh>Ld zNff_vgIo#r8)*Mqa9H?@pZh`10xebv<=72sTkZ#SIxIJU8b+mxmQp3MjaF(53=Jis z-HhPM#`<^>*EdH6M*h~xpp#9USkg)qEel!rTR`LRmZdVK^;!P|!R0E?i~avV$w=UJ zj%6WFsW8+4NNp8qStwHyVkuQ>(p)9LT%>1NB~qr@?IhD(z|s1xM84Zq1vE4Ut}$gG z#(|3Ip#RsJk0`vBhlu|#RY8(^VFRA3RDi6#hD>pEmvV%6gYSa~?DgPiuw*Fl{KnSM zUCUF#`i)(n)TTR}#rjZ*NUsw|K;R3RxuBZ0^#JG;rq?Rp*qKULzp-(YeCl=;_{P8p z;xLvx{l)+mW&&O6=>S^#(0ZVhEsg*Ef!Bg*{CNk`_!ADK@h2Wg<1aYC5FFTjv-vT9 z>+RBt?pw`|>JPqVFEL2tuV+l-uXhvx5egszB;@D-Vg-PR1Q1cs+X?u92cx5R z>92_B!{2W=9~RKQ9MpZe`4L3itMu2w*9aZnrQf1n#{CC(_&}3J(2muA(5e;CVfWx; zvJm$fi8TL6Es1ab;aU>a{3ESY5*!f{2-T0kZGMs1!_7YuOXQk=IF>+^K#T=NA!q`# zmYsp&wEk}o+y^jB~ z7{UX3~&+xN)34NBn6u8gj@gfPdWJSWW&P;4F?N4IF30mGZ_DW=?~uc*a#}( z8@LabfDHtV)^^8Apc?u8c842dw-<}_?dHc18XtnLhig8pZhV0IU}x-yQgx7GH>T!e z%-v2b-CU}mEAhBbfKEH;bp7#K;JE7#(2aAi*^jv~8G;m@bL;f|0-B*X#>fCV@$gD_ z11O7kGjuU@Fm^k!fDPz$eNoQYY{kIe23ic)oGQYwlYxPsq1*Kj=qkPcb-~?C-9aqM zt|H18yM6yOJ_1?FzyIWm2iqAKvJ4{Am=E%AKhXTcvW$uOFzCLUP>v2Zw{BMv{xv69 zI$cG&UH=?>$>dZ2P;TI+#|a2)1#Y-eCdYyQDeW|n2p>-Imoi=*LZ zS_x~zPq$Lm4hfIf@4I6^Si62H5dle9ma;b-w(5|0&H3+O2ghsXe-8g!|JMnCl2$<2 zi@gD$!i$Ibd$;SC1`CE#rtS}*P~T|M9m)ZV#exntutQ!5Y-eETKGA*4_(0=BP*PF8 zq3!!a`bGtRJ&W~;BFM}kZGEFgx}LT9XG)PsKvqg{;EVm(l*oaU za21IMWN`%tzLtFi;Qe2rTCb^!k1X4*y@O@WK!@coxgidb@he!H zzyANw0V|L}qC;|0B!d{#O4QPNio0gXK`Y~D7ij*)PV{`2emFRZjX|OOT z(d`am@v3C|ehU;)St-%hmuon>56%4ko577Kiwl{{%n-)%jde#JuK;6QiAaN`K`DP0 zbFU*~K;VnTir|!kdeqTz$QJ8x5O^Uy6Vjz=exrjJC5A4a0UeqF8cWF%iwg_v^}Q1K zzkubx!3(?1pwSeO*8imfFTRC?_By;c3L1Gh_PV6IRG{@+Dc6hp;h+eJd;O&Odknrp9sLR9;N@qyOc{PPcJpXhbH5&$}zCD8aJMDie1iupXKClI$0WDjWd0qZe# z22f!v)9ZRAive`X2B^XC6+93l1K(@AOaU^83LZTX>2?+A^?d_cK_t`dz~a&A`sW3Q zF?f6gbW$idp@_UN2fH)6Q{n~ljQ{^%f)<$?-v+IPw1|}`k?QvSV|~6GYu{9NBe zMk1#WP|?y2(pjknvWupg0tXZ>aqN z&M9A-6AS(#ud~1sbC6hz4n~T#4sd8fV$C7!|Nl;j7yQ%z|L;EhItR4pxb<79zzYqC z`1fgG@nA^g@fsiKMnqnBtOzLDx?OKD9|q-;+AF$&poD%r;KjQ2DDfrozf=MeU!cfJ z2RFbZ;y|$ly4v=q98zQ%U?e>x4_tsIyW<-`#)CW{{GvV->;XTpLticjosR%XdcrSK zAX3H~Q|~zf`8z^+FctbRm(j z@E6VC1S#=a5=k6XgoTB_@ca#mL>ajEf62nV4=U(5UVye)gU%cSCtlD%Bl!HXFauCe zl%u=$Ll;-e$r91-c38z{b)tmb2_#thwTsEA#}@XeHYVCs3K`3+nTCGD7dPgO=&&UhVb$ z5C$4%$<_yFPX2vt0WTDpK$i@pzUFb`-^LaIE@WB{M3#O8OR_M5C#ot+nVXL>b-RA( z;zP+-U2GkET_?KO+*%HlevY$n{e$j3(4~p*?nr=d1+4vPfxRqtVF53qWkAs<5EmbNI4pyKftewLfq{|1_*>YE1K>o@(|VwkDef@je5Vtj z5r{D3Z~wP7fKPM>4FYwxf!NK*SepN76g>kkJ7|6*(d+vHRE6=p$kPLj9dUrq7PY=# zoY3w2qPen!u}%bZa3E+Jcr~~u{sOcVju&z?3IBGMh~@{3tp`fv8fw2VbT@*ANBOt$ zNPztNp&1mN2VY(Soe5a`1zc`?0F@ivhhOdkcgJ5eSClZ;>2@FP^?h;h2S=wXMmV*eg<{l^gbTJ!}+5NK4z@i>DP0|P@x?4M(>ur6bQOyD*XQj*rA6nW>kPOl?v!yU<=nT{4Ld>nMYT!`@nPVptYvL zAP?|wbNx}G+U*N==4%=LZJ|H-x4Hg2_=to10!SXzNC3-qAA;0hpqv6(Vpa;ele5=x zfAbH?a^~iP3f%`|4}%gh$BU`|Kn+^>J=37MG!PE$eiI%R-0dsCeX_(CH0@E#v)yrX z)Ha1)Plhfvt|wjWCF)!UN|c+AF*YA(w0d5|X7#w7iRqcu@gg>>!{tm&$E+TdayP$Z zEWK!a(&|A8=g$BC|Nk#y`hK(fV02vkNl=#-8oi)Oa)J&xc6*%}Z9(%2<@}%_TW}8@ z6p63%Fe1TXJ;>Qek?^A<_UAFzUks72xr|SC#Qr$u`jf%2+w}!F*g>O$fuQWz3la!; zkqi!UnbrfP0v4`cO4z$0!EJm1vmUB@2fBTE z__v=_J_s#ZFk2Z{Aftt#o7!C8bi0alx;}Z4pbfe*@QU&O08kSp43q~zW9%>Hftt2A znvW=SyFP&|IepQ|@xSy9SdxDeXawrpVdhdk&?TV4pk+ydSuC%4z8z*P{SG=wpE-*; z9<{mY`v=tG1XV{_67cf4`HcpmIs&_{*Y^f!`%QN($BUy{AgA3hz8wIXszo@Bc{^x} zGRP(20WXBsfSTaVM>M)!->d++=O<%{VDnF=QvNKK*IX+YOMk3jDq+rIj&7)Z0?wKb zz**DxPxs+?@L863#Nn<1rDIrOyc=AHLJDJ0^nki8)(82U+QG-m{IDu!=ih!n`(W(h zT>_x{!L1MRH-iqL*_FV?z>sErh`$NM>-FLS#UWVfq1eN_KENbFGx`w8qQ|?^IH6iV zdr6_9XL|$7z{Y@v1)*X)VPc^1BBm>B55S*X}Vm>6iY3Pg;*sq+8-|GUz7pf()@ zO{ahz$KMqH|NnoO4$vkXm=1R&anKAaOdNEy+^zsVut`PLFi}ak>Y{X*7%ON4&Y^%b z>qAAs%?AV0K;ifC-~a!+90VY`ZDA^JgG3*QLqyeKqDMh-aL53pU%2_8!E4r?QsA&Y z$lnCo)Yg3Bf9&BiVcjm^osk;dJ}RKSo;>hc7_pSppHAt^&`d%u~846nR9sc49Xz$g9$mU=FOFgn2BhsvomxEjuRi>6D+3P+ZWLudW zXo{hhr}-Vz3XanF*8iXt)EvgQ!F_=&$;e*!`TX0jr&)v6XuncuK6Dba=EC)l^~K^- z-L*eJ*EqZWvA$m;;Mt(0c4{*FT_3?m;WE`BpGNMxPrGgBEtTf{q9@ zU%^zu^!;``QeObMwBP}yRA|$!@eSxUB}B0X>fljyj~nRjknr<0c2v-wL`V3+W!Wr>OV1ZEHvfN4m!iWLWkA zPX29sEE+)TSdMpsuS$X3BXsZu3*_pq<{upVEvrGxGLY_c^STDP(+w1;|3P=Ufv%Q= zg(&E*7idU>ucLun2{&}^bOU(`<4!k_Am}h4PzXb=5aREI-023A`47F*4a7#e(+$KO zMt8b_5)5diJ|se+H#~vwbhBIvZT_L(=>|%kFP_f)|Gyi2gB$ElH;^#mPB&l7JKaDE zUaW--I8kz^8z^0Zj=_Lr7sw?*kW0$&-{}U5Ina?qFF~acxsY94Rm83$f>lx(+yOj1iY9P2I}R2h7RP9gG)k?)hKtmfz*KnA;Cq$oo+CXT>SA8 zcBdOi=q2)oo*oYG`-UeWC19q2;b=j3Utsizd?4V z8^{AB-{}U{gmkAH$ZwE4-6nnc{~vs(TMsBY!54<1-RTC>i}Ox5kU`k)bOVVKzS9k) zs(CLc)iY4*PB)N|`0sSnn*uu54%G4j-{}Urey|sOi5dExZie6ksPWzD_85F7vp_TW z&RGV?6`gqRbOQx4{7$!JfzUFq)E;rC8`wGEq9Fis#au7qPPYZ1Wi{X^0xekT1sR6r zPB*X#C>{!Xkp^}s!8_fA!O8@>!MeM_cL+o7bUP^w>exg=+Ilc)P}`#mey1C#ifp;W z-^%k16uh9ix%EJaRPzt^644ie_MjFyc<1UJ&{5qd{=a6zfA5<#2c!c(A^RMgK=Bzi zf#qk|1b&@i6Yx08CJ=g-O@~^X#q_$YKiU=C}40Db;?F zpAXynQ3@J>(d%}VfNb*tEm#%#Z~h`g4>T;v^O`^Kg-ijM*?OSlYA5?eHSp4dSkO3B za91n`|F**cFE%*+|KECmf8XKAQnuy?_nTj^M}rk~`*QsEWU1ilX5`-{;LyqVnltc) ziVmo8exdsiSViL-)J+84z9Pn#x?MRyr$+E}-|Fm@0G*cJTLU^)y)_3!_WFQtpah+I z4H|RkoC-Sdx^pV%?Agw#As`h~WkBTI1Q0nDbR2r?|5Aw;%WdHyT~r6YChz5L0Z^q= z@&t7Mb69CnzzYruklRk|16}cq)FHsU1)8b*+BYYa`cgF{RhZodrtWj!990@hBwlDC zEdL5RkNd>`m$m|+<7WhVdqJ!DU!0Km|G$gf_?z*`j=7Z}hi@$alPMsw7j(!v=uX`) z{0t1>q1364;G?EWy!?7w!AiD*$nLG65DE);@rfTaUW$Q zL}Tg4Zm^C{ur)7@`573x*t1k4tq$_H?&o7*u<&Q(Z&|~~z+il7J7ecm@FBjRI;Mh- z!s)uzITdt-ZRb?bd9@u=qd}VyrbdCuDlnM^CaXa%p9(rA24r(*E9ewsu-ls*Aa2j? z?gfcK&JoT&#?@PRf%!vME69wlUXbpV+a*Uj_GbV4|Gyg&nOjRhY_O9%_ks@R1ueq` zorcs6J{TWz`hN2P7RWjI-2s0(r-E#F2^w7N20NhnhaY5BY{|6dA6g|f%|F~qdYXTD zmIyTe@ZoO-P3inQ{<8f4|NmX?j5cPa%Dw(f4VEUQ(%nD*gHMESUJ6QR49!bHDUIPJ z=-d_?<5GUGGNV%V?w>EM{{R1PlfvI(1fnxbDs1xkTR^uG*i`Vh$brNnO4VPAf@}bL z_1}RGF#VDPGg= z6?FH}S;~Pj+;@N#q%6J8p!sKJiEQ)FJpR_TtPBhddqGKu zq5Bwr%Q|ibhL;DK85pus;yd?(yz_Dy8v}#!w`R~@{_a*#5#rV%@tU>yw|1#k_g+w5 z^Md%G6YL`Q7j|H`LtGgN@xp61h|1OjrR>eUAcy}4mwuaUL7PRu0<8y1vbqm?cEUKZ z5WD_^&#vx}Ve4%Ll~w`0t)K$UEua_dl7QY;P-zwbxp=7g2xyB@%WZB328fH?Uu*&` zj=cf03*wL$4j>y}cXxw#0wGONwSqFE)nWeD2cU@TWtRSf1TG2_A#>86G-#AAJ}NH*B@{pyuSS> zXeS+#*IjKO9oW*|X7GvS4E!z0pv4=%Q%g9Tf4lOxhJuC|(Otve0=^Ui9NfoP*is4j z^WYCqjR$s2Fp^`mz>a|gRwO7XSwj3sIARMB1~PGh&b$F7JOhkCE9FpZ1*NOkqOiEy z4!REE1~dVJg5iaWHC4j<9{50SuonwB5#j9)whv?x#G5a!TEW8GzZ0BKI`@LAn&#jC zOZXs;41U463{=6u<3oWHo*7G_Aq1)A{)2A|351mU0moR_82In%G=#rL1mz4Cz#XO3-f>o%mW@vK^}mr1(z3)L+Kex#33aV`1)s1%(NchZ@CLP zV-H*&IwG6+g8MrttwO>LQrz`|4t4sUT;kUJzqnMm`8Q_`XY+4f{=QO>_-}<$z2^Vb z{H^KCpnA6Z@WCI<-KU!$vO8UV#J|sn^$!0&aON~V(Rz`;#R;?_08+y7w`zhpAP+L| zw{SBC*F7fGPIxjI@EL3Inb2ssYEg2Wzl z2P~va`Cm}d3%+k8pcgC^@S=1n14B2sI&D58kOsN4B(0OF`4AJdlAQ)xRd}!&bif)r z$a^oC`CD@TL2d>A3z~EX2}psm>I>!)L;h{-)`$69K`SXCQT*=&wEX68%J z;QkV{tlQm2w=}-xQb}|df5Xq%k`Q-DE5hnxF-zCO*DPI+x-ME>DOT$`!oTg4)*=3F zKf14VpF8-9x%nac2F6PdI9x>UxcQg9>ISDw{%vPAFm_*Te#n0C6*ENA=+bL>(0yNhY#YV+>BpcY^AZv+0;CyWdXZs92PZ`Bv11ljPr0&>({!|w?G7SKBI zZg53>99%bnMnal@R+RX_5Sf0N z|Ns4vT>~mH_``!=+*t_8YoJ;=%ODz(U0&*7x_-~+|No(`>4uenB~sns0@pcMe%hF*t+1Ek6Mn$ZoCuU~3{W^BOOzymoqfZPQy$?PGH0~=xefxjh` z1zwc#w`TnYZR7{F#hd>p^S4C*{{O#WFE|rIQbY+C_^_v!9>4$pKgPiD(g8$+%Qw(r z_@Fk`Z{1SVn6-e$Y$<57EXxMQ*Se7WirS9a1UiNg76g!3>jKA0^IlNd1Y-8Uj3rb5yHq>Bxd zJ_Jn#5Qmj;KvHH&8n&Qn{|Ii2ff5(!>J(5P@a1bzc>=Z(BSDHm%m{wrHXoEKK`lJ6 zROmO;A`wfVDUh+f3{uL->e^!*(gTmel95ORNs{+9` zgTsCqNX7sBQW0?2gYMMsZUuF%4nAOhZJ7;ba=kVH>*O*4hiOT{!KEM-EWs~&J|Myk zq79nWAmP@0-~#huctC;lzym4);z`sr754!%pzJ`|2kczj0VO*RC7{5Lh6Ygy2PjNH zRyV(Q`+i^gzcRRm2HEuwFWpssz;Y2J*FgLNP01xPkbW98U2s6sQKtvX%g^6I-5XG2 zq2(l`0a3!<$@ucl_y7OXIvHPH`TqaE)xlCW3xCE^Mt5u;&V3Im4EeXQyF-#&r1jy_ zG;mnQ_dvp00ix}NGw8xM{%!p3)+b6e(2B59?go3+QpbjR#=KJNE_P6!%l`2H|7(3n z-y7ED{yqm3N}!@eEbKKmh=vz2cOX)GK^+0cQl9@?L7kBoO^o2^02eMN{#)ND1x?&? zSoDJ0J0;)|A<&(23?*FMz2M1L@H$Q3Kk=XiCY;~?floaQ?S2DVQ^End?~3h3?K_Zv zLG6$dKK^Z|179Q>g1uS#05qu!9((~UMr*eDdSD*607I#8*o#8Y`46BwBeMiw95Mg@ zKk~l`Sn|K}yZ;4u%eUSx5pS+%VJs00hMbHO{9-S||NqVE43W*p zIU4_iPV26@5e+(uk*~Rqg|U?5zZpbf^D&Obe_-iH@!)$g6F_^>fv1$m$iVkSpHuKq8& zq>)1av1|;qd(f4`_)>6Kc(;cQ^9la#jw1ZqBiWh{NH8C4y2~GNWnf?s2*?1D zFM>b=6h}Z6l~uQc%E1@%-!C*jV1#ba>h}GR(#Z?jDi{emjq_>j;cnMA-3-Pj8!cEF z7!L4HIoN#=w6_bY-1q>d29WE|fUe2}tq${zVqi$KGhhF^~P)#=;rS9;AyUA zVJJNVzQnlOnd60069dCeP~!>2F==98c)cN|AGETSq4|hJd|dS5ZXXqv?~W{>Dasun zbtT52WjNg)9L6VJ1bq7UKeRhT;(r0p{{n&k1tKp%C2;c*o>;J&5EX$=CeXTXhQp!V zJ}MmDn*R%B{ufI8FVuJe8bAUmJjB8f8WtYh{mS@&@onQv#@~$p|GyXw+OpOCs{3R2 z!7RoX^^FV+VA+$#myG}ae+Dil!m}8HGN!#@69{}E@{EB2oQ^`fb5uBj0{@q&h`a#b znQ(+B_7DeTagRvrfjaI0(2B!rIiR8qyiHgFBmgRHN;zK4H3kjYOT-@jZ|aZ-I*kR? zkpm49ce`>dw#efZSZo6#Kyr&+@^}Se4`-=lEC6Nvs0h&U3s)GLQ!g-pPS$t;I%f=Y zsz&oa?)rcd(e7heOp)3LOO&(^mT+hvEQ!-TSnBb@uH*mz?jN1CH(LLfih+(tN&?-N z>-q#_)j|;QI_`gYOxTM+@FsD{tJufw{JHNW65F>8LoR-)`tBJ^T{I;hY955Pxf z{Qv)Y%W>ByAV)3)5wE3=yFLNAdm)H;&2!xK3CQgWL4@&b=g!y%0sloo9_@6!)BJ-G za{e=Dcqohcg^}_9|E;%6IIQ@E6wQ% z49)*IO6|MdQ#xHQ9CuFv??wH`QL5X``@)A)p!;HH=$VCYd^iP|4_aTSRmncZ)9oJ9 zoWjAu;M5s<2BPToJ@}?@-zS~0Z23Y0l%4-^lq&o$PYL@UdMEO=6lhUu?1S#w8&KE9 z{{H_z@-SEu)qR59u2(wU6F_cb>vp}+>7HVI;Kj!<=kCEivQP3b`|?;{EatQw549L_D>dbTxaP6YtxiZd;+z>;G^8SSvIsDC~^7bz|&kJ5b$CKsM!gs za9P|tYo9d#6RFXJDQiBU5CExbz#{)mHoQ>$_3wWqnAfbbfx+$dB4|nU0({lb@fVUH ze|6V_oZthBE@;vPEiQhMqY6(W=AhGjKnwA@9Y9G~AmahZ1Jgr6`=~oX_bzfY|NB=e z{(@B%yoK_KEs&6h9EQ}@GVJ|`$KvNb!Uh};; zrUG&$$gbw||2u1+z&r?=9`8Q>S_2gCwNJuc#LZ%0h&=ovSq1FE32vs2t*G$IW!e1oL0J;A>CguOVc47v#&G%*IM@4!h2l;*y<@idnxd~@UBD3SVK#__`8$G`uL zX*}P5L+0byI^8%r-B>_d?*%d#(zpd)d6Qk|;R?W7lEJzcZ3I74ALBfh?wl?EPc`$2igEC)|du%XJ;HsXBa%-;-}Ga-nWhbgr1ItAv^KHUc`Zlt0O$!KVFNy_@)T6 z_r-RI0r=B(8z_q$e$lN6cJ&T~?&c&&x;6`fr0X3Yq!<`pJU0FRAJP~&+UfeId8y0O z|NlX!(}Rwg2i@yv@$~=yaO3}-y#`PJ|L@%D@bv$G%TfW*PSTgWpy9`prSdQ2761QN zG}CNUEc(rbk)?sZ z#fX`K;l-T>(9Vl)haAfe@Yae}iKqYn2Xuoq@lQF}*=zF@v?>hbV5si@CXD|@J;2$S zzvUeh1B2yOkeU*XmfQR-_dvIQi28sIwVMhGI^&ayy&yMrwhDj(veyJePSpVgr>_8i zTO%6-Lw75PYkaA5DkzkXw~9Rd{~uIpDeeUs+j5(~bsZxELzjT@0f;9WesO`$YXmzK z;!dc;I$J>+ENd7oN@TiR7)?4{zjT9zIzqo@F)7wCT7b?Jd>zHV?@+*tj5=@zE^+B@ z1-Y{u>?Z9)%%D}ljQnl4K}S|F1@*Rq931c>Ya%FodBB%!v4R5?)qfq+uaLF*vuax;a~|)I{ZDJph(*bis%w=h=ILe znJk6?&~}S2$6UYgLX!YAXiqe$-@o589`~9 zsnnQ%JBRV5H0xeatagGG@J~6^d;m0V3`$twI0p?QgM$N-1mK#z17BR745}c&`as)7 zN}G={S%T9=iBcACL_jAveqO9cRpsyYAMB!Tu<4NWWgRNO-?Z}Y|Nk$+2SLvTWeT@0 zrtYcWl+6RKd^=pYOrSOFaTg{FP=oy?XiEaL&ie6^3pBd~&Kli3;GERm3ex_~g#(nI zK;!z|kW~M_b1x|2fD$hsNKdRl=TuODfsT3yO$!*G?A`n2_5c6fhaeeD8=MHO4;Q<1 zaXC43^vXZ||G(iU7erGxI1iR`Lp*hio!8y5Ybr=Zhq!w;*jPu1DUCn>3o|ej?SRE8 z$Oi2ny{!sQK^KMug!i_BMDWC{@c;k+nYV(JTkZvsHDVC+yAQz}$lv4$9wq|$4wAT9 zzwx(z1s%KipTA`dD56ld)!P;AV<-Lm-rQ}aQlH0!;f zG*v3l432B2v`*vZ!%WSfYdfr)4>2_#W@`NP4-_0HAl`-q5hQ4|Z)7n*f+ZjrB8wwX zpt%SfnV_5nI^zWrK+rm2E-0Azdq5jKAkox)5RwG64_Uhk@HgrG|NsBxWzZ00tUxC? z3xkqC7pS)aFX&)CZuJ1=2yn*IJ_Yf!_32`3{_WpqpDVLU|b&0(*NwR%jobseS0;kAUuj z0bv<0|1vQA2jAs~>{mqT!|)eWKXmqj3c4%??Ss8jK|T%&=xqfV%zO|Mpg4lB^+1VS zH&`okFGw4t7=jpPeXxH0Ybj{f0;}o%0hQkiN?oA)pk{%lMZlrf{Sg|hpCAEm{h7b% z$iM&pUzYy`rERFIKn;nlpyK?$3CDj?SaE0z8u|yPYUBSe-T#8_QZASL|3C7z4a7`n zL5f~OI+SoWSV@5wNXfiNmjtC`8PJKT8j|4lO!JBVuUWJ|b{~VEwORiNJ`&gbM#K0( zr|XYS*FTo55qZ1fOHtUPrPQ`dEhRCK)0*NF3`AenDrt4{yE_LNSZ-| z_&+51`#~F@Ah$zhF-2(~;%~VHx+sdjkVcG28QFVcdj^b3V;p_DiyfP(Cx}|H}=6@hF;ejcVl1NWed0)`{DmZ&vN1-S0xt~Ws2iE$e8ayckr!>t8reBFNB_0An9PJx%8 zQx-ZyZ@{=Y|3Swb-MImhvSwspfJlM4fet6#S@zmO_P^C$`TDDm(p(Qkes!r#IQ z3ZfUBC8EtQnE6{l<@9maJAXh1flkgl?s|vCnN#59GfcnVl>^`M1r3pxpj+IIyWRjD z#r5(UD37`d+HnB}bqO5LQA&zkv=M_fg?*c-X+-8qCPRaP#Af^~wwk4L=!6 znQlI4wsipwRr9x6sxUD0@d_y7Oh8=!56prf(sL9QsV zeUSzVo*Wha18>>CyQqkR&T%RcyRBPrfm5L6YzfoN2Rp!->eIjf|8Kr)Im_Q7sLa4{ z^TA6lWd?@3H*UUo$q3>fd;vNP>E?r$ll-lqtNQNVxO?Nau0bWI0K_?)LD~=8{Bz^x zMuyql39RFWNo- z|BsApJy56H{DY}Z3Uuj!@?BSsV6c)b?iaJbM`j4TE({BPVF58NGV*ouU005~tR2~0 z0>RC11a2I>8>7N;S4Jg^JB#DB{R`h23=DTef82HDXgfpeweXbk}k; z|NmDi@Zy*dC}V?~S}#HOGqnEa?*JbJ3cmhp zVFnF3l@x`)nAHNhSGn{L=u%!-Uy+%Gu|y;Mg-tsHLu9~z(VPa*wZEkt(3<;0XX%sH zZzU2h1ckr{w%Ebl(R}WIXDRA9)Unr!-L)LurBA|NTmu<*_ys>)`HNeibGlFbf6?m% z>8OKF!fgFtD*EEJAjoUrUhuY{|NmctuA1p~=ULGVxy)~c1Apra1_p)|OeNgSClor} zd0yTGl}0BRJKcF!@-Q+mlyZi@xTMIy5c!%FbQCiC|8j}{QhB{KebXpi!tF|4R(QUp$1c|COkOg}=B0YQ%pCKlqRJ z#mU$I|2IF7k39H*jTv&?Mr7P;)*YbL#9a<7Dor*`rRZ!|#b$HTfy1;VrbMH>I_^nKA; z`=GP*hV{Wx@fSHD11w(5gd6bEpB=QAjK9Nxoq@rc6*Mr*->d=}W;xM)gc%1?jI&tw`^FNki<}8-DuovI#|NrlF{Q%k@E&bv&A1F9LGoLSdz)a9So|k28 z3=CO}py8qar5rC?wN2TM3R*xcM-f*Swbu1`Fye-z8~f>w%i zmGWkBfvyGYV0*b5beIZX_Yb$%72vRN2M_Q359nqAy9&t{uyOg;1En?1wQm?o%DO|p zK$U%SkznyCQO@Fu$l|qd{a?!3!RGc_?HC)cTQ?8boG#b@9WIiruZ65jKa@&laYcYs z33jl#W${K@*FNEIa{2%N|7-6o#;pHYp!-!{l!He7LP3cUqPXN*7H?z+pWEw;-JxHg z%wsUaT_jmnIFxemFm<>{vb<*PVuv1z_D}mqL#;3)e=Ddr(E6Xh0(=g2coqY+ zbFKp#P5lA#qA#dF?E1y{r1d}ksRx<=Llb7FkAwjz*~GrEcI7Ey4|rj8|KI<}=HLHH zK<7gqf0+kbfC)Mdud=)JL-+BS-T$-?b)UQVqgTY;`d4vi7VmLa0VxIshIsz%jA_=c z0wu<2*2hb@L3gGe0}ZvjmhE-=XMLhrtoa~Q7FR@?C1VLIX!I=}qQd%A(J|2JiLiXq z;3L5TIzOrVpZ1UD=l@=&fR_B6ED`GV{gA~Km1Zf}9r^`JioekdO7RasDLx)F`pO## zbyoKe{_X4_ck#EVf#&|L50;M1eAG!Rkmw$m88!xYcr~|L1UdV#vEnavb zbcljlt0!PbrDq9bG=Lf@r4}H4$c>c8?EgUr#RKfqJs;bAX$Y8V*0e?&I_|6j`gLIbXY z`}ph1;BHxmMh<~q*B@Do0iYT>{QqUp?W3TJS6o5Ivju|opn}9o`5|!=@Zu=j|NoJ% z<(fffZpni5{4f3Uzw}4=|I05|Rv6mI>mhO933g#tqtl+#NO#Hy%GMRy&4=r zJrE5qb|B1X2HgsLt^3#uQ!_{u1qOm9ki)}XWK}URG@t(;X??s@@I@P3NB8mW>#tq@ zmx}cI{s@FPG2p)_D8gC~AmYQ66%-$raR&B}?$AGw;0B#}1v$Fj_+)su?Vdbdf$oc0 z3Z1@xI(>gcyapXMmuAUU@`Han8|Xw~{pKG3VB#-6vVejD6tge(xPoT3U%D|d zFzjYzW?*>D(|xn~JmYJQ-Qb(w&oeb2V=_MJ$iJN}4b+P{4jzc(0re(8N4v9wh897m z&<6AOgD!$BDQkYAz~Ax^6!0&&OM*N~oSR=rl;}3U;3|=Ae!)`OV(I#azjZfw2o1DH zlcD*vz{^bx3=EB@L7jc@$%x+$JMg!H*0DC9c6d1rtn>$H7~>`AD8X-snM&)MAOCB9 z{-^mgQ{#D%uGb~awSO2&GhpX}pH_IC)chi(B%t{PUx~FxiFWe~?h?u77i|2kjQ{`t z|9+U^00Tp*W#efE2L^`M=B<}Xb)6cY|KI=r|7)$*OQi}M37#UDpX?!5fl8wLh(cl07Ga48ndq`b* zg8!Ft1iUZ+o&EyeKh}B)+)xnt&pHQm$=}IN50*}jP7jVw4;j$qsuet)9s4)Y6Oc0f&cR(vOAX|W&-$=aJ?F!l+ToRtKB7##OV}>)Qz<<#n4IBai z|3yte7q^{gJqbG7>Hq8CZdaM+RM7o!e;7a~Q@bj3x_$tk-1Y->QrrJhiQ}%|B~6e_ z`M;Fo|HapG-L5j+t_oS;!&@OoNJ7@6{TEFEnf^5PaF$5M0Z@7O-Vi*M;rpc1_kr<& z?ox@?Z~Rjav>qrGe$l}QK32BV;6;ej|Nq^`UdJ@^{Wm^f>B<3CQF71HSEhu&+f_uh z{@;J_J(dn7r#gNAfEU7vz}*uD>WsVy1?8$EGNAQo@Zk?pa1mO<+|2jC`}m7hhTvrw z65tz*9x#-sw*D`X?B?q}c<=`+WWfNmW!I3x!Se6F*^3orpyCa5FyR}EVB_1zT~C0z zd*56|8p1ncA9Te2>x?~9!r2*n;h5`xf!AEeT`zz#Vn^(Mu!A0VLe>McGJ`s{z9Kt7 zxuo?(so?j63=ZrJrL2~&4@y`XeE&CeAKb;jz;K}X0kigD(0IF+M~U(aa|Tdd4LahB zH6VCcOe5qcP&pRd-IR~rOGcB z`~$hVng9QbQ~&<`Kh6MJ?Dt~-zkmO`8R8%ZS^h8m09txn`XUUnyT8}rl6^h>Ayt>tFs>P&LPCluvbrzG*%p(ERg%spN}qfByY%v;a-dl?4Ace=+~Y|Nk#P z|NH+RwAkWKXY8GT|K=|o-hzgCLC3wyq&3&xkt!AaU;5^M>6QQHFY;Qz)e2~_c z3nEH6kGcM1dd=Js`wx=s`CC9Un4Ph2z8!MlZ=C=t7hHer1eGVs2W>$m0e=f<=?I9~ zP!er@kiRvD5i&-W0_yKEMOuI4Zv$N_+We2DjIa40E93^Gmu`#<41r*O+kFECk^uK1 z{uWT*4iXre-w=Vp-vXLP$YKWH3u^x2HE2lo2xQq#GiZX(_e~a4l=UId`5Vmqt)Q#O z8h^guy`KT>7si)&KnQ@KuJr%^e~5qbzC!&| zA_?(JERsp3fiKU4CbyX)`S-d0>;CLf!sAhDd))O6$m-X;S>#49b_!20Od>Yico0r@(fzMWHEyZmoU&m^Zno*$}*s$$q3d5 zI{5S7f2?+aYf1AL!g&k~kuPV0_U?;!p8}2ELOlu|uk2*u>OTDP;jjPyK_{#Rzo@c; z98eFsmx|+mDWXI2;xyQ9$bA6dLsUT5@RmqtJuto$@%$j2<$Jx%DVPJSI9PlC$v{vFnWb3z*&Bxj9 z-eq8DKF0Bysr!5Dw~|G{pacLqxw{uMZgm87_?bd@xMi(GDNA_xYc@z!W&IBe2UTQ{ zr7J(eUd*or1^V&c)Hk4(t?wV>voGEqKw6L?@V}I!*Z0GV7|?1Q&;jxv;H|}g7vDe) z?js_gQ_DfeLH__BoBI^p2o5toxeqkt+RMT>Q~OYND96Pg+9F4HL~sg}2!qa>>Mi*H znz`45(fVB7o#qq&A*x+^2H!+hB3#MZ z8wWC?j?wye-33q=p1qsp>z#N`P!k>OgoPrH_ymkuLHl<~q>WDo1_pxLorn|*Y6@S7 zJ&Y;(0#x>ZX6=47g0>w&8vDUv;jITsqQTKq5@HLw%)G=GbZ$iG`)^8Oy z0Wbdl122)RFzl8&x+j8DAS*QZ#WgGNs77S#w>nYlf3;$uxZ-&+^)@&$w;m|v>2+s( z%>?ZLfNnny0Nwv=4#{btQ{GEtK_gi=p+*bXK4D;BDCX>D0f#93z;ws}2giTW7|>P$ z&^DLuHwz^Yp}>!H9_jxJpzTH+S&SK~^6UbOK|216-f83zXjTQW86ZI@gU~Di(hRwj z2hnr~nSv$!+(6e-1^gFfXo7~{|5A~K3UIUFE&mc0kO42mp~^qNg8P4|%t93;t? zK3v3`W__rfqxpaW|Mm;7nYu54hnNo+@qos2%h|x<2bvEu`IT^`wO%S=O|!mGa*%)f z3I6Se;BZf>s&LzPmT!|NsBTS_}UF|IaYHt2gog|Nj>rUif+8VAnwv{_Fhv4m3Vw z0ZrN5V!qLQSm3`h6|A{=5@OHIr?Vl}-#pp17Hsj;3x6*h?K-N$f4%Dgk}EDex$uPR z2tS5fUL0g#V7Phm?v2AQKok3~zkyas+OzVieeGm7~}9 zK|o;83ziyiv-qy-kF>^Gj(VmN=9{@3C!q#Ij6ZYpz|B8*9^O28^TEvzH(%U4c=PYw zn}@qYR9G4xfqI9{r|Q!>LsZyq=BTh8Udh0~!BD~mUU_r)4r>Bz8OmYMMNpu{HQ*IC zCCqo3KqAd=xOf>D{?~W9sIY-Ao8n(`g8Se@?oJmKmQEg(+d3-EN4P*Ij5BmQu^a~N z=mW3SftbMv7C4*+S((IqQ%5E0FnEcSZ9P+oTw3!3g%Z)(_aA^6JUc*j>5G^D{{N3U z3|86vhU2b?3TTy8^AQfPsjo#a#Y$`;cE!UD)&iMVst7Y!0&H;eFWD0I7u{gfUw}^R zfLd~wwFi`iPJ%-0=7F0J@5t6vateS}-0T1?0W3a#hj&gTr@-s|cUfD|6qdjgf;#VI z^X~9Y0V$jYs(gGont%Q)<$WRX0o1PH1g&whXgyh>V$BPhc`ugfMjWFC9RcCr=fc6# z{J!17KTp7xY)zpyr8Pp_(1bXMoZo~dAtJrQ@|^Tn%{sL zbv&SJds=Uo3bp<(;p=tpxI^PZAtEBytTj-Pe29pIHERP@Bo-nfW6jzE74e3MC|I+0Kt(JeA}ZFbJx~#K zh=_$X>jJ2VC`81@nso_Ogc%~@V9mM$D)R9l*o7|EtZSem_aP!4)~p+#B4;5YKGv*T zpd!0LB9I1P^BWORf57-;Sa_%JkIvXPoxUF|yVo#)`jnR4pv5<({M|o0egEvsn7}RY zQVMihSwI%!i>sjPdp>lQazsY9ek2|+U=0CT zqT#)+Z$MYIz5to+%hCOz`Jh0r>zlwVk#LakMY;d~xj{on%?CsRvczDjcOir&09i;h(Z_f9V8dg~5a$$s&6|Hy|q&e6$}%eg%Gv?1u|%^`Axu!W)$OX07coKp9=&Wjko{AoNSO&};rKCL4nq0UOJD9vy=YCZ`4~hSE2$m29j_zjS{B-%rwyxP5Bvu?JWECY zZw6WS!Wy(nySUOHP!Z54065@Yx-fzcDRj#U2Mjufdi%N-N#;LfyUFo zp6LDo4&yAA7w^Gp{zSGOC=~>izE*qx{Wm@k>F^SC5|Hu#P7BN3Alvv`JV66&EHCzh z)qjZuO@Q@-*07gybXxSfzUc-l%i;s)`rA^V>vF+`0SmY=;0FsIk%DI$j({wI@J`ns z(9&ZSLdGB4 z9*E%zS{Ym19r^>F7;|kb>oXCFvAgz5cPU4=?;qm>4xNnP1OgW8FK3^tR~E3W?=YV#`0nk=)#>cju%~En&(9mm=<_Z1*Sz_6oF}p7g-?M>_sw& zDpPn74W?CI1cPaf7v5l6=Y=zvHh5tTrcGWLgK3!;+F;t^g)*47c_F68~Iz;woo z17JGm#SSoC@L~g)E_ty6Ojo>E0H$kR%-98S!ZuKze9;9G-3HFP^#-S`Yhz4a__MQt*4{zyJTYfp&$w_yA^}0Es@`33c)r5bruzVhf0Q2F$zyVjcuD zZ-AKFz)a9c@{84ACg?QI7Yo2l&|t@lsbD5(#qx_TF!KUPTRoWh2E;4@Ge3ZsnPBD@ z5Hk+U`~hMHgPEXXTV8m8nV_kp7q(y~=mzx{MldIHfOhn#fF(c+pQD7kpr* z2uJ}lm?;5b{@4Ku0vQnVEtshQVm<;hRY1(^V5SC$c?Qe`o!$20AedaM#Iyo46F^LTuz50&QW$hBOf5(Aeo(YAl-L{J&H&9gI0wH-6Z!wY`vbVG#nOHF zwRd>f3s2CI3ZRqz1;So9{`vnu?8TGqpd#Y+{myxy!t^!kzJ%G_0^RMPL}v?PmhiBG zB$`kD2USO%+d&f05is!RD(F}yP$z<;dmhLEt^Z3oKu4CGVP{|neo^iE|3Bz(kj{3H zvwPiH0zL|G(Ftqx(Z(mJvu8)GV_S1(n3T?mPim#xOB8QBYy) z!2JPqIzg5ROqd_4R3sqF6ejjt1fpFcAj=FU_FUxu|L`pHVD1l)MM*ENiGa)t0GX!{ zkfjAvw;!rkB_K;1Cbk+XrV)^(0~4DL71IgG(uIjNBaAc%$kKxe=RlR31Z3&M#3G<# zG67izFfkXXm_5X9pZ z0a-RMu_r=skJkib*}{a+LX@_H%IknEJDBh`s4%GP4#={H3D1WLgUa!MEC*1>)AdKd ziw?Ni?Vw^kAj=V^ArGnnRKy2lIl+X(p~9fzJ|N2(ChPze1{M7QSsE~5O@#5FycdwA z36lYBFX8^s+YYJ~0`!aoGT{%;4>5CK^VFyV(#VNh)mkijg#zyOmuE(i;pc2Kh| zAcGSo$q?{j6;vCjW`XA3ET(`LlcB<(S|$LRdzk`W)IfznH4ZETGX=azMc4qUfC8X- zm?_|eH&g?tGJ<7erhpeFP+?H51k1@x0WV~s!l05SAj=%=0j7W#YzX5)6&5T@GX=bO zBLE2tP~`>7)l2~|u0n-D6&WmJGX=cZ2NecYYOuV`6!2m>XhX;mP;t=?s^ehUnl>K z2tXak9|13%pu(Wq8CDiB1-#Hk7!RtfVZ{MczzadB22jNfD-oCiUi{*NcnVaB!wLna zfESOU!k`KrRxU6Fyg0)L4;)ba4l5d%0$yx_Y5>*su%dw};KgjHFsR;#6%9-QFIu3& zpf&)gXaH3-OaU))5ypd>1hArkDd0sgR0F7a04o}p0$$iag+c8ESkb@~@Ini*E}t781W^<*h8Xsb3uw*yP}iB4A)&?+rS zqSNq+pOY#}29LtQvzPWB^cPS%_GBxFj~zT5RjFN-T^BpE#IS1$abQJ;aK`%dfa z61n5duvyvDN5Iq7t+z`!k28a3We;<7`~G;%+U@(p_;%~3=FORVROviLH=>><*|o&$g-EE7TGtO^`LXi>4-VzzlZ;U z8h5SVN`jE)n2o=+ek*b8cKs0^767yI-V?Butp`dJL35Utt_r0r0Rfl zPb&W*Bd0&YUYN%J{~sCrLJvfBqf9v0F2XY5{Cdm3|Nl!hdR;&KFID+p3NjHgg$)U* zfETC0w|lFgj_yK6DUcFUx33I%RvA5k$b^GZh(b6db^I?CKu;hypfmQM729>*jlVzq z|6gB@d$vAP7aEdh5Fxqw5G*9OBZVY*wtiVJi*!JE*o&fbp!PctIC=ap6#%6W8CVJ_ z5%^y!5dgZ38*+lsVgg7k5D8 z21jHt!tDiz#sB}^7rLEttXYrD;T9+n=;rO1%Pr9ARZz3X5t^$siOFttwKGXX(? z8K8>z|29xq1ix4dUTCNSa?V-MD46RL@We^*e{-;oz<|L2rDrlgt3F{msu4P7gAR+R zy}(#!Xc7CaM5nvkvH6aO|w>kD;Xnh!ErME)+1u{g2T;cy&H!1|+Ya(_K=_MgpkmwiPF8(yBglw=z!y`%B2SP+K&Pd2 z_kr5w%|}#PPnNhfp8$1N8B1-u+dyq{U66?ZFMh1}_rJRh)a-6P&=BzAC726pZiBhE zR)9taK!&_HzXFus1-f0YK&G2I+d#q)KXkT%n)AKwAR{}$rgys@=>(hF?RuiK4P+kZ zNJ+Pn*J}Suue@jm8C&|`MKzed^P(6`KY5Y8;@^Mc+s#J=od1{JcoDk-G&*}Y{ z9C)D<+#M^>eK@T71p|M}T`>j*5B`>;5UL+S*@-bQbcgbI@VBfHWnkzoo=nE1Cj;V>f{tiq3(f14At_K6Z9;{&ZH`R5<#<#7es@|wx`B*-R14hDv9Hx_Fr zmXdm~i=0@rf0T%zJBSNxSRE_>HYZl>4tl{3x?iG>jenaH8+H}Pz$*OM`L{W-<95&j z(9&}^4r?b4n1eX5Ij9nBSRE(-HYZN()`de(cpScM-y|28Ln+zzS(?TU31uyzuF zB_t;S{%v&v*jyC^HnC2Sf18sab~_CqDunpAISFA`!3S31C(OUiNf@`QUa*1^l8CjF z2rQUHusP@;=+35Xb)x*+oJ6r(Hy@%xjDMSx7>vqiCkdE? zB(OQi0Bl&DB>y%iN$l3~K~zZbZ*!8uuHp>~DDM5F`L{Vq<95(7Q1*9|v38PyIYVx>|?|IsR=Ynj$b9#nd#eA?Ce$V;0IX%bi_DaweSGO0|PA`z1^#Z$*K42s3Uh;2q zdWl_y7DUA>{%uaLu&dwztMGfxzs>12Zf89LwOQQWSUbHzcGes0Ms8&SC7Zgp{M($~ zVplO4qT(I@Hm7&kRTP3%_`T=f=JX!7vp{XJZnqECP9Kn+^#Qw)a$qCtKJssK`iNZx zXrmwhwz^OJ+nhdOS8)rpk8qpcXZ~$YpK&{D3#gIi_Ql%i3x7)!11K<@zVL6W`-0uf zHn5p>U-`E=eZ{TQq zd=GYb-B12)PCv1$I15qni+`KbFYGEnJIMLB`TgeK=JXr4vp@%Jbi4hrcKTCN3dx3l zw11Qcp*J5&6Zp5){pH{0^cSnF6aTilfBf5={$Z6>;os)>pMRUve_YNeWime5eK7vz zGteDW~-7^{Jo`M1?Q;os&2Dlssfx|M$$ytKfSozB0_4^mR#Y`+wOPNH&q zZte6OIjWvx4`$H$68zihUhr>o!ckIywp{RU!&g!;{Qv)-f14kqq`>K{TcAxOZm+GK zUL!l}HFjsM{Rc9#?hXGoCmbaOXxSbAHhd*TCfE!=NJ)XySJ&V29%=DM0&6`M3E&N(!9LS_4{0;`Z6v=`*skK4W)QJ;c&4{M(#x z6cn)#6?h5?Yp@DGNI`+qS)yQPeYbY{4lka*^KYyBj@@0)|9}JI2mdxF93{n3hzdL< z#bU4uKS)V|(_OWob1L0_TRZ(m4zAzWofQB!vhEN6HYZSNfu*yd2T=hlF|erM0juzX zlo~jl_3Sq&0GvR%zTFFGh}DsXrKK51@dMcqGsar=^e7OaI{Y@{se~>qU=@ClVg{$P(!tL9WbO0`*;zQ+Cstr1 z>mcnDtj>~vsK8UqeER|NnjfT?!Rf3EpsO<7zF9kcgBK#-Ky4K4X?_vdOeZ|WOany4 z5B_a+IEtA#h>D;5+x&jws>S(REx_*jW$p9}Ik<4NPq@KG)56`anB2RrMfwbM&vXW{7g7=ewfgS2L_I!gee0#CW}?kmV^evonnr?XCc1%=jI zYp1u!&ce~}nGH6w4$_*z>a0qL3OwaXI9P=rq+G%2EJLufK3Y3{geR_#{M+hqbbOe> zX5#DkJp2L*415L4ey|EZNWp^BT{A(~WV(H|cKV7OTsZnYIbb94^?SS^Dj@wHtO2S4 zR^bO}zTk8g6WCclt(|@%I}1m@=jvy0SU_4cSS{TQQGusinFvRVE zkjrqGQ%bY=w|O!0Z*ybBD(l0)&5MbDn;X;Xxdcs8fSL3%57d`(<>24O(e28^zm4G~ z=)7s;1E9;}y8qAdVi(xq$1dSJ8pj|NC`>9u(6gK-ysKu)VMzSMol(v_!7 zu-lgdWEiJI^FbzSSDvCz5Su`|s7sk*4|n_Wbcb?;d6bCqZ#PP7{Z_)8W^Gu?0XlpC zAk*s?{M(uMw{vPkcUL#Q0WA(hO!$Gk+S?lN|NsB2(11oi4$#t)7wpGC=MFdjV64-E z$OXJe-tqsxLjaW5+ZF)Y+YuV@!g&j5-bDm-6cuRI^Vzr;94(L;4A9IqXt(X6-~axD zF46;8^xy1-H0bEoGM45S%%GEG9Xj0vUU2OA{~yecls@3lTqnQ~+36-y!kWbt@tWhm z*^4^R3dk&mEar^JXm){4H=Y-DM?kZTJm1|oK=Vr_{2&Gs149YhH#ZLUQkLd44hG0V zOQ@a8wOKUHp2jzzNgzZ(gH~Q}bZ)Kq|NsAsZ<7E2XF2rF z04)#e_7>@FtpS}cbu&QvWaC5D5C8u+9%K?=U@&^#gN zXcefk|HdzDHiK4_wjL|E zt(&WP7)s>+7xN$tW3*#n0B^>F>5QD&l)yDeO4OR?aXoT1rzux z$#~d|oJAuzJs;v>u&m}OS^wYoMa0(s|0AuPc}f?By{HD==+}Cnbozhe7gs@N7aDhe zcwr7w5NZ9PWPLX{zF(I82i++b4gxPG{ea|$#y6lvVuX0!7EU*(QP^t!6D8>=c?aIRn3j7Ri1_p(I7w!k44lmK~cI5!wx%6hLafcFQMo{WqAull5s15{i$zmY%+#O_j#Ue^~{oB>&pVK43+fLSGy z#o6onA}rv=5zyI@M|eOP!vR`gh1Y}q3t9>RI$gu~Qn(Z7fQ<^j;MPke9=$B)paT zmQL3{z0II}&?(o+4!V9+C_GCnW5Z-lfft|~DVmS)7@zEB3j@ixb%PbKznJpt|Nqyl zFBpIS|KD84!4O$$6qetuexu?dt$|Cj#B z3JreoX)QE;^0$H}&$ArDGe8AE@C*L^u*l5Ia_F583Yg&Dc90nvpu#fX#k+kl1-@DF z!7pYyfUX8@Jy6P*r5F678_Fw@$Z~*c%VH0Bu?wz8GK(uq0J2^nAnb*MJ*W^902MNj z(<8c{f)0ZS0D%`5zCf}AdJYDc@Zm2&%e}jAybu!k|39pI2k6Sw7yT@tYooyXEW1B^ zzX{2z8K8A)uo6E2R^YSXpt=T}wjn20guSQ}2JJ8SzYT2I#0`jAF^kb5!#a^& zptB9sI)I#40m_}<7+6X{yNhGNxg-3At?>W_xza|NsA^R^_%E{{Qc;<$%}b zoo*uFGvYy&I-=GEp8}G_n4z5vu5%&QeP;)ywG!U%?4aVig!LOcdnt3XIs@qXSkQSi zFAfSp91kiQUtC#_aJ)lj+ZqN228j7Q|F?k^Kx%fz424vXuRs+e#2O4=fopamYjo5S z8yerB<=&90{DqtlBF<+sf#Td-gy;z8ZdM1?YA-?SL158d%<^LXYDk>(w}Q?)1t%J) zEVP1G1=S1CIv$pKN;X5){5O6P2Q{FSyOAGMxp$Vcybk)t&QuxzuDuPwwKu4m0o9|< zW}t-6(|Vv(qM4tmvz+6<@r#Ug(E3guq*bb0{M#W$&<)+7X+uy7`*Xl6$^0$CacR{#$)hdXmOO+b=LCL|=S)kO-(wV2k z@xSql8*8ENF$vFNe67@6Ex=G}0rra#!h{T%33A~9VJ|?7yugi;68=VhP&#X_XJII1 z#-3^1Dv>e`j!bSM@c%zF(lrGTkq$b>GqT%T086A}^*1D!Cm@`?aV6B_Tp%wadC&;# zK^=t3c9=>DkOwtE%gT;`idsl{04fr&ln2=rNL~YV8jQd3Z|4G?r)e3U#Twu1IKMZD zDb4zLIY;BcoBtUYUi0-j?g#PN8V~;b55AzJ`QU|v&sdm0LiClMiSIrJsnVdWgCKD0 zzz5noSn~*7dad24{7#9Abfbai*&~D8i zAea2=F8+4KAVe+aYt z!wZMiAir9FD7kEWzyW^PE=v2P+m#1gYIM53=ynBdT7C2474QH5Sv-)mWPAX07ka>p zEsH^wAkT|)y#N3A`hMu_0M#O`-%5EJeLsLYXy7A|d)q*DV5f0!HH-1dPIl1#V^CW_ zd|}5lPJwWb07z3o4SaYQkMYS)-w)l)tp`fdL5h;PLFxrSOzvLS4*@S^K@9*-FtZ=j zM5_J35LsHVuw@#jK(I#uqy=#seB2!od#K&9)Vv_yicjx=kyRc?H0UEIGXOTdB0AX-zV( zKuPe6MhnnI6Qy1d6|LV&9KfemS%EexpL+vZf%xOKdft$vpFyyfBhADE)9$d?DbLM&_2=pke~UW^hxf6 zkuSaW|N9RYWrvBH><8Ty|EBqkKp6BGv#D*M?fX1kz9RhFK6JZ&Y4I_TER{FDWEm<@ zA_Te&0KCMRe>+Qova7&rrtU+n2TGVh*CEvYVTePVadrsQ&H^3d!2&uI3v^xiRB*FZ z0Gw&T8NEUgbQcmY=ul1ZZr%lXyaKPeA@pJp2Q&=x!ebTas1h;I=2YR=|Nb|h_z%|K z{6+=QRp@r*2=10uY2pwF3-5G&V*IV!l_#vz^}+wkpp$Z6yqNs<-~Ue6H*v$VHq2yfzAwe0UdGoqxFBO8tkBwaQ;@%uJ|x?75pur8@n=2fU+gzkYP|4 z+@2A1;^^g!Du1{JIl&}Z<7roKQAz)ehrbIT2B?4TGfH(sG!M=pt z2AIYC`sqTj39_Kue7Y$|aN_<#AoDTvwW`sV-TZr?YZt}j|omgu)0DAE3Z zvGqWSRIl%yz%1~Y@mY)k|3g7}j_sT455`jN?pguR3A73fuMHN0d}e*TL?r-psCJ_-AO0d%e#JX1|7gk&mM zN`}y(-EV@!!b3qjK{9^iu!E1f+my<{5DQx5|1|b+w~q?TcSjaB2I!4rB}Sl|#kxKI z7@v6IPzXxn83Nq_8bRFwDnTzqz~?A)#DWe_>JCv6=wt$w$_$4=yLnwy1VRI{{$()a zvJ0gAH)UX8V1T5wBLTfGDl93W#t`U^G>z^Ej_v}U=70Z7teR_7bpDsHS(m8jlGa@fuG!4OP%54QS_j|lvY7+C2^h?X2OUwg9pvnkPS82C49!O*;^U$Z z8y`sN2J;&$SwLzt4CE+f1>atFI5=>3!9s3<*W6G>H^?q;j!tKm&TO90 zz<`Lz*vRNZEDZlIfJ&xrR}N4gx%mMjXngSt)V9cYNWcXi?)Lp)eD;M*!N316@BaV) zKLG0KUKbS}?GzQB;IQycjqVqaFgP0Uzx2;>*FT^I!M(0uAc1k1fR;|s{uI)6rGCI> z7kE@x1k^wY@2=u${Z=aWLUkGJT%?cB{{8Ph20kSoRJWHs>Gl;k#>UWkvW}(uASjVJ zSi16*bH4bz6m;Ow>odpL41#;(7`qR*o~)DV5^uRw!p6VvlKX4sEQ6>H0SC|4ll3pV zLq(1;Ftnbm5NfbDt>Jyme2l@sqrt+mnBOd;oU-W?&$=tq{(?y@Cz2H>sgJfTjCiyY#10`tM2$;&%p3n5i~{t>I`?gawrC{C<>%?R&czI=xt=Q zVPG)6&Aps!I$#fAA4DZI+-h9bk_2KPE~Q`=`3d9{*l&M%>hX!poG-?#sHcMI$i&CyMm4( z5(w*bz0>Q;5gyR%dLiHiKj@Ic$X?e6pt~moo8R#CmR{)ovvg_N(iabmK;wl zQISB%$#jOONN^u0)#&z7kpLNBeChkg?i<}MDgxg>c7NzT{5?fQqWeVmF%Zps@wI#R z4Y0}(6%mk{i?1)MwupXhc`k@)_M`C<{Db%=^cIY$w{wTp^C z8KDEyZEY770qGDG5#LJo@3+3+XuieJeX9F%_f3#h{-rRn*tqyZ0t{yw zemWG3HvCj5X5(Lb;qt4)-G_`XH9VBR{Nk|j0pm-c=;-zp=yv4+9iaXFzw$v)j#&BN z&xb!HDxhftP&xVHr8Q{Wq?7Fh^I}*IIsX`xLtaY-{x9We{Z_*H;;1zPLnqs7))#xg zij6^oT3JjlWI@e!kS!=%in@I{g2Tf3w>xqf-|nsj-xApXO0ow!UH3FT0;SGwN4CaS z|LqwVKxghbGIhFs;or`9@PR;Q=z~tzAC12l5B&dMs@naz`>xWWqhvpy5HD6xt zWMN=1KG0kHVfE_OSxnI{m$5J~EbLgwEzn!~p||!)XXu@!9-XddvgA8suPp8LVC+6P zb7`FNHRcNkf3bFk9%+0i&%n@7$?DmB@`0oFN6?8ar5C!-HJ|@~`9T(QT&v5}5Bx2l zE!o}2FF*Kx0mOgJVi_~_Ln)V&^|hL>FTo2XUC+$Sl8;or$b6yO^~}Lvtf~-0J(^EE zaL_){8GFU}fWzenovtUkU8a8M_C3LTqSN<=^$F1JN~g2_#}~0$yPha!Gd}6q>3gNq zW$Fj73cc2oCF)?+r#oY>^j0uh|LCl}(S5v#wfP4liqguf&FBAj`(Ee{Jpyv0qRZ3| zy-tkQ$7%(8Yd>_K>$PduK4E;|^J=iF2bQr{N*EoxMOzkf3v?gSW(9?m^@&=3SP*u9 ze!1=6|Nqvf`1>W97#Ore@AQ^F=?uL9GV9RNnaz*nnL(#DFYRk`96DXkSRbpo-d%d5H}psMv4anoK!I<3JJR}G4F@FPkwX2|%Nu|H z|F`CCSja8F-?Io5nqb%U)_yQPuzL0C?t_iKph3+BaJ)d=dIrU3iq<^-kA2-630{feA{%$04B@ zvh{;or|W~}f6O)aL0kDke{`3g=su1Vj_0w3V|VQVPzq%QMQ!(qZr44RpMhFistgPa z4cs3VPFTn-z+L*G`G-R(SGVhz&T^Jc_SfvqKNL!tI?W*!9e8wiZW^SP1D#Kbyor;( zCGLXJ5|==UI|o|gfr|T3@qqQ@3LU?cO zgU;A3ov{l#W0!Qs&gqO@W9h0=D*j^LbofYB<_*wki7z=o8$m+_x=(fbZs_7__^D9B z-|&;Ogsb5vR|#vwPu@~yr`ONBxSTqCS2zFQ=5McNVqo~M(z>yQU7*+TybVV=TNZPK z*Xz68t}5LO-3_1qrGZ}@3YD%$P3ri;r1WN69vPS-Wvu3JDZP=#7A3bLL9YP}!S@@Fv18-8l@w}589 z!1geMZFa5`ZTRWR-}mm{|Nqd?X#*X&@AVRNZ=Uf1kXfCsOB#N1^0zbn|NlRW<)!|= z|NncP{&l);0EbyQdlu(QY0#z_NK`6$c$5f$qw*5y4j+z}pba%y?9C_tM|Ap5c?sGY zlg0j$@gL}fYKKnOIj@-^?kxGy@Y1m1CkKCfH)v3471;2y#SK3VUT?9CRVY#Fb^71w zx&fMC_IP;kw-)~U|G(LH%Kt3(h?iBMyI{B?yqbS-@wevw{r~^9hw*{#&tMzmK~ZCz zeU6KNU+L=RV;7h|HvS6`VPL4|g``_h6y13()aAQ+U!VvB!)p$ZdJc%QYCn5{qStpu zr(n150?^4U*O?g@ntw=?Np`t@w_&Ye{db_l^?SGP8viT_$B0hfHLsbweb<0SRF^O_ zF!)=@mvVVH`di4C{Ot5y)9ZUAFaR{P@M5(A=*H(q=r-*QumAt&@6l&wVA!=`A-6#Ds|3&mI=svb43%8F1Qv4( ze81QHD#0>VgunFzI3J~Tx*mD?6tp|@So5Kfga4R2L)UbcZfSnN&fjv5iGd;e1P}Nm z1!hq0PP1ez672riTf3vzcSoo1hNVlF{`cL*zrB*HJM>)lapOasu`Q~gJlPq0rPFl* zcpyjlLTBs^sGBgTL8= z5O2Rdm{-ox8GGiXIY?parBW5Q@2+P+4dc$zDW&4gwI>)#1)FP+FqCo|A4uzTJ@--s ztnh!SnA>+p4wynt%Se_|7E8&JEm^GHhkHYB#CN*(bk@%3tXM;^hmFXTdyNW zr|TU4?QGx-HK*HmNoQ;a|8@rc^(Q)gmoR(%vG)2?#A@xkq?pzCfWvF%Zr6@ZuRow! zfwccj&AD?x7fAZI{;%KL?Yp77c1E{rPxB!r2Y-l7t^eyMb(c=*4!zTOjOhUA8nP>$ zp&Qa#ztvf{UaBwxb*`@;d?nv~g82Ywoazws|L)KYovt^SFYN%0U3J!8;l9ZHp)+(t zXXu@@)^GKvKtv{3j`>4c>$l3-?%0;@W8ZJ^Z$HrKI)nMcH`gnSC5+D9zBjrL9eg0) z>AT@#?gmcR4c)FA4nCB>`2ON6?w|jCXLN?%>2$r(S$n1QToyy??at5*(IrA@-N%jp zyQgsy=%ghy`6n!Pofw|9?h?#{Ucrj0~j?-LBU_mkgP7yWZ-I z1v3@Wx?S(>1iL%-R+{y}QuegY(0gvLdD0xxI$iI*W^w3rz18h|=QX=Sr|UIPaD}b` zCyO-e4@L6E2RdUKLOr{{%6fJIo(6V- zclGQ7ehusb&JFAW5)JI2^&`hrQU4_5Xil_leyO^SA}9&zDFx z|NK`X(tQzr5fwA!da2h;-Iu>PsnnOMA`~I617L<+yZxG}`}8+Qm4*`W7gze>HTnDt z|NeI$kB^IvJ=`73VST^k(>FIB#!{YdZafVo&%U|wFqJ+4Ezc@t4|{QPKFBp})@~f7 zoXvGC45h~$I@$j7fgIb-R>El^QNr%f$@Y3fheWp<&wn?T<_GVaPcU}6@$hdu{CZ9n zPsRh#U6PCU|NGyZ`h)>=k0cN59!b#`4hT1KUjWa8z19qSv1%^pI_}gz44}!o7vQ^Z zB0+Or@Y^BzK>g<9FDCE*_y2HrDNlFpldu<0K$;+9djjAfZT(gv(H$$$db>oh!H%I+ z1Uxxc!fJdnt&_v}KwLCvCJ%H96zGzp@+{Eo;D_cNpmjJ5rJ~)w9IYoy*!Z`xrFAkI z|91xuzJn%z`M0qJyij@zSp!kx&|UkXxxR$4PTe}bq(&8VuoUP5OwcXm|I16lvN->j zvp^1Y>aP9JdZ3isI=-Yxuc3~Sp+uv*zT~wbOo#D*ke+VW5ANY0T?J5Gtp`f^UdZ(Q z``>*2|8WM;%?7B4Hyw|EX#zPh88jOy@V}G?H0}E1A9$Tv?BOhq42^Vdffs7~{(%-f zfv+F#{tmjV>=_%g3HXjOT9HoX?TrZ>&|NoEdjQs=Riw0*b;Aa3GeIM}RA1Gdq z@cehHq)8 z!℘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 m(D)mJ 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�xdbYZ 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%0DFuDVMK8`7ru{B&1w^ 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 z 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Ð_CwQev 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 literal 0 HcmV?d00001 From 56bd9da07cbc6db9806380c79351ab0c5747c8f5 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Tue, 14 Jun 2016 18:37:06 +0200 Subject: [PATCH 09/11] Update Oculus sample (will be moved soon) --- .../oculus_glfw_sample/oculus_glfw_sample.c | 50 +-- examples/oculus_glfw_sample/raymath.h | 20 +- examples/oculus_glfw_sample/rlgl.c | 421 +++++++++++++++++- examples/oculus_glfw_sample/rlgl.h | 12 +- examples/oculus_glfw_sample/standard_shader.h | 46 +- 5 files changed, 482 insertions(+), 67 deletions(-) diff --git a/examples/oculus_glfw_sample/oculus_glfw_sample.c b/examples/oculus_glfw_sample/oculus_glfw_sample.c index 73f19883d..8fddf5b93 100644 --- a/examples/oculus_glfw_sample/oculus_glfw_sample.c +++ b/examples/oculus_glfw_sample/oculus_glfw_sample.c @@ -23,8 +23,7 @@ #include #include -#define GLAD_IMPLEMENTATION -#include "glad.h" // Extensions loading library +#include "glad.h" #include // Windows/Context and inputs management #define RLGL_STANDALONE @@ -148,33 +147,34 @@ int main(void) glfwSwapInterval(0); // Load OpenGL 3.3 extensions - if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) - { - TraceLog(WARNING, "GLAD: Cannot load OpenGL extensions"); - return 3; - } - else TraceLog(INFO, "GLAD: OpenGL extensions loaded successfully"); + rlglLoadExtensions(glfwGetProcAddress); + + // Initialize rlgl internal buffers and OpenGL state + rlglInit(); + rlglInitGraphics(0, 0, screenWidth, screenHeight); + rlClearColor(245, 245, 245, 255); // Define clear color + rlEnableDepthTest(); // Enable DEPTH_TEST for 3D //-------------------------------------------------------- #if defined(PLATFORM_OCULUS) ovrResult result = ovr_Initialize(NULL); - if (OVR_FAILURE(result)) TraceLog(LOG_ERROR, "OVR: Could not initialize Oculus device"); + if (OVR_FAILURE(result)) TraceLog(ERROR, "OVR: Could not initialize Oculus device"); result = ovr_Create(&session, &luid); if (OVR_FAILURE(result)) { - TraceLog(LOG_WARNING, "OVR: Could not create Oculus session"); + TraceLog(WARNING, "OVR: Could not create Oculus session"); ovr_Shutdown(); } hmdDesc = ovr_GetHmdDesc(session); - TraceLog(LOG_INFO, "OVR: Product Name: %s", hmdDesc.ProductName); - TraceLog(LOG_INFO, "OVR: Manufacturer: %s", hmdDesc.Manufacturer); - TraceLog(LOG_INFO, "OVR: Product ID: %i", hmdDesc.ProductId); - TraceLog(LOG_INFO, "OVR: Product Type: %i", hmdDesc.Type); - TraceLog(LOG_INFO, "OVR: Serian Number: %s", hmdDesc.SerialNumber); - TraceLog(LOG_INFO, "OVR: Resolution: %ix%i", hmdDesc.Resolution.w, hmdDesc.Resolution.h); + TraceLog(INFO, "OVR: Product Name: %s", hmdDesc.ProductName); + TraceLog(INFO, "OVR: Manufacturer: %s", hmdDesc.Manufacturer); + TraceLog(INFO, "OVR: Product ID: %i", hmdDesc.ProductId); + TraceLog(INFO, "OVR: Product Type: %i", hmdDesc.Type); + TraceLog(INFO, "OVR: Serian Number: %s", hmdDesc.SerialNumber); + TraceLog(INFO, "OVR: Resolution: %ix%i", hmdDesc.Resolution.w, hmdDesc.Resolution.h); //screenWidth = hmdDesc.Resolution.w/2; //screenHeight = hmdDesc.Resolution.h/2; @@ -188,20 +188,14 @@ int main(void) // Recenter OVR tracking origin ovr_RecenterTrackingOrigin(session); #endif - - // Initialize rlgl internal buffers and OpenGL state - rlglInit(); - rlglInitGraphics(0, 0, screenWidth, screenHeight); - rlClearColor(245, 245, 245, 255); // Define clear color - rlEnableDepthTest(); // Enable DEPTH_TEST for 3D - - Vector3 cubePosition = { 0.0f, 0.0f, 0.0f }; Camera camera; camera.position = (Vector3){ 5.0f, 5.0f, 5.0f }; // Camera position camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target) camera.fovy = 45.0f; // Camera field-of-view Y + + Vector3 cubePosition = { 0.0f, 0.0f, 0.0f }; //-------------------------------------------------------------------------------------- // Main game loop @@ -293,7 +287,7 @@ int main(void) // Get session status information ovrSessionStatus sessionStatus; ovr_GetSessionStatus(session, &sessionStatus); - if (sessionStatus.ShouldQuit) TraceLog(LOG_WARNING, "OVR: Session should quit..."); + if (sessionStatus.ShouldQuit) TraceLog(WARNING, "OVR: Session should quit..."); if (sessionStatus.ShouldRecenter) ovr_RecenterTrackingOrigin(session); #endif @@ -581,12 +575,12 @@ static OculusBuffer LoadOculusBuffer(ovrSession session, int width, int height) ovrResult result = ovr_CreateTextureSwapChainGL(session, &desc, &buffer.textureChain); - if (!OVR_SUCCESS(result)) TraceLog(LOG_WARNING, "OVR: Failed to create swap textures buffer"); + 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(LOG_WARNING, "OVR: Unable to count swap chain textures"); + if (!OVR_SUCCESS(result) || !textureCount) TraceLog(WARNING, "OVR: Unable to count swap chain textures"); for (int i = 0; i < textureCount; ++i) { @@ -682,7 +676,7 @@ static OculusMirror LoadOculusMirror(ovrSession session, int width, int height) mirrorDesc.Width = mirror.width; mirrorDesc.Height = mirror.height; - if (!OVR_SUCCESS(ovr_CreateMirrorTextureGL(session, &mirrorDesc, &mirror.texture))) TraceLog(LOG_WARNING, "Could not create mirror texture"); + if (!OVR_SUCCESS(ovr_CreateMirrorTextureGL(session, &mirrorDesc, &mirror.texture))) TraceLog(WARNING, "Could not create mirror texture"); glGenFramebuffers(1, &mirror.fboId); diff --git a/examples/oculus_glfw_sample/raymath.h b/examples/oculus_glfw_sample/raymath.h index 4075a1a93..10eabb6be 100644 --- a/examples/oculus_glfw_sample/raymath.h +++ b/examples/oculus_glfw_sample/raymath.h @@ -47,10 +47,16 @@ #include "raylib.h" // Required for structs: Vector3, Matrix #endif -#if defined(RAYMATH_EXTERN_INLINE) - #define RMDEF extern inline +#ifdef __cplusplus + #define RMEXTERN extern "C" // Functions visible from other files (no name mangling of functions in C++) #else - #define RMDEF extern + #define RMEXTERN extern // Functions visible from other files +#endif + +#if defined(RAYMATH_EXTERN_INLINE) + #define RMDEF RMEXTERN inline // Functions are embeded inline (compiler generated code) +#else + #define RMDEF RMEXTERN #endif //---------------------------------------------------------------------------------- @@ -105,10 +111,6 @@ typedef struct Quaternion { #ifndef RAYMATH_EXTERN_INLINE -#ifdef __cplusplus -extern "C" { -#endif - //------------------------------------------------------------------------------------ // Functions Declaration to work with Vector3 //------------------------------------------------------------------------------------ @@ -166,10 +168,6 @@ RMDEF Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle); // Returns RMDEF void QuaternionToAxisAngle(Quaternion q, Vector3 *outAxis, float *outAngle); // Returns the rotation angle and axis for a given quaternion RMDEF void QuaternionTransform(Quaternion *q, Matrix mat); // Transform a quaternion given a transformation matrix -#ifdef __cplusplus -} -#endif - #endif // notdef RAYMATH_EXTERN_INLINE #endif // RAYMATH_H diff --git a/examples/oculus_glfw_sample/rlgl.c b/examples/oculus_glfw_sample/rlgl.c index 722256346..1e3928895 100644 --- a/examples/oculus_glfw_sample/rlgl.c +++ b/examples/oculus_glfw_sample/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 //---------------------------------------------------------------------------------- @@ -159,11 +163,45 @@ typedef struct { // Draw call type // NOTE: Used to track required draw-calls, organized by texture typedef struct { - GLuint textureId; int vertexCount; - // TODO: Store draw state -> blending mode, shader + GLuint vaoId; + GLuint textureId; + GLuint shaderId; + + Matrix projection; + Matrix modelview; + + // TODO: Store additional draw state data + //int blendMode; + //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 //---------------------------------------------------------------------------------- @@ -213,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 @@ -228,15 +277,14 @@ static PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArrays; static int blendMode = 0; // White texture useful for plain color polys (required by shader) -// NOTE: It's required in shapes and models modules! -unsigned int whiteTexture; +static unsigned int whiteTexture; //---------------------------------------------------------------------------------- // Module specific Functions Declaration //---------------------------------------------------------------------------------- #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) static void LoadCompressedTexture(unsigned char *data, int width, int height, int mipmapCount, int compressedFormat); -static unsigned int LoadShaderProgram(char *vShaderStr, char *fShaderStr); // Load custom shader strings and return program id +static unsigned int LoadShaderProgram(const char *vShaderStr, const char *fShaderStr); // Load custom shader strings and return program id static Shader LoadDefaultShader(void); // Load default shader (just vertex positioning and texture coloring) static Shader LoadStandardShader(void); // Load standard shader (support materials and lighting) @@ -254,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); @@ -1146,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) { @@ -1177,11 +1252,13 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int textureForma GLuint id = 0; // Check texture format support by OpenGL 1.1 (compressed textures not supported) - if ((rlGetVersion() == OPENGL_11) && (textureFormat >= 8)) +#if defined(GRAPHICS_API_OPENGL_11) + if (textureFormat >= 8) { TraceLog(WARNING, "OpenGL 1.1 does not support GPU compressed texture formats"); return id; } +#endif if ((!texCompDXTSupported) && ((textureFormat == COMPRESSED_DXT1_RGB) || (textureFormat == COMPRESSED_DXT1_RGBA) || (textureFormat == COMPRESSED_DXT3_RGBA) || (textureFormat == COMPRESSED_DXT5_RGBA))) @@ -1795,8 +1872,13 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) // 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) { + // Transpose and inverse model transformations matrix for fragment normal calculations + Matrix transInvTransform = transform; + MatrixTranspose(&transInvTransform); + MatrixInvert(&transInvTransform); + // Send model transformations matrix to shader - glUniformMatrix4fv(glGetUniformLocation(material.shader.id, "modelMatrix"), 1, false, MatrixToFloat(transform)); + glUniformMatrix4fv(glGetUniformLocation(material.shader.id, "modelMatrix"), 1, false, MatrixToFloat(transInvTransform)); // Send view transformation matrix to shader. View matrix 8, 9 and 10 are view direction vector axis values (target - position) glUniform3f(glGetUniformLocation(material.shader.id, "viewDir"), matView.m8, matView.m9, matView.m10); @@ -2095,6 +2177,24 @@ void *rlglReadTexturePixels(Texture2D texture) return pixels; } +/* +// TODO: Record draw calls to be processed in batch +// NOTE: Global state must be kept +void rlglRecordDraw(void) +{ + // TODO: Before adding a new draw, check if anything changed from last stored draw +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + draws[drawsCounter].vaoId = currentState.vaoId; // lines.id, trangles.id, quads.id? + draws[drawsCounter].textureId = currentState.textureId; // whiteTexture? + draws[drawsCounter].shaderId = currentState.shaderId; // defaultShader.id + draws[drawsCounter].projection = projection; + draws[drawsCounter].modelview = modelview; + draws[drawsCounter].vertexCount = currentState.vertexCount; + + drawsCounter++; +#endif +} +*/ //---------------------------------------------------------------------------------- // Module Functions Definition - Shaders Functions @@ -2361,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 //---------------------------------------------------------------------------------- @@ -2403,7 +2627,7 @@ static void LoadCompressedTexture(unsigned char *data, int width, int height, in } // Load custom shader strings and return program id -static unsigned int LoadShaderProgram(char *vShaderStr, char *fShaderStr) +static unsigned int LoadShaderProgram(const char *vShaderStr, const char *fShaderStr) { unsigned int program = 0; @@ -3341,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/examples/oculus_glfw_sample/rlgl.h b/examples/oculus_glfw_sample/rlgl.h index 9c25f7104..93e155b7f 100644 --- a/examples/oculus_glfw_sample/rlgl.h +++ b/examples/oculus_glfw_sample/rlgl.h @@ -48,7 +48,7 @@ // Choose opengl version here or just define it at compile time: -DGRAPHICS_API_OPENGL_33 //#define GRAPHICS_API_OPENGL_11 // Only available on PLATFORM_DESKTOP -//#define GRAPHICS_API_OPENGL_33 // Only available on PLATFORM_DESKTOP +//#define GRAPHICS_API_OPENGL_33 // Only available on PLATFORM_DESKTOP or Oculus Rift CV1 //#define GRAPHICS_API_OPENGL_ES2 // Only available on PLATFORM_ANDROID or PLATFORM_RPI or PLATFORM_WEB // Security check in case no GRAPHICS_API_OPENGL_* defined @@ -296,6 +296,7 @@ void rlglInit(void); // Initialize rlgl (shaders, VAO void rlglClose(void); // De-init rlgl void rlglDraw(void); // Draw VAO/VBO void rlglInitGraphics(int offsetX, int offsetY, int width, int height); // Initialize Graphics (OpenGL stuff) +void rlglLoadExtensions(void *loader); // Load OpenGL extensions 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) @@ -346,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 diff --git a/examples/oculus_glfw_sample/standard_shader.h b/examples/oculus_glfw_sample/standard_shader.h index 956b5c32c..a4bc96941 100644 --- a/examples/oculus_glfw_sample/standard_shader.h +++ b/examples/oculus_glfw_sample/standard_shader.h @@ -1,6 +1,6 @@ // Vertex shader definition to embed, no external file required -const static unsigned char vStandardShaderStr[] = +static const char vStandardShaderStr[] = #if defined(GRAPHICS_API_OPENGL_21) "#version 120 \n" #elif defined(GRAPHICS_API_OPENGL_ES2) @@ -37,7 +37,7 @@ const static unsigned char vStandardShaderStr[] = "} \n"; // Fragment shader definition to embed, no external file required -const static unsigned char fStandardShaderStr[] = +static const char fStandardShaderStr[] = #if defined(GRAPHICS_API_OPENGL_21) "#version 120 \n" #elif defined(GRAPHICS_API_OPENGL_ES2) @@ -85,13 +85,13 @@ const static unsigned char fStandardShaderStr[] = "{\n" " vec3 surfacePos = vec3(modelMatrix*vec4(fragPosition, 1));\n" " vec3 surfaceToLight = l.position - surfacePos;\n" -" float brightness = clamp(dot(n, surfaceToLight)/(length(surfaceToLight)*length(n)), 0, 1);\n" +" float brightness = clamp(float(dot(n, surfaceToLight)/(length(surfaceToLight)*length(n))), 0.0, 1.0);\n" " float diff = 1.0/dot(surfaceToLight/l.radius, surfaceToLight/l.radius)*brightness*l.intensity;\n" " float spec = 0.0;\n" " if (diff > 0.0)\n" " {\n" " vec3 h = normalize(-l.direction + v);\n" -" spec = pow(dot(n, h), 3 + glossiness)*s;\n" +" spec = pow(dot(n, h), 3.0 + glossiness)*s;\n" " }\n" " return (diff*l.diffuse.rgb + spec*colSpecular.rgb);\n" "}\n" @@ -99,23 +99,23 @@ const static unsigned char fStandardShaderStr[] = "vec3 CalcDirectionalLight(Light l, vec3 n, vec3 v, float s)\n" "{\n" " vec3 lightDir = normalize(-l.direction);\n" -" float diff = clamp(dot(n, lightDir), 0.0, 1.0)*l.intensity;\n" +" float diff = clamp(float(dot(n, lightDir)), 0.0, 1.0)*l.intensity;\n" " float spec = 0.0;\n" " if (diff > 0.0)\n" " {\n" " vec3 h = normalize(lightDir + v);\n" -" spec = pow(dot(n, h), 3 + glossiness)*s;\n" +" spec = pow(dot(n, h), 3.0 + glossiness)*s;\n" " }\n" " return (diff*l.intensity*l.diffuse.rgb + spec*colSpecular.rgb);\n" "}\n" "\n" "vec3 CalcSpotLight(Light l, vec3 n, vec3 v, float s)\n" "{\n" -" vec3 surfacePos = vec3(modelMatrix*vec4(fragPosition, 1));\n" +" vec3 surfacePos = vec3(modelMatrix*vec4(fragPosition, 1.0));\n" " vec3 lightToSurface = normalize(surfacePos - l.position);\n" " vec3 lightDir = normalize(-l.direction);\n" -" float diff = clamp(dot(n, lightDir), 0.0, 1.0)*l.intensity;\n" -" float attenuation = clamp(dot(n, lightToSurface), 0.0, 1.0);\n" +" float diff = clamp(float(dot(n, lightDir)), 0.0, 1.0)*l.intensity;\n" +" float attenuation = clamp(float(dot(n, lightToSurface)), 0.0, 1.0);\n" " attenuation = dot(lightToSurface, -lightDir);\n" " float lightToSurfaceAngle = degrees(acos(attenuation));\n" " if (lightToSurfaceAngle > l.coneAngle) attenuation = 0.0;\n" @@ -125,37 +125,45 @@ const static unsigned char fStandardShaderStr[] = " if (diffAttenuation > 0.0)\n" " {\n" " vec3 h = normalize(lightDir + v);\n" -" spec = pow(dot(n, h), 3 + glossiness)*s;\n" +" spec = pow(dot(n, h), 3.0 + glossiness)*s;\n" " }\n" " return (falloff*(diffAttenuation*l.diffuse.rgb + spec*colSpecular.rgb));\n" "}\n" "\n" "void main()\n" "{\n" -" mat3 normalMatrix = transpose(inverse(mat3(modelMatrix)));\n" +" mat3 normalMatrix = mat3(modelMatrix);\n" " vec3 normal = normalize(normalMatrix*fragNormal);\n" " vec3 n = normalize(normal);\n" " vec3 v = normalize(viewDir);\n" +#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21) +" vec4 texelColor = texture2D(texture0, fragTexCoord);\n" +#elif defined(GRAPHICS_API_OPENGL_33) " vec4 texelColor = texture(texture0, fragTexCoord);\n" +#endif " vec3 lighting = colAmbient.rgb;\n" " if (useNormal == 1)\n" " {\n" +#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21) +" n *= texture2D(texture1, fragTexCoord).rgb;\n" +#elif defined(GRAPHICS_API_OPENGL_33) " n *= texture(texture1, fragTexCoord).rgb;\n" +#endif " n = normalize(n);\n" " }\n" " float spec = 1.0;\n" +#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21) +" if (useSpecular == 1) spec *= normalize(texture2D(texture2, fragTexCoord).r);\n" +#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" " {\n" " if (lights[i].enabled == 1)\n" " {\n" -" switch (lights[i].type)\n" -" {\n" -" case 0: lighting += CalcPointLight(lights[i], n, v, spec); break;\n" -" case 1: lighting += CalcDirectionalLight(lights[i], n, v, spec); break;\n" -" case 2: lighting += CalcSpotLight(lights[i], n, v, spec); break;\n" -" default: break;\n" -" }\n" +" if(lights[i].type == 0) lighting += CalcPointLight(lights[i], n, v, spec);\n" +" else if(lights[i].type == 1) lighting += CalcDirectionalLight(lights[i], n, v, spec);\n" +" else if(lights[i].type == 2) lighting += CalcSpotLight(lights[i], n, v, spec);\n" " }\n" " }\n" #if defined(GRAPHICS_API_OPENGL_33) @@ -163,4 +171,4 @@ const static unsigned char fStandardShaderStr[] = #elif defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21) " gl_FragColor = vec4(texelColor.rgb*lighting*colDiffuse.rgb, texelColor.a*colDiffuse.a); \n" #endif -"} \n"; \ No newline at end of file +"}\n"; From c91401060662e2e6f828fdbeb41838ad085b436c Mon Sep 17 00:00:00 2001 From: raysan5 Date: Tue, 14 Jun 2016 18:37:28 +0200 Subject: [PATCH 10/11] Correct issue on Oculus drawing --- src/rlgl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/rlgl.c b/src/rlgl.c index 1e3928895..5d6fd9d7e 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -2562,6 +2562,8 @@ void BeginOculusDrawing(void) // - Require OculusBuffer format to be OVR_FORMAT_R8G8B8A8_UNORM_SRGB // - Do NOT enable GL_FRAMEBUFFER_SRGB //glEnable(GL_FRAMEBUFFER_SRGB); + + rlClearScreenBuffers(); // Clear current framebuffer(s) } void EndOculusDrawing(void) From d1a5374ac42e054ca65793f7358fc21bbcf393b9 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Tue, 14 Jun 2016 18:38:57 +0200 Subject: [PATCH 11/11] raylib Oculus Rift CV1 example... IT WORKS!!! --- examples/core_oculus_rift.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/examples/core_oculus_rift.c b/examples/core_oculus_rift.c index 2871407b0..865178295 100644 --- a/examples/core_oculus_rift.c +++ b/examples/core_oculus_rift.c @@ -2,6 +2,9 @@ * * raylib [core] example - Oculus Rift CV1 * +* Compile example using: +* gcc -o $(NAME_PART).exe $(FILE_NAME) -L. -L..\src\external\OculusSDK\LibOVR -lLibOVRRT32_1 -lraylib -lglfw3 -lopengl32 -lgdi32 -std=c99 +* * This example has been created using raylib 1.5 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * @@ -21,8 +24,8 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [core] example - oculus rift"); InitOculusDevice(); - - // Define the camera to look into our 3d world + + // Define the camera to look into our 3d world Camera camera; camera.position = (Vector3){ 5.0f, 5.0f, 5.0f }; // Camera position camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point @@ -30,8 +33,8 @@ int main() camera.fovy = 45.0f; // Camera field-of-view Y Vector3 cubePosition = { 0.0f, 0.0f, 0.0f }; - - SetTargetFPS(90); // Set our game to run at 90 frames-per-second + + //SetTargetFPS(90); // Set our game to run at 90 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop @@ -58,13 +61,13 @@ int main() DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED); DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, MAROON); - + DrawGrid(10, 1.0f); End3dMode(); } - EndOculusDrawing() + EndOculusDrawing(); EndDrawing(); //---------------------------------------------------------------------------------- @@ -72,7 +75,7 @@ int main() // De-Initialization //-------------------------------------------------------------------------------------- - CloseOculusdevice(); // Close Oculus Rift device + CloseOculusDevice(); // Close Oculus Rift device CloseWindow(); // Close window and OpenGL context //--------------------------------------------------------------------------------------