ソースを参照

Merge remote-tracking branch 'refs/remotes/raysan5/develop' into develop

victorfisac 9 年 前
コミット
7a09043cba
69 ファイル変更1567 行追加14259 行削除
  1. 13 10
      CHANGELOG
  2. 5 7
      HELPME.md
  3. 27 18
      README.md
  4. 1 1
      ROADMAP.md
  5. 8 2
      examples/Makefile
  6. 138 0
      examples/audio_module_playing.c
  7. BIN
      examples/audio_module_playing.png
  8. 74 0
      examples/audio_standalone.c
  9. BIN
      examples/core_2d_camera.png
  10. BIN
      examples/core_3d_camera_first_person.png
  11. BIN
      examples/core_3d_camera_free.png
  12. 12 2
      examples/core_3d_picking.c
  13. BIN
      examples/core_3d_picking.png
  14. BIN
      examples/core_input_mouse.png
  15. 2 0
      examples/core_oculus_rift.c
  16. BIN
      examples/core_oculus_rift.png
  17. BIN
      examples/core_world_screen.png
  18. 1 1
      examples/models_obj_loading.c
  19. BIN
      examples/oculus_glfw_sample/LibOVRRT32_1.dll
  20. 0 196
      examples/oculus_glfw_sample/OculusSDK/LibOVR/Include/Extras/OVR_CAPI_Util.h
  21. 0 3785
      examples/oculus_glfw_sample/OculusSDK/LibOVR/Include/Extras/OVR_Math.h
  22. 0 70
      examples/oculus_glfw_sample/OculusSDK/LibOVR/Include/Extras/OVR_StereoProjection.h
  23. 0 2116
      examples/oculus_glfw_sample/OculusSDK/LibOVR/Include/OVR_CAPI.h
  24. 0 76
      examples/oculus_glfw_sample/OculusSDK/LibOVR/Include/OVR_CAPI_Audio.h
  25. 0 155
      examples/oculus_glfw_sample/OculusSDK/LibOVR/Include/OVR_CAPI_D3D.h
  26. 0 99
      examples/oculus_glfw_sample/OculusSDK/LibOVR/Include/OVR_CAPI_GL.h
  27. 0 53
      examples/oculus_glfw_sample/OculusSDK/LibOVR/Include/OVR_CAPI_Keys.h
  28. 0 209
      examples/oculus_glfw_sample/OculusSDK/LibOVR/Include/OVR_ErrorCode.h
  29. 0 60
      examples/oculus_glfw_sample/OculusSDK/LibOVR/Include/OVR_Version.h
  30. 0 26
      examples/oculus_glfw_sample/base.vs
  31. 0 59
      examples/oculus_glfw_sample/distortion.fs
  32. 0 9
      examples/oculus_glfw_sample/glad.h
  33. 0 738
      examples/oculus_glfw_sample/oculus_glfw_sample.c
  34. BIN
      examples/oculus_glfw_sample/raylib_OculusRiftCV1_test01.png
  35. BIN
      examples/oculus_glfw_sample/raylib_OculusRiftCV1_test02.png
  36. BIN
      examples/oculus_glfw_sample/raylib_OculusRiftCV1_test03.png
  37. 0 1129
      examples/oculus_glfw_sample/raymath.h
  38. 0 3801
      examples/oculus_glfw_sample/rlgl.c
  39. 0 363
      examples/oculus_glfw_sample/rlgl.h
  40. 0 174
      examples/oculus_glfw_sample/standard_shader.h
  41. BIN
      examples/resources/audio/2t2m_spa.xm
  42. 4 16
      examples/resources/shaders/glsl100/distortion.fs
  43. 2 2
      examples/resources/shaders/glsl100/grayscale.fs
  44. 4 4
      examples/resources/shaders/glsl100/swirl.fs
  45. 6 19
      examples/resources/shaders/glsl330/distortion.fs
  46. 3 3
      examples/resources/shaders/glsl330/swirl.fs
  47. 67 170
      examples/rlgl_oculus_rift.c
  48. 21 23
      examples/rlgl_standalone.c
  49. BIN
      examples/shaders_custom_uniform.png
  50. BIN
      examples/shaders_postprocessing.png
  51. BIN
      examples/shaders_standard_lighting.png
  52. BIN
      release/android/armeabi/libraylib.a
  53. 33 24
      release/android/raylib.h
  54. BIN
      release/html5/libraylib.bc
  55. 33 24
      release/html5/raylib.h
  56. BIN
      release/win32/mingw32/libraylib.a
  57. 3 3
      src/Makefile
  58. 257 239
      src/audio.c
  59. 25 19
      src/audio.h
  60. 5 6
      src/core.c
  61. 3 12
      src/raylib.h
  62. 426 339
      src/rlgl.c
  63. 23 2
      src/rlgl.h
  64. 106 0
      src/shader_distortion.h
  65. 1 2
      src/shader_standard.h
  66. 23 6
      src/shapes.c
  67. 10 7
      src/text.c
  68. 231 180
      templates/android_project/jni/include/raylib.h
  69. BIN
      templates/android_project/jni/libs/libraylib.a

+ 13 - 10
CHANGELOG

@@ -1,24 +1,24 @@
 changelog
 ---------
 
-Current Release:    raylib 1.5.0 (xx June 2016)
+Current Release:    raylib 1.5.0 (18 July 2016)
 
 NOTE: Only versions marked as 'Release' are available in installer, updates are only available as source.
 NOTE: Current Release includes all previous updates.
 
 -----------------------------------------------
-Release:     raylib 1.5.0 (xx June 2016)
+Release:     raylib 1.5.0 (18 July 2016)
 -----------------------------------------------
 NOTE: 
   Probably this new version is the biggest boost of the library ever, lots of parts of the library have been redesigned, 
   lots of bugs have been solved and some **AMAZING** new features have been added.
 
 HUGE changes:
-[rlgl] OCULUS RIFT CV1: Added support for VR witha bunch of Oculus-specific functions to init/close device and Oculus rendering.
+[rlgl] OCULUS RIFT CV1: Added support for VR, not oly Oculus Rift CV1 but also stereo rendering simulator (multiplatform).
 [rlgl] MATERIALS SYSTEM: Added support for Materials (.mtl) and multiple material properties: diffuse, specular, normal.
-[rlgl] LIGHTING SYSTEM: Added support for up to 8 lights of 3 different types: Omni, Directional and Spot
-[physac] REDESIGNED: Improved performance and simplified usage, physic objects are managed internally
-[audio] CHIPTUNES: Added support for module audio music (.xm, .mod) loading and playing
+[rlgl] LIGHTING SYSTEM: Added support for up to 8 lights of 3 different types: Omni, Directional and Spot.
+[physac] REDESIGNED: Improved performance and simplified usage, physic objects now are managed internally in a second thread!
+[audio] CHIPTUNES: Added support for module audio music (.xm, .mod) loading and playing. Multiple mixing channels supported.
 
 other changes:
 
@@ -34,6 +34,9 @@ other changes:
 [core] Translate mouse inputs as touch inputs in HTML5
 [core] Improved function GetKeyPressed() to support multiple keys (including function keys)
 [core] Improved gamepad support, specially for RaspberryPi (including multiple gamepads support)
+[rlgl] Support stereo rendering simulation (duplicate draw calls by viewport, optimized)
+[rlgl] Added distortion shader (embeded) to support custom VR simulator: shader_distortion.h
+[rlgl] Added support for OpenGL 2.1 on desktop
 [rlgl] Improved 2D vs 3D drawing system (lines, triangles, quads)
 [rlgl] Improved DXT-ETC1 support on HTML5
 [rlgl] Review function: rlglUnproject()
@@ -43,7 +46,7 @@ other changes:
 [rlgl] Added support for indexed and dynamic mesh data
 [rlgl] Set fixed vertex attribs location points
 [rlgl] Improved mesh data loading support
-[rlgl] Added standard shader (embeded) to support materials and lighting: standard_shader.h
+[rlgl] Added standard shader (embeded) to support materials and lighting: shader_standard.h
 [rlgl] Added light functions: CreateLight(), DestroyLight()
 [rlgl] Added wire mode functions: rlDisableWireMode(), rlEnableWireMode()
 [rlgl] Review function consistency, added: rlglLoadMesh(), rlglUpdateMesh(), rlglDrawMesh(), rlglUnloadMesh()
@@ -77,23 +80,23 @@ other changes:
 [audio] Renamed SoundIsPlaying() to IsSoundPlaying()
 [audio] Renamed MusicIsPlaying() to IsMusicPlaying()
 [audio] Support multiple Music streams (indexed)
+[audio] Support multiple mixing channels
 [gestures] Improved and reviewed gestures system
 [raymath] Added QuaternionInvert()
 [raymath] Removed function: PrintMatrix()
-[raygui] Ported to header-only library
+[raygui] Ported to header-only library (https://github.com/raysan5/raygui)
 [shaders] Added depth drawing shader (requires a depth texture)
 [shaders] Reviewed included shaders and added comments
 [OpenAL Soft] Updated to latest version (1.17.2)
 [GLFW3] Updated to latest version (3.2)
-[GLAD] Converted to header only library
 [stb] Updated to latest headers versions
+[GLAD] Converted to header only library and simplified to only used extensions
 [*] Reorganize library folders: external libs moved to src/external folder
 [*] Reorganize src folder for Android library
 [*] Review external dependencies usage
 [*] Improved Linux and OSX build systems
 [*] Lots of tweaks and bugs corrected all around
 
-
 -----------------------------------------------
 Release:     raylib 1.4.0 (22 February 2016)
 -----------------------------------------------

+ 5 - 7
HELPME.md

@@ -7,23 +7,21 @@ please, [let me know][raysan5].
 The following help is highly appreciated:
 
 	- C programming - Can you write / review / test / improve the code? 
-	- Translators / Localizators - Can you translate raylib to another language?
 	- Documentation / Tutorials / Example writters - Can you write some tutorial / example?
 	- Web Development - Can you help with the web? Can you setup a forum?
-	- Porting to Linux, OSX... - Can you compile and test raylib on another OS?
+	- Porting to Linux, OSX, RaspberryPi, consoles... - Can you compile and test raylib on another systems?
 	- Testers of current features and multiple systems - Can you find some bug on raylib?
 
 If you can not help on any of the above points but you still want to contribute in some way... please, consider helping 
-with a small [donation](http://www.raylib.com/helpme.htm) (just some euros...). It will really motivate to continue improving this project (and pay some bills… or some coffee).
+with a small [donation](http://www.raylib.com/helpme.htm) or contributing with [raylib patreon](https://www.patreon.com/raysan5). It will really motivate to continue improving this project (and pay some bills… or some coffee).
 
 raylib philosophy
 ------------------
 
-   * raylib is a tool to LEARN videogames programming, every single function in raylib should be a tutorial on itself (clear code).
-   * raylib is SIMPLE and EASY-TO-USE, I tried to keep it compact with a small set of functions, if a function is too complex or 
-	 has not a clear usefulness, better not to include it.
+   * raylib is a tool to LEARN videogames programming, every single function in raylib should be a tutorial on itself.
+   * raylib is SIMPLE and EASY-TO-USE, I tried to keep it compact with a small set of functions, if a function is too complex or has not a clear usefulness, better not to include it.
    * raylib is open source and free; educators and institutions can use this tool to TEACH videogames programming completely by free. 
-   * raylib is, hopefully, collaborative; contribution of tutorials / code-examples / bugs-solving / code-comments are highly appreciated.
+   * raylib is collaborative; contribution of tutorials / code-examples / bugs-solving / code-comments are highly appreciated.
    * raylib's license (and its external libs respective licenses) allow using it for commercial products.
 
 contact

+ 27 - 18
README.md

@@ -43,7 +43,7 @@ notes on raylib 1.1
 On April 2014, after 6 month of first raylib release, raylib 1.1 has been released. This new version presents a
 complete internal redesign of the library to support OpenGL 1.1, OpenGL 3.3+ and OpenGL ES 2.0.
 
-A new module named [rlgl](https://github.com/raysan5/raylib/blob/master/src/rlgl.h) has been added to the library. This new module translate raylib-OpenGL-style 
+A new module named [rlgl](https://github.com/raysan5/raylib/blob/master/src/rlgl.h) has been added to the library. This new module translates raylib-OpenGL-style 
 immediate mode functions (i.e. rlVertex3f(), rlBegin(), ...) to different versions of OpenGL (1.1, 3.3+, ES2), selectable by one define.
 
 [rlgl](https://github.com/raysan5/raylib/blob/master/src/rlgl.h) also comes with a second new module named [raymath](https://github.com/raysan5/raylib/blob/master/src/raymath.h), which includes
@@ -83,9 +83,7 @@ Shaders support is the biggest addition to raylib 1.3, with support for easy sha
 attached to 3d models or used as fullscreen postrocessing effects. A bunch of postprocessing shaders are also included
 in this release, check raylib/shaders folder.
 
-Textures module has grown to support most of the internal texture formats available in OpenGL (RGB565, RGB888, RGBA5551, RGBA4444, etc.), 
-including compressed texture formats (DXT, ETC1, ETC2, ASTC, PVRT); raylib 1.3 can load .dds, .pkm, .ktx, .astc and .pvr files. 
-
+Textures module has grown to support most of the internal texture formats available in OpenGL (RGB565, RGB888, RGBA5551, RGBA4444, etc.), including compressed texture formats (DXT, ETC1, ETC2, ASTC, PVRT); raylib 1.3 can load .dds, .pkm, .ktx, .astc and .pvr files. 
 A brand new [camera](https://github.com/raysan5/raylib/blob/develop/src/camera.c) module offers to the user multiple preconfigured ready-to-use camera systems (free camera, 1st person, 3rd person).
 Camera modes are very easy to use, just check examples: [core_3d_camera_free.c](https://github.com/raysan5/raylib/blob/develop/examples/core_3d_camera_free.c) and [core_3d_camera_first_person.c](https://github.com/raysan5/raylib/blob/develop/examples/core_3d_camera_first_person.c).
 
@@ -133,22 +131,27 @@ Lots of code changes and lots of hours of hard work have concluded in this amazi
 notes on raylib 1.5
 -------------------
 
-On June 2016, after 4 months of raylib 1.4 release, arrives raylib 1.5. Probably this new version is the biggest boost of the library ever, lots of parts of the library have been redesigned, lots of bugs have been solved and some **AMAZING** new features have been added.
+On July 2016, after 5 months of raylib 1.4 release, arrives raylib 1.5. This new version is the biggest boost of the library until now, lots of parts of the library have been redesigned, lots of bugs have been solved and some **AMAZING** new features have been added.
+
+VR support: raylib supports **Oculus Rift CV1**, one of the most anticipated VR devices in the market. Additionally, raylib supports simulated VR stereo rendering, independent of the VR device; it means, raylib can generate stereo renders with custom head-mounted-display device parameteres, that way, any VR device in the market can be **simulated in any platform** just configuring device parameters (and consequently, lens distortion). To enable VR is [extremely easy](https://github.com/raysan5/raylib/blob/develop/examples/core_oculus_rift.c).
+
+New materials system: now raylib supports standard material properties for 3D models, including diffuse-ambient-specular colors and diffuse-normal-specular textures. Just assign values to standard material and everything is processed internally.
+
+New lighting system: added support for up to 8 configurable lights and 3 light types: **point**, **directional** and **spot** lights. Just create a light, configure its parameters and raylib manages render internally for every 3d object using standard material.
 
-New platform support: **Oculus Rift CV1**. raylib introduces VR support for one of the most anticipated VR devices in the market.
-Supporting Oculus Rift CV1 makes raylib the only (or one of the few) C libraries in the market to support VR out-of-the-box. Additionally, stereo mode rendering has been added to raylib independently of the VR device.
+Complete gamepad support on Raspberry Pi: Gamepad system has been completely redesigned. Now multiple gamepads can be easily configured and used; gamepad data is read and processed in raw mode in a second thread.
 
-New materials system:
+Redesigned physics module: [physac](https://github.com/raysan5/raylib/blob/develop/src/physac.h) module has been converted to header only and usage [has been simplified](https://github.com/raysan5/raylib/blob/develop/examples/physics_basic_rigidbody.c). Performance has also been singnificantly improved, now physic objects are managed internally in a second thread.
 
-New lighting system:
+Audio chiptunese support and mixing channels: Added support for module audio music (.xm, .mod) loading and playing. Multiple mixing channels are now also supported. All this features thanks to the amazing work of @kd7tck.
 
-Complete gamepad support on Raspberry Pi
+Other additions include a [2D camera system](https://github.com/raysan5/raylib/blob/develop/examples/core_2d_camera.c), render textures for offline render (and most comprehensive [postprocessing](https://github.com/raysan5/raylib/blob/develop/examples/shaders_postprocessing.c)) or support for legacy OpenGL 2.1 on desktop platforms.
 
-Redesigned physics module: physac
+This new version is so massive that is difficult to list all the improvements, most of raylib modules have been reviewed and [rlgl](https://github.com/raysan5/raylib/blob/develop/src/rlgl.c) module has been completely redesigned to accomodate to new material-lighting systems and stereo rendering. You can check [CHANGELOG](https://github.com/raysan5/raylib/blob/develop/CHANGELOG) file for a more detailed list of changes.
 
-Up to 8 new code examples have been added to show the new raylib features and the usage of multiple raylib modules as standalone libraries (rlgl, audio).
+Up to 8 new code examples have been added to show the new raylib features and also some samples to show the usage of [rlgl](https://github.com/raysan5/raylib/blob/develop/examples/rlgl_standalone.c) and [audio](https://github.com/raysan5/raylib/blob/develop/examples/audio_standalone.c) raylib modules as standalone libraries.
 
-Lots of code changes (more than 250 commits) and lots of hours of hard work have concluded in this amazing new raylib 1.5.
+Lots of code changes (+400 commits) and lots of hours of hard work have concluded in this amazing new raylib 1.5.
 
 features
 --------
@@ -160,10 +163,14 @@ features
    *  Powerful fonts module with multiple SpriteFonts formats support (XNA bitmap fonts, AngelCode fonts, TTF)
    *  Outstanding texture formats support, including compressed formats (DXT, ETC, PVRT, ASTC)
    *  Basic 3d support for Shapes, Models, Billboards, Heightmaps and Cubicmaps
+   *  Materials (diffuse, normal, specular) and Lighting (point, directional, spot) support
+   *  Shaders support, including Model shaders and Postprocessing shaders
    *  Powerful math module for Vector and Matrix operations: [raymath](https://github.com/raysan5/raylib/blob/master/src/raymath.c) 
-   *  Audio loading and playing with streaming support (WAV, OGG, XM, MOD)
-   *  Custom color palette for fancy visuals on raywhite background
+   *  Audio loading and playing with streaming support and mixing channels (WAV, OGG, XM, MOD)
+   *  VR stereo rendering support with configurable HMD device parameters
    *  Multiple platforms support: Windows, Linux, Mac, **Android**, **Raspberry Pi**, **HTML5** and **Oculus Rift CV1**
+   *  Custom color palette for fancy visuals on raywhite background
+   *  Minimal external dependencies (GLFW3, OpenGL, OpenAL)
 
 raylib uses on its core module the outstanding [GLFW3](http://www.glfw.org/) library. The best option by far I found for 
 multiplatform (Windows, Linux, Mac) window/context and input management (clean, focused, great license, well documented, modern, ...).
@@ -171,10 +178,12 @@ multiplatform (Windows, Linux, Mac) window/context and input management (clean,
 raylib uses on its [audio](https://github.com/raysan5/raylib/blob/master/src/audio.c) module, [OpenAL Soft](http://kcat.strangesoft.net/openal.html) audio library, in multiple flavours,
 to accomodate to Android, Raspberry Pi and HTML5.
 
-On Android, raylib uses `native_app_glue module` (provided on Android NDK) and native Android libraries to manage window/context, inputs and activity cycle.
+On Android, raylib uses `native_app_glue module` (provided by Android NDK) and native Android libraries to manage window/context, inputs and activity cycle.
 
 On Raspberry Pi, raylib uses Videocore API and EGL for window/context management and raw inputs reading.
 
+On Oculus Rift CV1, raylib uses Oculus PC SDK libraries but only the core C library ([LibOVR](https://github.com/raysan5/raylib/tree/develop/src/external/OculusSDK/LibOVR)); runtime library (LibOVRRT32_1.dll) must be linked at compilation time.
+
 raylib is licensed under a zlib/libpng license. View [LICENSE](https://github.com/raysan5/raylib/blob/master/LICENSE.md).
 
 tools requirements
@@ -196,12 +205,12 @@ Since raylib v1.1, you can download a Windows Installer package for easy install
 building source (generate libraylib.a)
 --------------------------------------
 
-Check raylib wiki page: [Building source](https://github.com/raysan5/raylib/wiki/Building-source)
+Check raylib wiki page: [Compile for...](https://github.com/raysan5/raylib/wiki)
 
 building examples
 -----------------
 
-Check raylib wiki page: [Building examples](https://github.com/raysan5/raylib/wiki/Building-examples)
+Check raylib wiki page: [Compile for...](https://github.com/raysan5/raylib/wiki)
 
 contact
 -------

+ 1 - 1
ROADMAP.md

@@ -17,7 +17,7 @@ raylib 1.x
 
 raylib 1.5
 
-    [DONE] Support Oculus Rift CV1
+    [DONE] Support Oculus Rift CV1 and VR stereo rendering (simulator)
     [DONE] Redesign Shaders/Textures system -> New Materials system
     [DONE] Support lighting: Omni, Directional and Spot lights
     [DONE] Redesign physics module (physac)

+ 8 - 2
examples/Makefile

@@ -120,8 +120,9 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
         # libraries for Debian GNU/Linux desktop compiling
         # requires the following packages:
         # libglfw3-dev libopenal-dev libegl1-mesa-dev
-        LIBS = -lraylib -lglfw3 -lGL -lopenal -lm -pthread -ldl -lX11 \
-               -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor
+        LIBS = -lraylib -lglfw3 -lGL -lopenal -lm -pthread -ldl
+        # on XWindow could require also below libraries, just uncomment
+        #LIBS += -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor
     else
     ifeq ($(PLATFORM_OS),OSX)
         # libraries for OS X 10.9 desktop compiling
@@ -208,6 +209,7 @@ EXAMPLES = \
     shaders_standard_lighting \
     audio_sound_loading \
     audio_music_stream \
+    audio_module_playing \
     fix_dylib \
 
 
@@ -434,6 +436,10 @@ audio_sound_loading: audio_sound_loading.c
 audio_music_stream: audio_music_stream.c
 	$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
 
+# compile [audio] example - module playing (OGG)
+audio_module_playing: audio_module_playing.c
+	$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
+
 # fix dylib install path name for each executable (MAC)
 fix_dylib:
 ifeq ($(PLATFORM_OS),OSX)

+ 138 - 0
examples/audio_module_playing.c

@@ -0,0 +1,138 @@
+/*******************************************************************************************
+*
+*   raylib [audio] example - Module playing (streaming)
+*
+*   NOTE: This example requires OpenAL Soft library installed
+*
+*   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)
+*
+*   Copyright (c) 2016 Ramon Santamaria (@raysan5)
+*
+********************************************************************************************/
+
+#include "raylib.h"
+
+#define MAX_CIRCLES  64
+
+typedef struct {
+    Vector2 position;
+    float radius;
+    float alpha;
+    float speed;
+    Color color;
+} CircleWave;
+
+int main()
+{
+    // Initialization
+    //--------------------------------------------------------------------------------------
+    int screenWidth = 800;
+    int screenHeight = 450;
+
+    InitWindow(screenWidth, screenHeight, "raylib [audio] example - module playing (streaming)");
+
+    InitAudioDevice();              // Initialize audio device
+    
+    Color colors[14] = { ORANGE, RED, GOLD, LIME, BLUE, VIOLET, BROWN, LIGHTGRAY, PINK,
+                         YELLOW, GREEN, SKYBLUE, PURPLE, BEIGE };
+    
+    // Creates ome circles for visual effect
+    CircleWave circles[MAX_CIRCLES];
+    
+    for (int i = MAX_CIRCLES - 1; i >= 0; i--)
+    {
+        circles[i].alpha = 0.0f;
+        circles[i].radius = GetRandomValue(10, 40);
+        circles[i].position.x = GetRandomValue(circles[i].radius, screenWidth - circles[i].radius);
+        circles[i].position.y = GetRandomValue(circles[i].radius, screenHeight - circles[i].radius);
+        circles[i].speed = (float)GetRandomValue(1, 100)/20000.0f;
+        circles[i].color = colors[GetRandomValue(0, 13)];
+    }
+    
+    // Load postprocessing bloom shader
+    Shader shader = LoadShader("resources/shaders/glsl330/base.vs", 
+                               "resources/shaders/glsl330/bloom.fs");
+
+    // Create a RenderTexture2D to be used for render to texture
+    RenderTexture2D target = LoadRenderTexture(screenWidth, screenHeight);
+
+    PlayMusicStream(0, "resources/audio/2t2m_spa.xm");         // Play module stream
+
+    float timePlayed = 0.0f;
+
+    SetTargetFPS(60);               // Set our game to run at 60 frames-per-second
+    //--------------------------------------------------------------------------------------
+
+    // Main game loop
+    while (!WindowShouldClose())    // Detect window close button or ESC key
+    {
+        // Update
+        //----------------------------------------------------------------------------------
+        for (int i = MAX_CIRCLES - 1; i >= 0; i--)
+        {
+            circles[i].alpha += circles[i].speed;
+            circles[i].radius += circles[i].speed*10.0f;
+            
+            if (circles[i].alpha > 1.0f) circles[i].speed *= -1;
+            
+            if (circles[i].alpha <= 0.0f)
+            {
+                circles[i].alpha = 0.0f;
+                circles[i].radius = GetRandomValue(10, 40);
+                circles[i].position.x = GetRandomValue(circles[i].radius, screenWidth - circles[i].radius);
+                circles[i].position.y = GetRandomValue(circles[i].radius, screenHeight - circles[i].radius);
+                circles[i].color = colors[GetRandomValue(0, 13)];
+                circles[i].speed = (float)GetRandomValue(1, 100)/20000.0f;
+            }
+        }
+
+        // Get timePlayed scaled to bar dimensions
+        timePlayed = (GetMusicTimePlayed(0)/GetMusicTimeLength(0)*(screenWidth - 40))*2;
+        
+        UpdateMusicStream(0);        // Update music buffer with new stream data
+        //----------------------------------------------------------------------------------
+
+        // Draw
+        //----------------------------------------------------------------------------------
+        BeginDrawing();
+
+            ClearBackground(BLACK);
+            
+            BeginTextureMode(target);   // Enable drawing to texture
+
+                for (int i = MAX_CIRCLES - 1; i >= 0; i--)
+                {
+                    DrawCircleV(circles[i].position, circles[i].radius, Fade(circles[i].color, circles[i].alpha));
+                }
+                
+            EndTextureMode();           // End drawing to texture (now we have a texture available for next passes)
+            
+            BeginShaderMode(shader);
+
+                // NOTE: Render texture must be y-flipped due to default OpenGL coordinates (left-bottom)
+                DrawTextureRec(target.texture, (Rectangle){ 0, 0, target.texture.width, -target.texture.height }, (Vector2){ 0, 0 }, WHITE);
+                
+            EndShaderMode();
+
+            // Draw time bar
+            DrawRectangle(20, screenHeight - 20 - 12, screenWidth - 40, 12, LIGHTGRAY);
+            DrawRectangle(20, screenHeight - 20 - 12, (int)timePlayed, 12, MAROON);
+            DrawRectangleLines(20, screenHeight - 20 - 12, screenWidth - 40, 12, WHITE);
+
+        EndDrawing();
+        //----------------------------------------------------------------------------------
+    }
+
+    // De-Initialization
+    //--------------------------------------------------------------------------------------
+    UnloadShader(shader);           // Unload shader
+    UnloadRenderTexture(target);    // Unload render texture
+    
+    CloseAudioDevice();     // Close audio device (music streaming is automatically stopped)
+
+    CloseWindow();          // Close window and OpenGL context
+    //--------------------------------------------------------------------------------------
+
+    return 0;
+}

BIN
examples/audio_module_playing.png


+ 74 - 0
examples/audio_standalone.c

@@ -0,0 +1,74 @@
+/*******************************************************************************************
+*
+*   raylib [audio] example - Using audio module as standalone module
+*
+*   NOTE: This example does not require any graphic device, it can run directly on console.
+*
+*   [audio] module requires some external libs:
+*       OpenAL Soft - Audio device management lib (http://kcat.strangesoft.net/openal.html)
+*       stb_vorbis - Ogg audio files loading (http://www.nothings.org/stb_vorbis/)
+*       jar_xm - XM module file loading
+*       jar_mod - MOD audio file loading
+*
+*   Compile audio module using:
+*   gcc -c audio.c stb_vorbis.c -Wall -std=c99 -DAUDIO_STANDALONE
+*
+*   Compile example using:
+*   gcc -o $(NAME_PART).exe $(FILE_NAME) audio.o stb_vorbis.o -lopenal32 -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)
+*
+*   Copyright (c) 2015 Ramon Santamaria (@raysan5)
+*
+********************************************************************************************/
+
+#include <stdio.h>
+#include <conio.h>      // Windows only, no stardard library
+
+#include "audio.h"
+
+#define KEY_ESCAPE  27
+
+int main()
+{
+    unsigned char key;
+    
+    InitAudioDevice();
+    
+    Sound fxWav = LoadSound("resources/audio/weird.wav");         // Load WAV audio file
+    Sound fxOgg = LoadSound("resources/audio/tanatana.ogg");      // Load OGG audio file
+    
+    PlayMusicStream(0, "resources/audio/guitar_noodling.ogg");
+
+    printf("\nPress s or d to play sounds...\n");
+    
+    while (key != KEY_ESCAPE)
+    {
+        if (kbhit()) key = getch();
+
+        if (key == 's')
+        {
+            PlaySound(fxWav);
+            key = 0;
+        }
+        
+        if (key == 'd')
+        {
+            PlaySound(fxOgg);
+            key = 0;
+        }
+        
+        UpdateMusicStream(0);
+    }
+    
+    UnloadSound(fxWav);     // Unload sound data
+    UnloadSound(fxOgg);     // Unload sound data
+    
+    CloseAudioDevice();
+    
+    printf("\n\nPress ENTER to close...");
+    getchar();
+
+    return 0;
+}

BIN
examples/core_2d_camera.png


BIN
examples/core_3d_camera_first_person.png


BIN
examples/core_3d_camera_free.png


+ 12 - 2
examples/core_3d_picking.c

@@ -68,8 +68,18 @@ int main()
 
             Begin3dMode(camera);
 
-                DrawCube(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, GRAY);
-                DrawCubeWires(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, DARKGRAY);
+                if (collision) 
+                {
+                    DrawCube(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, RED);
+                    DrawCubeWires(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, MAROON);
+
+                    DrawCubeWires(cubePosition, cubeSize.x + 0.2f, cubeSize.y + 0.2f, cubeSize.z + 0.2f, GREEN);
+                }
+                else
+                {
+                    DrawCube(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, GRAY);
+                    DrawCubeWires(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, DARKGRAY);
+                }
                 
                 DrawRay(ray, MAROON);
                 

BIN
examples/core_3d_picking.png


BIN
examples/core_input_mouse.png


+ 2 - 0
examples/core_oculus_rift.c

@@ -21,6 +21,8 @@ int main()
     int screenWidth = 1080;
     int screenHeight = 600;
     
+    // NOTE: screenWidth/screenHeight should match VR device aspect ratio
+    
     InitWindow(screenWidth, screenHeight, "raylib [core] example - oculus rift");
     
     // NOTE: If device is not available, it fallbacks to default device (simulator)

BIN
examples/core_oculus_rift.png


BIN
examples/core_world_screen.png


+ 1 - 1
examples/models_obj_loading.c

@@ -49,7 +49,7 @@ int main()
 
                 DrawModel(dwarf, position, 2.0f, WHITE);   // Draw 3d model with texture
 
-                DrawGrid(10, 1.0f);        // Draw a grid
+                DrawGrid(10, 1.0f);         // Draw a grid
 
                 DrawGizmo(position);        // Draw gizmo
 

BIN
examples/oculus_glfw_sample/LibOVRRT32_1.dll


+ 0 - 196
examples/oculus_glfw_sample/OculusSDK/LibOVR/Include/Extras/OVR_CAPI_Util.h

@@ -1,196 +0,0 @@
-/********************************************************************************//**
-\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

+ 0 - 3785
examples/oculus_glfw_sample/OculusSDK/LibOVR/Include/Extras/OVR_Math.h

@@ -1,3785 +0,0 @@
-/********************************************************************************//**
-\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 <math.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <float.h>
-#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<class T>
-const T OVRMath_Min(const T a, const T b)
-{ return (a < b) ? a : b; }
-
-template<class T>
-const T OVRMath_Max(const T a, const T b)
-{ return (b < a) ? a : b; }
-
-template<class T>
-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 T> class Quat;
-template<class T> class Size;
-template<class T> class Rect;
-template<class T> class Vector2;
-template<class T> class Vector3;
-template<class T> class Vector4;
-template<class T> class Matrix2;
-template<class T> class Matrix3;
-template<class T> class Matrix4;
-template<class T> class Pose;
-template<class T> class PoseState;
-
-// CompatibleTypes::Type is used to lookup a compatible C-version of a C++ class.
-template<class C>
-struct CompatibleTypes
-{    
-    // Declaration here seems necessary for MSVC; specializations are
-    // used instead.
-    typedef struct {} Type;
-};
-
-// Specializations providing CompatibleTypes::Type value.
-template<> struct CompatibleTypes<Quat<float> >     { typedef ovrQuatf Type; };
-template<> struct CompatibleTypes<Quat<double> >    { typedef ovrQuatd Type; };
-template<> struct CompatibleTypes<Matrix2<float> >  { typedef ovrMatrix2f Type; };
-template<> struct CompatibleTypes<Matrix2<double> > { typedef ovrMatrix2d Type; };
-template<> struct CompatibleTypes<Matrix3<float> >  { typedef ovrMatrix3f Type; };
-template<> struct CompatibleTypes<Matrix3<double> > { typedef ovrMatrix3d Type; };
-template<> struct CompatibleTypes<Matrix4<float> >  { typedef ovrMatrix4f Type; };
-template<> struct CompatibleTypes<Matrix4<double> > { typedef ovrMatrix4d Type; };
-template<> struct CompatibleTypes<Size<int> >       { typedef ovrSizei Type; };
-template<> struct CompatibleTypes<Size<float> >     { typedef ovrSizef Type; };
-template<> struct CompatibleTypes<Size<double> >    { typedef ovrSized Type; };
-template<> struct CompatibleTypes<Rect<int> >       { typedef ovrRecti Type; };
-template<> struct CompatibleTypes<Vector2<int> >    { typedef ovrVector2i Type; };
-template<> struct CompatibleTypes<Vector2<float> >  { typedef ovrVector2f Type; };
-template<> struct CompatibleTypes<Vector2<double> > { typedef ovrVector2d Type; };
-template<> struct CompatibleTypes<Vector3<float> >  { typedef ovrVector3f Type; };
-template<> struct CompatibleTypes<Vector3<double> > { typedef ovrVector3d Type; };
-template<> struct CompatibleTypes<Vector4<float> >  { typedef ovrVector4f Type; };
-template<> struct CompatibleTypes<Vector4<double> > { typedef ovrVector4d Type; };
-template<> struct CompatibleTypes<Pose<float> >     { typedef ovrPosef Type; };
-template<> struct CompatibleTypes<Pose<double> >    { typedef ovrPosed Type; };
-
-//------------------------------------------------------------------------------------//
-// ***** Math
-//
-// Math class contains constants and functions. This class is a template specialized
-// per type, with Math<float> and Math<double> being distinct.
-template<class T>
-class Math
-{  
-public:
-    // By default, support explicit conversion to float. This allows Vector2<int> 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<float>
-{
-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<double>
-{
-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<float>  Mathf;
-typedef Math<double> 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<class T>
-inline T Sqr(T x) { return x*x; }
-
-// Sign: returns 0 if x == 0, -1 if x < 0, and 1 if x > 0
-template<class T>
-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 T>
-class Quat;
-
-
-//-------------------------------------------------------------------------------------
-// ***** Vector2<>
-
-// Vector2f (Vector2d) represents a 2-dimensional vector or point in space,
-// consisting of coordinates x and y
-
-template<class T>
-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<typename Math<T>::OtherFloatType> &src)
-        : x((T)src.x), y((T)src.y) { }
-
-    static Vector2 Zero() { return Vector2(0, 0); }
-
-    // C-interop support.
-    typedef  typename CompatibleTypes<Vector2<T> >::Type CompatibleType;
-
-    Vector2(const CompatibleType& s) : x(s.x), y(s.y) {  }
-
-    operator const CompatibleType& () const
-    {
-        OVR_MATH_STATIC_ASSERT(sizeof(Vector2<T>) == sizeof(CompatibleType), "sizeof(Vector2<T>) failure");
-        return reinterpret_cast<const CompatibleType&>(*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<T>::Tolerance()) const
-    {
-        return (fabs(b.x-x) <= tolerance) &&
-               (fabs(b.y-y) <= tolerance);
-    }
-    bool Compare(const Vector2& b, T tolerance = Math<T>::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<T>::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<float>  Vector2f;
-typedef Vector2<double> Vector2d;
-typedef Vector2<int>    Vector2i;
-
-typedef Vector2<float>  Point2f;
-typedef Vector2<double> Point2d;
-typedef Vector2<int>    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 T>
-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<typename Math<T>::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<Vector3<T> >::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<T>) == sizeof(CompatibleType), "sizeof(Vector3<T>) failure");
-        return reinterpret_cast<const CompatibleType&>(*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<T>::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<T>::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<T>::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<float>  Vector3f;
-typedef Vector3<double> Vector3d;
-typedef Vector3<int32_t>  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<float>   Point3f;
-typedef Vector3<double>  Point3d;
-typedef Vector3<int32_t>  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 T>
-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<T>& v, const T w_=T(1)) : x(v.x), y(v.y), z(v.z), w(w_) { }
-    explicit Vector4(const Vector4<typename Math<T>::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<T> >::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<T>) == sizeof(CompatibleType), "sizeof(Vector4<T>) failure");
-        return reinterpret_cast<const CompatibleType&>(*this);
-    }
-
-    Vector4& operator= (const Vector3<T>& 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<T>::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<T>::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<T>::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<float>  Vector4f;
-typedef Vector4<double> Vector4d;
-typedef Vector4<int>    Vector4i;
-
-
-//-------------------------------------------------------------------------------------
-// ***** Bounds3
-
-// Bounds class used to describe a 3D axis aligned bounding box.
-
-template<class T>
-class Bounds3
-{
-public:
-    Vector3<T>    b[2];
-
-    Bounds3()
-    {
-    }
-
-    Bounds3( const Vector3<T> & mins, const Vector3<T> & maxs )
-{
-        b[0] = mins;
-        b[1] = maxs;
-    }
-
-    void Clear()
-    {
-        b[0].x = b[0].y = b[0].z = Math<T>::MaxValue;
-        b[1].x = b[1].y = b[1].z = -Math<T>::MaxValue;
-    }
-
-    void AddPoint( const Vector3<T> & 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<T> & GetMins() const { return b[0]; }
-    const Vector3<T> & GetMaxs() const { return b[1]; }
-
-    Vector3<T> & GetMins() { return b[0]; }
-    Vector3<T> & GetMaxs() { return b[1]; }
-};
-
-typedef Bounds3<float>    Bounds3f;
-typedef Bounds3<double>    Bounds3d;
-
-
-//-------------------------------------------------------------------------------------
-// ***** Size
-
-// Size class represents 2D size with Width, Height components.
-// Used to describe distentions of render targets, etc.
-
-template<class T>
-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<typename Math<T>::OtherFloatType> &src)
-        : w((T)src.w), h((T)src.h) { }
-
-    // C-interop support.
-    typedef  typename CompatibleTypes<Size<T> >::Type CompatibleType;
-
-    Size(const CompatibleType& s) : w(s.w), h(s.h) {  }
-
-    operator const CompatibleType& () const
-    {
-        OVR_MATH_STATIC_ASSERT(sizeof(Size<T>) == sizeof(CompatibleType), "sizeof(Size<T>) failure");
-        return reinterpret_cast<const CompatibleType&>(*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<T> ToVector() const     { return Vector2<T>(w, h); }
-};
-
-
-typedef Size<int>       Sizei;
-typedef Size<unsigned>  Sizeu;
-typedef Size<float>     Sizef;
-typedef Size<double>    Sized;
-
-
-
-//-----------------------------------------------------------------------------------
-// ***** Rect
-
-// Rect describes a rectangular area for rendering, that includes position and size.
-template<class T>
-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<T>& pos, const Size<T>& sz) : x(pos.x), y(pos.y), w(sz.w), h(sz.h) { }
-    Rect(const Size<T>& sz)                        : x(0), y(0), w(sz.w), h(sz.h) { }
-    
-    // C-interop support.
-    typedef  typename CompatibleTypes<Rect<T> >::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<T>) == sizeof(CompatibleType), "sizeof(Rect<T>) failure");
-        return reinterpret_cast<const CompatibleType&>(*this);
-    }
-
-    Vector2<T> GetPos() const                { return Vector2<T>(x, y); }
-    Size<T>    GetSize() const               { return Size<T>(w, h); }
-    void       SetPos(const Vector2<T>& pos) { x = pos.x; y = pos.y; }
-    void       SetSize(const Size<T>& 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<int> 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 T>
-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<typename Math<T>::OtherFloatType> &src)
-        : x((T)src.x), y((T)src.y), z((T)src.z), w((T)src.w)
-    {
-        // NOTE: Converting a normalized Quat<float> to Quat<double>
-        // 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<Quat<T> >::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<T>& 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<T> 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<T>* axis, T* angle) const
-    {
-        if ( x*x + y*y + z*z > Math<T>::Tolerance() * Math<T>::Tolerance() ) {
-            *axis  = Vector3<T>(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<T>(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<T> 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<T>(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<T> 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<T>(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<T>& 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<T>& 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<T>& 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<T>& 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<T>::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<T> Imag() const                 { return Vector3<T>(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<T>::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<T> 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<T>& alignTo, const Vector3<T>& v)
-    {
-        OVR_MATH_ASSERT(alignTo.IsNormalized() && v.IsNormalized());
-        Vector3<T> bisector = (v + alignTo);
-        bisector.Normalize();
-        T cosHalfAngle = v.Dot(bisector); // 0..1
-        if (cosHalfAngle > T(0))
-        {
-            Vector3<T> 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<T> 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<T> 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<T> Rotate(const Vector3<T>& 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<T>(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<T> InverseRotate(const Vector3<T>& 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<T>(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<T> 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<T> angularVelocity, Vector3<T> angularAcceleration, T dt) const
-    {
-        const Vector3<T>& omega = angularVelocity;
-        const Vector3<T>& omegaDot = angularAcceleration;
-
-        Vector3<T> omega1 = (omega + omegaDot * dt);
-        Vector3<T> 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<Axis_Y, Axis_X, Axis_Z, Rotate_CCW, Handed_R>(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 <Axis A1, Axis A2, Axis A3, RotateDirection D, HandedSystem S>
-    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<T>::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 <Axis A1, Axis A2, Axis A3, RotateDirection D>
-    void GetEulerAngles(T *a, T *b, T *c) const
-    { GetEulerAngles<A1, A2, A3, D, Handed_R>(a, b, c); }
-
-    template <Axis A1, Axis A2, Axis A3>
-    void GetEulerAngles(T *a, T *b, T *c) const
-    { GetEulerAngles<A1, A2, A3, Rotate_CCW, Handed_R>(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 <Axis A1, Axis A2, RotateDirection D, HandedSystem S>
-    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<T>::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<float>  Quatf;
-typedef Quat<double> 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 T>
-class Pose
-{
-public:
-    typedef typename CompatibleTypes<Pose<T> >::Type CompatibleType;
-
-    Pose() { }
-    Pose(const Quat<T>& orientation, const Vector3<T>& pos)
-        : Rotation(orientation), Translation(pos) {  }
-    Pose(const Pose& s)
-        : Rotation(s.Rotation), Translation(s.Translation) {  }
-    Pose(const Matrix3<T>& R, const Vector3<T>& t)
-        : Rotation((Quat<T>)R), Translation(t) {  }
-    Pose(const CompatibleType& s)
-        : Rotation(s.Orientation), Translation(s.Position) {  }
-
-    explicit Pose(const Pose<typename Math<T>::OtherFloatType> &s)
-        : Rotation(s.Rotation), Translation(s.Translation)
-    {
-        // Ensure normalized rotation if converting from float to double
-        if (sizeof(T) > sizeof(typename Math<T>::OtherFloatType))
-            Rotation.Normalize();
-    }
-
-    static Pose Identity() { return Pose(Quat<T>(0, 0, 0, 1), Vector3<T>(0, 0, 0)); }
-
-    void SetIdentity() { Rotation = Quat<T>(0, 0, 0, 1); Translation = Vector3<T>(0, 0, 0); }
-
-    // used to make things obviously broken if someone tries to use the value
-    void SetInvalid() { Rotation = Quat<T>(NAN, NAN, NAN, NAN); Translation = Vector3<T>(NAN, NAN, NAN); }
-
-    bool IsEqual(const Pose&b, T tolerance = Math<T>::Tolerance()) const
-    {
-        return Translation.IsEqual(b.Translation, tolerance) && Rotation.IsEqual(b.Rotation, tolerance);
-    }
-
-    operator typename CompatibleTypes<Pose<T> >::Type () const
-    {
-        typename CompatibleTypes<Pose<T> >::Type result;
-        result.Orientation = Rotation;
-        result.Position = Translation;
-        return result;
-    }
-
-    Quat<T>    Rotation;
-    Vector3<T> 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<T> FromArray(const T* v)
-    {
-        Quat<T> rotation(v[0], v[1], v[2], v[3]);
-        Vector3<T> 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<T>(rotation.Normalized(), translation);
-    }
-
-    Vector3<T> Rotate(const Vector3<T>& v) const
-    {
-        return Rotation.Rotate(v);
-    }
-
-    Vector3<T> InverseRotate(const Vector3<T>& v) const
-    {
-        return Rotation.InverseRotate(v);
-    }
-
-    Vector3<T> Translate(const Vector3<T>& v) const
-    {
-        return v + Translation;
-    }
-
-    Vector3<T> Transform(const Vector3<T>& v) const
-    {
-        return Rotate(v) + Translation;
-    }
-
-    Vector3<T> InverseTransform(const Vector3<T>& v) const
-    {
-        return InverseRotate(v - Translation);
-    }
-
-
-    Vector3<T> Apply(const Vector3<T>& v) const
-    {
-        return Transform(v);
-    }
-
-    Pose operator*(const Pose& other) const   
-    {
-        return Pose(Rotation * other.Rotation, Apply(other.Translation));
-    }
-
-    Pose Inverted() const   
-    {
-        Quat<T> 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<T>::FastSlerp.
-    Pose FastLerp(const Pose& b, T s)
-    {
-        return Pose(Rotation.FastSlerp(b.Rotation, s), Translation.Lerp(b.Translation, s));
-    }
-
-    Pose TimeIntegrate(const Vector3<T>& linearVelocity, const Vector3<T>& angularVelocity, T dt) const
-    {
-        return Pose(
-                (Rotation * Quat<T>::FastFromRotationVector(angularVelocity * dt, false)).Normalized(),
-                Translation + linearVelocity * dt);
-    }
-
-    Pose TimeIntegrate(const Vector3<T>& linearVelocity, const Vector3<T>& linearAcceleration,
-                       const Vector3<T>& angularVelocity, const Vector3<T>& angularAcceleration,
-                       T dt) const
-    {
-        return Pose(Rotation.TimeIntegrate(angularVelocity, angularAcceleration, dt),
-                    Translation + linearVelocity*dt + linearAcceleration*dt*dt * T(0.5));
-    }
-};
-
-typedef Pose<float>  Posef;
-typedef Pose<double> 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 T>
-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<T>& 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<T>& 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<T>& p)
-    {
-        Matrix4 result(p.Rotation);
-        result.SetTranslation(p.Translation);
-        *this = result;
-    }
-
-
-    // C-interop support
-    explicit Matrix4(const Matrix4<typename Math<T>::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<Matrix4<T> >::Type& s) 
-    {
-        OVR_MATH_STATIC_ASSERT(sizeof(s) == sizeof(Matrix4), "sizeof(s) == sizeof(Matrix4)");
-        memcpy(M, s.M, sizeof(M));
-    }
-
-    operator typename CompatibleTypes<Matrix4<T> >::Type () const
-    {
-        typename CompatibleTypes<Matrix4<T> >::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<T>& v)
-    {
-        M[0][0] = v.x;
-        M[1][0] = v.y;
-        M[2][0] = v.z;
-    }
-    Vector3<T> GetXBasis() const
-    {
-        return Vector3<T>(M[0][0], M[1][0], M[2][0]);
-    }
-
-    void SetYBasis(const Vector3<T> & v)
-    {
-        M[0][1] = v.x;
-        M[1][1] = v.y;
-        M[2][1] = v.z;
-    }
-    Vector3<T> GetYBasis() const
-    {
-        return Vector3<T>(M[0][1], M[1][1], M[2][1]);
-    }
-
-    void SetZBasis(const Vector3<T> & v)
-    {
-        M[0][2] = v.x;
-        M[1][2] = v.y;
-        M[2][2] = v.z;
-    }
-    Vector3<T> GetZBasis() const
-    {
-        return Vector3<T>(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<T> Transform(const Vector3<T>& 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<T>((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<T> Transform(const Vector4<T>& v) const
-    {
-        return Vector4<T>(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<T> 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 <Axis A1, Axis A2, Axis A3, RotateDirection D, HandedSystem S>
-    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<T>::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 <Axis A1, Axis A2, RotateDirection D, HandedSystem S>
-    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<T>::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<T>& 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<T>& v)
-    {
-        M[0][3] = v.x;
-        M[1][3] = v.y;
-        M[2][3] = v.z;
-    }
-
-    Vector3<T> GetTranslation() const
-    {
-        return Vector3<T>( M[0][3], M[1][3], M[2][3] );
-    }
-
-    // Creates a matrix for scaling by vector
-    static Matrix4 Scaling(const Vector3<T>& 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<T>& eye, const Vector3<T>& at, const Vector3<T>& up)
-    {
-        Vector3<T> z = (eye - at).Normalized();  // Forward
-        Vector3<T> x = up.Cross(z).Normalized(); // Right
-        Vector3<T> 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<T>& eye, const Vector3<T>& at, const Vector3<T>& up)
-    {
-        Vector3<T> z = (at - eye).Normalized();  // Forward
-        Vector3<T> x = up.Cross(z).Normalized(); // Right
-        Vector3<T> 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<float>  Matrix4f;
-typedef Matrix4<double> 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 T>
-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<T>& xBasis, const Vector3<T>& yBasis, const Vector3<T>& 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<T>& 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<typename Math<T>::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<Matrix3<T> >::Type& s) 
-    {
-        OVR_MATH_STATIC_ASSERT(sizeof(s) == sizeof(Matrix3), "sizeof(s) == sizeof(Matrix3)");
-        memcpy(M, s.M, sizeof(M));
-    }
-
-    operator const typename CompatibleTypes<Matrix3<T> >::Type () const
-    {
-        typename CompatibleTypes<Matrix3<T> >::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<T>& 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<T> 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<T> operator* (const Vector3<T> &b) const
-    {
-        Vector3<T> 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<T> Transform(const Vector2<T>& v) const
-    {
-        const T rcpZ = T(1) / (M[2][0] * v.x + M[2][1] * v.y + M[2][2]);
-        return Vector2<T>((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<T> Transform(const Vector3<T>& v) const
-    {
-        return Vector3<T>(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<T> &a, const Vector3<T> &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<T> &a, const Vector3<T> &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<T> Col(int c) const
-    {
-        return Vector3<T>(M[0][c], M[1][c], M[2][c]);
-    }
-
-    inline Vector3<T> Row(int r) const
-    {
-        return Vector3<T>(M[r][0], M[r][1], M[r][2]);
-    }
-
-    inline Vector3<T> GetColumn(int c) const
-    {
-        return Vector3<T>(M[0][c], M[1][c], M[2][c]);
-    }
-
-    inline Vector3<T> GetRow(int r) const
-    {
-        return Vector3<T>(M[r][0], M[r][1], M[r][2]);
-    }
-
-    inline void SetColumn(int c, const Vector3<T>& v)
-    {
-        M[0][c] = v.x;
-        M[1][c] = v.y;
-        M[2][c] = v.z;
-    }
-
-    inline void SetRow(int r, const Vector3<T>& v)
-    {
-        M[r][0] = v.x;
-        M[r][1] = v.y;
-        M[r][2] = v.z;
-    }
-
-    inline T Determinant() const
-    {
-        const Matrix3<T>& 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<T> Inverse() const
-    {
-        Matrix3<T> a;
-        const  Matrix3<T>& 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<T>& a, const Vector3<T>& 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<T>& 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<T>& 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<float>  Matrix3f;
-typedef Matrix3<double> Matrix3d;
-
-//-------------------------------------------------------------------------------------
-// ***** Matrix2
-
-template<class T>
-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<T>& xBasis, const Vector2<T>& 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<typename Math<T>::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<Matrix2<T> >::Type& s)
-    {
-        OVR_MATH_STATIC_ASSERT(sizeof(s) == sizeof(Matrix2), "sizeof(s) == sizeof(Matrix2)");
-        memcpy(M, s.M, sizeof(M));
-    }
-
-    operator const typename CompatibleTypes<Matrix2<T> >::Type() const
-    {
-        typename CompatibleTypes<Matrix2<T> >::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<T>& 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<T> operator* (const Vector2<T> &b) const
-    {
-        return Vector2<T>(M[0][0] * b.x + M[0][1] * b.y,
-                          M[1][0] * b.x + M[1][1] * b.y);
-    }
-
-    Vector2<T> Transform(const Vector2<T>& v) const
-    {
-        return Vector2<T>(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<T> GetColumn(int c) const
-    {
-        return Vector2<T>(M[0][c], M[1][c]);
-    }
-
-    Vector2<T> GetRow(int r) const
-    {
-        return Vector2<T>(M[r][0], M[r][1]);
-    }
-
-    void SetColumn(int c, const Vector2<T>& v)
-    {
-        M[0][c] = v.x;
-        M[1][c] = v.y;
-    }
-
-    void SetRow(int r, const Vector2<T>& 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<T>& a, const Vector2<T>& 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<float>  Matrix2f;
-typedef Matrix2<double> Matrix2d;
-
-//-------------------------------------------------------------------------------------
-
-template<class T>
-class SymMat3
-{
-private:
-    typedef SymMat3<T> 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<T>() const
-    {
-        return Matrix3<T>(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<T> &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<T> &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<T> &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<float>  SymMat3f;
-typedef SymMat3<double> SymMat3d;
-
-template<class T>
-inline Matrix3<T> operator*(const SymMat3<T>& a, const SymMat3<T>& 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<T>(
-        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<class T>
-inline Matrix3<T> operator*(const Matrix3<T>& a, const SymMat3<T>& 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<T>(
-        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 T>
-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<float>  Anglef;
-typedef Angle<double> Angled;
-
-
-//-------------------------------------------------------------------------------------
-// ***** Plane
-
-// Consists of a normal vector and distance from the origin where the plane is located.
-
-template<class T>
-class Plane
-{
-public:
-    Vector3<T> N;
-    T          D;
-
-    Plane() : D(0) {}
-
-    // Normals must already be normalized
-    Plane(const Vector3<T>& 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<T>& p, const Vector3<T>& 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<T>& p) const
-    {
-        return (N.Dot(p)) + D;
-    }
-
-    Plane<T> Flipped() const
-    {
-        return Plane(-N, -D);
-    }
-
-    void Flip()
-    {
-        N = -N;
-        D = -D;
-    }
-
-    bool operator==(const Plane<T>& rhs) const
-    {
-        return (this->D == rhs.D && this->N == rhs.N);
-    }
-};
-
-typedef Plane<float> Planef;
-typedef Plane<double> 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

+ 0 - 70
examples/oculus_glfw_sample/OculusSDK/LibOVR/Include/Extras/OVR_StereoProjection.h

@@ -1,70 +0,0 @@
-/************************************************************************************
-
-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

+ 0 - 2116
examples/oculus_glfw_sample/OculusSDK/LibOVR/Include/OVR_CAPI.h

@@ -1,2116 +0,0 @@
-/********************************************************************************//**
-\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 <stdint.h>
-
-#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,   ///< <B>(read only)</B> 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.
-///
-/// <b>Example code</b>
-///     \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.
-///
-/// <b>Example code</b>
-///     \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.
-///
-/// <b>Example code</b>
-///     \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).
-///
-/// <b>Example code</b>
-///     \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

+ 0 - 76
examples/oculus_glfw_sample/OculusSDK/LibOVR/Include/OVR_CAPI_Audio.h

@@ -1,76 +0,0 @@
-/********************************************************************************//**
-\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 <windows.h>
-#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

+ 0 - 155
examples/oculus_glfw_sample/OculusSDK/LibOVR/Include/OVR_CAPI_D3D.h

@@ -1,155 +0,0 @@
-/********************************************************************************//**
-\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 <Unknwn.h>
-
-//-----------------------------------------------------------------------------------
-// ***** 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.
-///
-/// <b>Example code</b>
-///     \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.
-///
-///
-/// <b>Example code</b>
-///     \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.
-///
-/// <b>Example code</b>
-///     \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

+ 0 - 99
examples/oculus_glfw_sample/OculusSDK/LibOVR/Include/OVR_CAPI_GL.h

@@ -1,99 +0,0 @@
-/********************************************************************************//**
-\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

+ 0 - 53
examples/oculus_glfw_sample/OculusSDK/LibOVR/Include/OVR_CAPI_Keys.h

@@ -1,53 +0,0 @@
-/********************************************************************************//**
-\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

+ 0 - 209
examples/oculus_glfw_sample/OculusSDK/LibOVR/Include/OVR_ErrorCode.h

@@ -1,209 +0,0 @@
-/********************************************************************************//**
-\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 <stdint.h>
-
-
-
-
-
-
-
-#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,///<Content protection is not available for the display
-    ovrError_ApplicationInvisible       = -6006,   ///< Application declared itself as an invisible type and is not allowed to submit frames.
-    ovrError_Disallowed                 = -6007,   ///< The given request is disallowed under the current conditions.
-    ovrError_DisplayPluggedIncorrectly  = -6008,   ///< Display portion of HMD is plugged into an incompatible port (ex: IGP)
-
-    /* Fatal errors */
-    ovrError_RuntimeException           = -7000,   ///< A runtime exception occurred. The application is required to shutdown LibOVR and re-initialize it before this error state will be cleared.
-
-
-    ovrError_MetricsUnknownApp            = -90000,
-    ovrError_MetricsDuplicateApp          = -90001,
-    ovrError_MetricsNoEvents              = -90002,
-    ovrError_MetricsRuntime               = -90003,
-    ovrError_MetricsFile                  = -90004,
-    ovrError_MetricsNoClientInfo          = -90005,
-    ovrError_MetricsNoAppMetaData         = -90006,
-    ovrError_MetricsNoApp                 = -90007,
-    ovrError_MetricsOafFailure            = -90008,
-    ovrError_MetricsSessionAlreadyActive  = -90009,
-    ovrError_MetricsSessionNotActive      = -90010,
-
-} ovrErrorType;
-
-
-
-/// Provides information about the last error.
-/// \see ovr_GetLastErrorInfo
-typedef struct ovrErrorInfo_
-{
-    ovrResult Result;               ///< The result from the last API call that generated an error ovrResult.
-    char      ErrorString[512];     ///< A UTF8-encoded null-terminated English string describing the problem. The format of this string is subject to change in future versions.
-} ovrErrorInfo;
-
-#endif /* OVR_ErrorCode_h */

+ 0 - 60
examples/oculus_glfw_sample/OculusSDK/LibOVR/Include/OVR_Version.h

@@ -1,60 +0,0 @@
-/********************************************************************************//**
-\file      OVR_Version.h
-\brief     This header provides LibOVR version identification.
-\copyright Copyright 2014-2016 Oculus VR, LLC All Rights reserved.
-*************************************************************************************/
-
-#ifndef OVR_Version_h
-#define OVR_Version_h
-
-
-
-/// Conventional string-ification macro.
-#if !defined(OVR_STRINGIZE)
-    #define OVR_STRINGIZEIMPL(x) #x
-    #define OVR_STRINGIZE(x)     OVR_STRINGIZEIMPL(x)
-#endif
-
-
-// Master version numbers
-#define OVR_PRODUCT_VERSION 1  // Product version doesn't participate in semantic versioning.
-#define OVR_MAJOR_VERSION   1  // If you change these values then you need to also make sure to change LibOVR/Projects/Windows/LibOVR.props in parallel.
-#define OVR_MINOR_VERSION   4  // 
-#define OVR_PATCH_VERSION   0
-#define OVR_BUILD_NUMBER    0
-
-// This is the ((product * 100) + major) version of the service that the DLL is compatible with.
-// When we backport changes to old versions of the DLL we update the old DLLs
-// to move this version number up to the latest version.
-// The DLL is responsible for checking that the service is the version it supports
-// and returning an appropriate error message if it has not been made compatible.
-#define OVR_DLL_COMPATIBLE_VERSION 101
-
-#define OVR_FEATURE_VERSION 0
-
-
-/// "Major.Minor.Patch"
-#if !defined(OVR_VERSION_STRING)
-    #define OVR_VERSION_STRING  OVR_STRINGIZE(OVR_MAJOR_VERSION.OVR_MINOR_VERSION.OVR_PATCH_VERSION)
-#endif
-
-
-/// "Major.Minor.Patch.Build"
-#if !defined(OVR_DETAILED_VERSION_STRING)
-    #define OVR_DETAILED_VERSION_STRING OVR_STRINGIZE(OVR_MAJOR_VERSION.OVR_MINOR_VERSION.OVR_PATCH_VERSION.OVR_BUILD_NUMBER)
-#endif
-
-
-/// \brief file description for version info
-/// This appears in the user-visible file properties. It is intended to convey publicly
-/// available additional information such as feature builds.
-#if !defined(OVR_FILE_DESCRIPTION_STRING)
-    #if defined(_DEBUG)
-        #define OVR_FILE_DESCRIPTION_STRING "dev build debug"
-    #else
-        #define OVR_FILE_DESCRIPTION_STRING "dev build"
-    #endif
-#endif
-
-
-#endif // OVR_Version_h

+ 0 - 26
examples/oculus_glfw_sample/base.vs

@@ -1,26 +0,0 @@
-#version 330
-
-// Input vertex attributes
-in vec3 vertexPosition;
-in vec2 vertexTexCoord;
-in vec3 vertexNormal;
-in vec4 vertexColor;
-
-// Input uniform values
-uniform mat4 mvpMatrix;
-
-// Output vertex attributes (to fragment shader)
-out vec2 fragTexCoord;
-out vec4 fragColor;
-
-// NOTE: Add here your custom variables 
-
-void main()
-{
-    // Send vertex attributes to fragment shader
-    fragTexCoord = vertexTexCoord;
-    fragColor = vertexColor;
-    
-    // Calculate final vertex position
-    gl_Position = mvpMatrix*vec4(vertexPosition, 1.0);
-}

+ 0 - 59
examples/oculus_glfw_sample/distortion.fs

@@ -1,59 +0,0 @@
-#version 330
-
-// Input vertex attributes (from vertex shader)
-in vec2 fragTexCoord;
-
-// Input uniform values
-uniform sampler2D texture0;
-
-// Output fragment color
-out vec4 finalColor;
-
-// NOTE: Add here your custom variables
-const vec2 LeftLensCenter = vec2(0.2863248, 0.5);
-const vec2 RightLensCenter = vec2(0.7136753, 0.5);
-const vec2 LeftScreenCenter = vec2(0.25, 0.5);
-const vec2 RightScreenCenter = vec2(0.75, 0.5);
-const vec2 Scale = vec2(0.25, 0.45);    //vec2(0.1469278, 0.2350845);
-const vec2 ScaleIn = vec2(4, 2.2222);
-const vec4 HmdWarpParam = vec4(1, 0.22, 0.24, 0);
-
-/*
-// Another set of default values
-ChromaAbCorrection = {1.0, 0.0, 1.0, 0}
-DistortionK = {1.0, 0.22, 0.24, 0}
-Scale = {0.25, 0.5*AspectRatio, 0, 0}
-ScaleIn = {4.0, 2/AspectRatio, 0, 0}
-Left Screen Center = {0.25, 0.5, 0, 0}
-Left Lens Center = {0.287994117, 0.5, 0, 0}
-Right Screen Center = {0.75, 0.5, 0, 0}
-Right Lens Center = {0.712005913, 0.5, 0, 0}
-*/
-
-// Scales input texture coordinates for distortion.
-vec2 HmdWarp(vec2 in01, vec2 LensCenter)
-{
-    vec2 theta = (in01 - LensCenter)*ScaleIn; // Scales to [-1, 1]
-    float rSq = theta.x*theta.x + theta.y*theta.y;
-    vec2 rvector = theta*(HmdWarpParam.x + HmdWarpParam.y*rSq + HmdWarpParam.z*rSq*rSq + HmdWarpParam.w*rSq*rSq*rSq);
-
-    return LensCenter + Scale*rvector;
-}
-
-void main()
-{
-    // SOURCE: http://www.mtbs3d.com/phpbb/viewtopic.php?f=140&t=17081
-    
-    // The following two variables need to be set per eye
-    vec2 LensCenter = gl_FragCoord.x < 540 ? LeftLensCenter : RightLensCenter;
-    vec2 ScreenCenter = gl_FragCoord.x < 540 ? LeftScreenCenter : RightScreenCenter;
-
-    vec2 tc = HmdWarp(fragTexCoord, LensCenter);
-
-    if (any(bvec2(clamp(tc,ScreenCenter-vec2(0.25,0.5), ScreenCenter+vec2(0.25,0.5)) - tc))) finalColor = vec4(0.0, 0.0, 0.0, 1.0);
-    else
-    {
-        //tc.x = gl_FragCoord.x < 640 ? (2.0 * tc.x) : (2.0 * (tc.x - 0.5));
-        finalColor = texture2D(texture0, tc);
-    }
-}

ファイルの差分が大きいため隠しています
+ 0 - 9
examples/oculus_glfw_sample/glad.h


+ 0 - 738
examples/oculus_glfw_sample/oculus_glfw_sample.c

@@ -1,738 +0,0 @@
-/*******************************************************************************************
-*
-*   raylib Oculus minimum sample (OpenGL 3.3 Core)
-*
-*   NOTE: This example requires raylib module [rlgl]
-*
-*   Compile rlgl module using:
-*   gcc -c rlgl.c -Wall -std=c99 -DRLGL_STANDALONE -DRAYMATH_IMPLEMENTATION -DGRAPHICS_API_OPENGL_33
-*
-*   Compile example using:
-*   gcc -o oculus_glfw_sample.exe oculus_glfw_sample.c rlgl.o -L. -lLibOVRRT32_1 -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)
-*
-*   Copyright (c) 2015 Ramon Santamaria (@raysan5)
-*
-********************************************************************************************/
-
-#include <stdlib.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-#include <math.h>
-
-#include "glad.h"
-#include <GLFW/glfw3.h>         // Windows/Context and inputs management
-
-#define RLGL_STANDALONE
-#include "rlgl.h"               // rlgl library: OpenGL 1.1 immediate-mode style coding
-
-#define PLATFORM_OCULUS
-
-#if defined(PLATFORM_OCULUS)
-    #include "OculusSDK/LibOVR/Include/OVR_CAPI_GL.h"    // Oculus SDK for OpenGL
-#endif
-
-#if defined(PLATFORM_OCULUS)
-// OVR device variables
-ovrSession session;
-ovrHmdDesc hmdDesc;
-ovrGraphicsLuid luid;
-#endif
-
-unsigned int frameIndex = 0;
-
-#define RED        (Color){ 230, 41, 55, 255 }     // Red
-#define MAROON     (Color){ 190, 33, 55, 255 }     // Maroon
-#define RAYWHITE   (Color){ 245, 245, 245, 255 }   // My own White (raylib logo)
-#define DARKGRAY   (Color){ 80, 80, 80, 255 }      // Dark Gray
-
-//----------------------------------------------------------------------------------
-// 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
-
-//----------------------------------------------------------------------------------
-// Module specific Functions Declaration
-//----------------------------------------------------------------------------------
-static void ErrorCallback(int error, const char* description);
-static void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
-
-// Drawing functions (uses rlgl functionality)
-static void DrawGrid(int slices, float spacing);
-static void DrawCube(Vector3 position, float width, float height, float length, Color color);
-static void DrawCubeWires(Vector3 position, float width, float height, float length, Color color);
-static void DrawRectangleV(Vector2 position, Vector2 size, Color color);
-
-#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
-
-//----------------------------------------------------------------------------------
-// Main Entry point
-//----------------------------------------------------------------------------------
-int main(void)
-{
-    // Initialization
-    //--------------------------------------------------------------------------------------
-    int screenWidth = 1080;     // Mirror screen width (set to hmdDesc.Resolution.w/2)
-    int screenHeight = 600;     // Mirror screen height (set to hmdDesc.Resolution.h/2)
-    
-    // NOTE: Mirror screen size can be set to any desired resolution!
-    
-    // GLFW3 Initialization + OpenGL 3.3 Context + Extensions
-    //--------------------------------------------------------
-    glfwSetErrorCallback(ErrorCallback);
-    
-    if (!glfwInit())
-    {
-        TraceLog(WARNING, "GLFW3: Can not initialize GLFW");
-        return 1;
-    }
-    else TraceLog(INFO, "GLFW3: GLFW initialized successfully");
-    
-    glfwWindowHint(GLFW_DEPTH_BITS, 16);
-    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
-    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
-    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
-    glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
-   
-    GLFWwindow *window = glfwCreateWindow(screenWidth, screenHeight, "raylib oculus sample", NULL, NULL);
-    
-    if (!window)
-    {
-        glfwTerminate();
-        return 2;
-    }
-    else TraceLog(INFO, "GLFW3: Window created successfully");
-    
-    glfwSetKeyCallback(window, KeyCallback);
-    
-    glfwMakeContextCurrent(window);
-    glfwSwapInterval(0);
-
-    // Load OpenGL 3.3 extensions
-    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(ERROR, "OVR: Could not initialize Oculus device");
-
-    result = ovr_Create(&session, &luid);
-    if (OVR_FAILURE(result))
-    {
-        TraceLog(WARNING, "OVR: Could not create Oculus session");
-        ovr_Shutdown();
-    }
-
-    hmdDesc = ovr_GetHmdDesc(session);
-    
-    TraceLog(INFO, "OVR: Product Name: %s", hmdDesc.ProductName);
-    TraceLog(INFO, "OVR: Manufacturer: %s", hmdDesc.Manufacturer);
-    TraceLog(INFO, "OVR: Product ID: %i", hmdDesc.ProductId);
-    TraceLog(INFO, "OVR: Product Type: %i", hmdDesc.Type);
-    TraceLog(INFO, "OVR: Serian Number: %s", hmdDesc.SerialNumber);
-    TraceLog(INFO, "OVR: Resolution: %ix%i", hmdDesc.Resolution.w, hmdDesc.Resolution.h);
-    
-    //screenWidth = hmdDesc.Resolution.w/2;
-    //screenHeight = hmdDesc.Resolution.h/2;
-
-    // Initialize Oculus Buffers
-    OculusLayer layer = InitOculusLayer(session);   
-    OculusBuffer buffer = LoadOculusBuffer(session, layer.width, layer.height);
-    OculusMirror mirror = LoadOculusMirror(session, screenWidth, screenHeight);
-    layer.eyeLayer.ColorTexture[0] = buffer.textureChain;     //SetOculusLayerTexture(eyeLayer, buffer.textureChain);
-
-    // Recenter OVR tracking origin
-    ovr_RecenterTrackingOrigin(session);
-#endif
-    
-    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    
-    while (!glfwWindowShouldClose(window)) 
-    {
-        // Update
-        //----------------------------------------------------------------------------------
-#if defined(PLATFORM_OCULUS)
-        frameIndex++;
-        
-        ovrPosef eyePoses[2];
-        ovr_GetEyePoses(session, frameIndex, ovrTrue, layer.viewScaleDesc.HmdToEyeOffset, eyePoses, &layer.eyeLayer.SensorSampleTime);
-        
-        layer.eyeLayer.RenderPose[0] = eyePoses[0];
-        layer.eyeLayer.RenderPose[1] = eyePoses[1];
-#endif
-        Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up);
-        //----------------------------------------------------------------------------------
-
-        // Draw
-        //----------------------------------------------------------------------------------
-#if defined(PLATFORM_OCULUS)
-        SetOculusBuffer(session, buffer);
-#endif
-        rlClearScreenBuffers();             // Clear current framebuffer(s)
-
-#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 modelview = MatrixMultiply(matView, eyeView);
-
-			SetMatrixModelview(modelview);
-			SetMatrixProjection(layer.eyeProjections[eye]);
-#else
-            // Calculate projection matrix (from perspective) and view matrix from camera look at
-            Matrix matProj = MatrixPerspective(camera.fovy, (double)screenWidth/(double)screenHeight, 0.01, 1000.0);
-            MatrixTranspose(&matProj);
-			
-            SetMatrixModelview(matView);    // Replace internal modelview matrix by a custom one
-            SetMatrixProjection(matProj);   // Replace internal projection matrix by a custom one
-#endif
-            DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED);
-            DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, RAYWHITE);
-            DrawGrid(10, 1.0f);
-
-            // NOTE: Internal buffers drawing (3D data)
-            rlglDraw();
-            
-#if !defined(PLATFORM_OCULUS)
-            // Draw '2D' elements in the scene (GUI)
-            // TODO: 2D drawing on Oculus Rift: requires an ovrLayerQuad layer
-            rlMatrixMode(RL_PROJECTION);                            // Enable internal projection matrix
-            rlLoadIdentity();                                       // Reset internal projection matrix
-            rlOrtho(0.0, screenWidth, screenHeight, 0.0, 0.0, 1.0); // Recalculate internal projection matrix
-            rlMatrixMode(RL_MODELVIEW);                             // Enable internal modelview matrix
-            rlLoadIdentity();                                       // Reset internal modelview matrix
-            
-            DrawRectangleV((Vector2){ 10.0f, 10.0f }, (Vector2){ 600.0f, 20.0f }, DARKGRAY);
-
-            // NOTE: Internal buffers drawing (2D data)
-            rlglDraw();
-#endif
-#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
-
-        glfwSwapBuffers(window);
-        glfwPollEvents();
-        //----------------------------------------------------------------------------------
-    }
-
-    // De-Initialization
-    //--------------------------------------------------------------------------------------
-#if defined(PLATFORM_OCULUS)
-    UnloadOculusMirror(session, mirror);    // Unload Oculus mirror buffer
-    UnloadOculusBuffer(session, buffer);    // Unload Oculus texture buffers
-
-    ovr_Destroy(session);   // Must be called after glfwTerminate() --> no
-    ovr_Shutdown();
-#endif
-
-    rlglClose();                            // Unload rlgl internal buffers and default shader/texture
-    
-    glfwDestroyWindow(window);
-    glfwTerminate();
-    //--------------------------------------------------------------------------------------
-    
-    return 0;
-}
-
-//----------------------------------------------------------------------------------
-// Module specific Functions Definitions
-//----------------------------------------------------------------------------------
-
-// GLFW3: Error callback
-static void ErrorCallback(int error, const char* description)
-{
-    TraceLog(ERROR, description);
-}
-
-// GLFW3: Keyboard callback
-static void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
-{
-    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
-    {
-        glfwSetWindowShouldClose(window, GL_TRUE);
-    }
-}
-
-// Draw rectangle using rlgl OpenGL 1.1 style coding (translated to OpenGL 3.3 internally)
-static void DrawRectangleV(Vector2 position, Vector2 size, Color color)
-{
-    rlBegin(RL_TRIANGLES);
-        rlColor4ub(color.r, color.g, color.b, color.a);
-
-        rlVertex2i(position.x, position.y);
-        rlVertex2i(position.x, position.y + size.y);
-        rlVertex2i(position.x + size.x, position.y + size.y);
-
-        rlVertex2i(position.x, position.y);
-        rlVertex2i(position.x + size.x, position.y + size.y);
-        rlVertex2i(position.x + size.x, position.y);
-    rlEnd();
-}
-
-// Draw a grid centered at (0, 0, 0)
-static void DrawGrid(int slices, float spacing)
-{
-    int halfSlices = slices / 2;
-
-    rlBegin(RL_LINES);
-        for(int i = -halfSlices; i <= halfSlices; i++)
-        {
-            if (i == 0)
-            {
-                rlColor3f(0.5f, 0.5f, 0.5f);
-                rlColor3f(0.5f, 0.5f, 0.5f);
-                rlColor3f(0.5f, 0.5f, 0.5f);
-                rlColor3f(0.5f, 0.5f, 0.5f);
-            }
-            else
-            {
-                rlColor3f(0.75f, 0.75f, 0.75f);
-                rlColor3f(0.75f, 0.75f, 0.75f);
-                rlColor3f(0.75f, 0.75f, 0.75f);
-                rlColor3f(0.75f, 0.75f, 0.75f);
-            }
-
-            rlVertex3f((float)i*spacing, 0.0f, (float)-halfSlices*spacing);
-            rlVertex3f((float)i*spacing, 0.0f, (float)halfSlices*spacing);
-
-            rlVertex3f((float)-halfSlices*spacing, 0.0f, (float)i*spacing);
-            rlVertex3f((float)halfSlices*spacing, 0.0f, (float)i*spacing);
-        }
-    rlEnd();
-}
-
-// Draw cube
-// NOTE: Cube position is the center position
-void DrawCube(Vector3 position, float width, float height, float length, Color color)
-{
-    float x = 0.0f;
-    float y = 0.0f;
-    float z = 0.0f;
-
-    rlPushMatrix();
-
-        // NOTE: Be careful! Function order matters (rotate -> scale -> translate)
-        rlTranslatef(position.x, position.y, position.z);
-        //rlScalef(2.0f, 2.0f, 2.0f);
-        //rlRotatef(45, 0, 1, 0);
-
-        rlBegin(RL_TRIANGLES);
-            rlColor4ub(color.r, color.g, color.b, color.a);
-
-            // Front Face -----------------------------------------------------
-            rlVertex3f(x-width/2, y-height/2, z+length/2);  // Bottom Left
-            rlVertex3f(x+width/2, y-height/2, z+length/2);  // Bottom Right
-            rlVertex3f(x-width/2, y+height/2, z+length/2);  // Top Left
-
-            rlVertex3f(x+width/2, y+height/2, z+length/2);  // Top Right
-            rlVertex3f(x-width/2, y+height/2, z+length/2);  // Top Left
-            rlVertex3f(x+width/2, y-height/2, z+length/2);  // Bottom Right
-
-            // Back Face ------------------------------------------------------
-            rlVertex3f(x-width/2, y-height/2, z-length/2);  // Bottom Left
-            rlVertex3f(x-width/2, y+height/2, z-length/2);  // Top Left
-            rlVertex3f(x+width/2, y-height/2, z-length/2);  // Bottom Right
-
-            rlVertex3f(x+width/2, y+height/2, z-length/2);  // Top Right
-            rlVertex3f(x+width/2, y-height/2, z-length/2);  // Bottom Right
-            rlVertex3f(x-width/2, y+height/2, z-length/2);  // Top Left
-
-            // Top Face -------------------------------------------------------
-            rlVertex3f(x-width/2, y+height/2, z-length/2);  // Top Left
-            rlVertex3f(x-width/2, y+height/2, z+length/2);  // Bottom Left
-            rlVertex3f(x+width/2, y+height/2, z+length/2);  // Bottom Right
-
-            rlVertex3f(x+width/2, y+height/2, z-length/2);  // Top Right
-            rlVertex3f(x-width/2, y+height/2, z-length/2);  // Top Left
-            rlVertex3f(x+width/2, y+height/2, z+length/2);  // Bottom Right
-
-            // Bottom Face ----------------------------------------------------
-            rlVertex3f(x-width/2, y-height/2, z-length/2);  // Top Left
-            rlVertex3f(x+width/2, y-height/2, z+length/2);  // Bottom Right
-            rlVertex3f(x-width/2, y-height/2, z+length/2);  // Bottom Left
-
-            rlVertex3f(x+width/2, y-height/2, z-length/2);  // Top Right
-            rlVertex3f(x+width/2, y-height/2, z+length/2);  // Bottom Right
-            rlVertex3f(x-width/2, y-height/2, z-length/2);  // Top Left
-
-            // Right face -----------------------------------------------------
-            rlVertex3f(x+width/2, y-height/2, z-length/2);  // Bottom Right
-            rlVertex3f(x+width/2, y+height/2, z-length/2);  // Top Right
-            rlVertex3f(x+width/2, y+height/2, z+length/2);  // Top Left
-
-            rlVertex3f(x+width/2, y-height/2, z+length/2);  // Bottom Left
-            rlVertex3f(x+width/2, y-height/2, z-length/2);  // Bottom Right
-            rlVertex3f(x+width/2, y+height/2, z+length/2);  // Top Left
-
-            // Left Face ------------------------------------------------------
-            rlVertex3f(x-width/2, y-height/2, z-length/2);  // Bottom Right
-            rlVertex3f(x-width/2, y+height/2, z+length/2);  // Top Left
-            rlVertex3f(x-width/2, y+height/2, z-length/2);  // Top Right
-
-            rlVertex3f(x-width/2, y-height/2, z+length/2);  // Bottom Left
-            rlVertex3f(x-width/2, y+height/2, z+length/2);  // Top Left
-            rlVertex3f(x-width/2, y-height/2, z-length/2);  // Bottom Right
-        rlEnd();
-    rlPopMatrix();
-}
-
-// Draw cube wires
-void DrawCubeWires(Vector3 position, float width, float height, float length, Color color)
-{
-    float x = 0.0f;
-    float y = 0.0f;
-    float z = 0.0f;
-
-    rlPushMatrix();
-
-        rlTranslatef(position.x, position.y, position.z);
-        //rlRotatef(45, 0, 1, 0);
-
-        rlBegin(RL_LINES);
-            rlColor4ub(color.r, color.g, color.b, color.a);
-
-            // Front Face -----------------------------------------------------
-            // Bottom Line
-            rlVertex3f(x-width/2, y-height/2, z+length/2);  // Bottom Left
-            rlVertex3f(x+width/2, y-height/2, z+length/2);  // Bottom Right
-
-            // Left Line
-            rlVertex3f(x+width/2, y-height/2, z+length/2);  // Bottom Right
-            rlVertex3f(x+width/2, y+height/2, z+length/2);  // Top Right
-
-            // Top Line
-            rlVertex3f(x+width/2, y+height/2, z+length/2);  // Top Right
-            rlVertex3f(x-width/2, y+height/2, z+length/2);  // Top Left
-
-            // Right Line
-            rlVertex3f(x-width/2, y+height/2, z+length/2);  // Top Left
-            rlVertex3f(x-width/2, y-height/2, z+length/2);  // Bottom Left
-
-            // Back Face ------------------------------------------------------
-            // Bottom Line
-            rlVertex3f(x-width/2, y-height/2, z-length/2);  // Bottom Left
-            rlVertex3f(x+width/2, y-height/2, z-length/2);  // Bottom Right
-
-            // Left Line
-            rlVertex3f(x+width/2, y-height/2, z-length/2);  // Bottom Right
-            rlVertex3f(x+width/2, y+height/2, z-length/2);  // Top Right
-
-            // Top Line
-            rlVertex3f(x+width/2, y+height/2, z-length/2);  // Top Right
-            rlVertex3f(x-width/2, y+height/2, z-length/2);  // Top Left
-
-            // Right Line
-            rlVertex3f(x-width/2, y+height/2, z-length/2);  // Top Left
-            rlVertex3f(x-width/2, y-height/2, z-length/2);  // Bottom Left
-
-            // Top Face -------------------------------------------------------
-            // Left Line
-            rlVertex3f(x-width/2, y+height/2, z+length/2);  // Top Left Front
-            rlVertex3f(x-width/2, y+height/2, z-length/2);  // Top Left Back
-
-            // Right Line
-            rlVertex3f(x+width/2, y+height/2, z+length/2);  // Top Right Front
-            rlVertex3f(x+width/2, y+height/2, z-length/2);  // Top Right Back
-
-            // Bottom Face  ---------------------------------------------------
-            // Left Line
-            rlVertex3f(x-width/2, y-height/2, z+length/2);  // Top Left Front
-            rlVertex3f(x-width/2, y-height/2, z-length/2);  // Top Left Back
-
-            // Right Line
-            rlVertex3f(x+width/2, y-height/2, z+length/2);  // Top Right Front
-            rlVertex3f(x+width/2, y-height/2, z-length/2);  // Top Right Back
-        rlEnd();
-    rlPopMatrix();
-}
-
-#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, &currentIndex);
-    ovr_GetTextureSwapChainBufferGL(session, buffer.textureChain, currentIndex, &currentTexId);
-
-    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);
-}
-
-// 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

BIN
examples/oculus_glfw_sample/raylib_OculusRiftCV1_test01.png


BIN
examples/oculus_glfw_sample/raylib_OculusRiftCV1_test02.png


BIN
examples/oculus_glfw_sample/raylib_OculusRiftCV1_test03.png


+ 0 - 1129
examples/oculus_glfw_sample/raymath.h

@@ -1,1129 +0,0 @@
-/**********************************************************************************************
-*
-*   raymath (header only file)
-*
-*   Some useful functions to work with Vector3, Matrix and Quaternions
-*
-*   You must:
-*       #define RAYMATH_IMPLEMENTATION
-*   before you include this file in *only one* C or C++ file to create the implementation.
-*
-*   Example:
-*       #define RAYMATH_IMPLEMENTATION
-*       #include "raymath.h"
-*
-*   You can also use:
-*       #define RAYMATH_EXTERN_INLINE       // Inlines all functions code, so it runs faster.
-*                                           // This requires lots of memory on system.
-*       #define RAYMATH_STANDALONE          // Not dependent on raylib.h structs: Vector3, Matrix.
-*
-*
-*   Copyright (c) 2015 Ramon Santamaria (@raysan5)
-*
-*   This software is provided "as-is", without any express or implied warranty. In no event
-*   will the authors be held liable for any damages arising from the use of this software.
-*
-*   Permission is granted to anyone to use this software for any purpose, including commercial
-*   applications, and to alter it and redistribute it freely, subject to the following restrictions:
-*
-*     1. The origin of this software must not be misrepresented; you must not claim that you
-*     wrote the original software. If you use this software in a product, an acknowledgment
-*     in the product documentation would be appreciated but is not required.
-*
-*     2. Altered source versions must be plainly marked as such, and must not be misrepresented
-*     as being the original software.
-*
-*     3. This notice may not be removed or altered from any source distribution.
-*
-**********************************************************************************************/
-
-#ifndef RAYMATH_H
-#define RAYMATH_H
-
-//#define RAYMATH_STANDALONE        // NOTE: To use raymath as standalone lib, just uncomment this line
-//#define RAYMATH_EXTERN_INLINE     // NOTE: To compile functions as static inline, uncomment this line
-
-#ifndef RAYMATH_STANDALONE
-    #include "raylib.h"             // Required for structs: Vector3, Matrix
-#endif
-
-#ifdef __cplusplus
-    #define RMEXTERN extern "C"     // Functions visible from other files (no name mangling of functions in C++)
-#else
-    #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
-
-//----------------------------------------------------------------------------------
-// Defines and Macros
-//----------------------------------------------------------------------------------
-#ifndef PI
-    #define PI 3.14159265358979323846
-#endif
-
-#ifndef DEG2RAD
-    #define DEG2RAD (PI/180.0f)
-#endif
-
-#ifndef RAD2DEG
-    #define RAD2DEG (180.0f/PI)
-#endif
-
-//----------------------------------------------------------------------------------
-// Types and Structures Definition
-//----------------------------------------------------------------------------------
-
-#if defined(RAYMATH_STANDALONE)
-    // Vector2 type
-    typedef struct Vector2 {
-        float x;
-        float y;
-    } Vector2;
-
-    // Vector3 type
-    typedef struct Vector3 {
-        float x;
-        float y;
-        float z;
-    } Vector3;
-
-    // Matrix type (OpenGL style 4x4 - right handed, column major)
-    typedef struct Matrix {
-        float m0, m4, m8, m12;
-        float m1, m5, m9, m13;
-        float m2, m6, m10, m14;
-        float m3, m7, m11, m15;
-    } Matrix;
-#endif
-
-// Quaternion type
-typedef struct Quaternion {
-    float x;
-    float y;
-    float z;
-    float w;
-} Quaternion;
-
-#ifndef RAYMATH_EXTERN_INLINE
-
-//------------------------------------------------------------------------------------
-// Functions Declaration to work with Vector3
-//------------------------------------------------------------------------------------
-RMDEF Vector3 VectorAdd(Vector3 v1, Vector3 v2);              // Add two vectors
-RMDEF Vector3 VectorSubtract(Vector3 v1, Vector3 v2);         // Substract two vectors
-RMDEF Vector3 VectorCrossProduct(Vector3 v1, Vector3 v2);     // Calculate two vectors cross product
-RMDEF Vector3 VectorPerpendicular(Vector3 v);                 // Calculate one vector perpendicular vector
-RMDEF float VectorDotProduct(Vector3 v1, Vector3 v2);         // Calculate two vectors dot product
-RMDEF float VectorLength(const Vector3 v);                    // Calculate vector lenght
-RMDEF void VectorScale(Vector3 *v, float scale);              // Scale provided vector
-RMDEF void VectorNegate(Vector3 *v);                          // Negate provided vector (invert direction)
-RMDEF void VectorNormalize(Vector3 *v);                       // Normalize provided vector
-RMDEF float VectorDistance(Vector3 v1, Vector3 v2);           // Calculate distance between two points
-RMDEF Vector3 VectorLerp(Vector3 v1, Vector3 v2, float amount); // Calculate linear interpolation between two vectors
-RMDEF Vector3 VectorReflect(Vector3 vector, Vector3 normal);  // Calculate reflected vector to normal
-RMDEF void VectorTransform(Vector3 *v, Matrix mat);           // Transforms a Vector3 by a given Matrix
-RMDEF Vector3 VectorZero(void);                               // Return a Vector3 init to zero
-RMDEF Vector3 VectorMin(Vector3 vec1, Vector3 vec2);          // Return min value for each pair of components
-RMDEF Vector3 VectorMax(Vector3 vec1, Vector3 vec2);          // Return max value for each pair of components
-
-//------------------------------------------------------------------------------------
-// Functions Declaration to work with Matrix
-//------------------------------------------------------------------------------------
-RMDEF float MatrixDeterminant(Matrix mat);                    // Compute matrix determinant
-RMDEF float MatrixTrace(Matrix mat);                          // Returns the trace of the matrix (sum of the values along the diagonal)
-RMDEF void MatrixTranspose(Matrix *mat);                      // Transposes provided matrix
-RMDEF void MatrixInvert(Matrix *mat);                         // Invert provided matrix
-RMDEF void MatrixNormalize(Matrix *mat);                      // Normalize provided matrix
-RMDEF Matrix MatrixIdentity(void);                            // Returns identity matrix
-RMDEF Matrix MatrixAdd(Matrix left, Matrix right);            // Add two matrices
-RMDEF Matrix MatrixSubstract(Matrix left, Matrix right);      // Substract two matrices (left - right)
-RMDEF Matrix MatrixTranslate(float x, float y, float z);      // Returns translation matrix
-RMDEF Matrix MatrixRotate(Vector3 axis, float angle);         // Returns rotation matrix for an angle around an specified axis (angle in radians)
-RMDEF Matrix MatrixRotateX(float angle);                      // Returns x-rotation matrix (angle in radians)
-RMDEF Matrix MatrixRotateY(float angle);                      // Returns y-rotation matrix (angle in radians)
-RMDEF Matrix MatrixRotateZ(float angle);                      // Returns z-rotation matrix (angle in radians)
-RMDEF Matrix MatrixScale(float x, float y, float z);          // Returns scaling matrix
-RMDEF Matrix MatrixMultiply(Matrix left, Matrix right);       // Returns two matrix multiplication
-RMDEF Matrix MatrixFrustum(double left, double right, double bottom, double top, double near, double far);  // Returns perspective projection matrix
-RMDEF Matrix MatrixPerspective(double fovy, double aspect, double near, double far);                        // Returns perspective projection matrix
-RMDEF Matrix MatrixOrtho(double left, double right, double bottom, double top, double near, double far);    // Returns orthographic projection matrix
-RMDEF Matrix MatrixLookAt(Vector3 position, Vector3 target, Vector3 up);  // Returns camera look-at matrix (view matrix)
-
-//------------------------------------------------------------------------------------
-// Functions Declaration to work with Quaternions
-//------------------------------------------------------------------------------------
-RMDEF float QuaternionLength(Quaternion quat);                // Compute the length of a quaternion
-RMDEF void QuaternionNormalize(Quaternion *q);                // Normalize provided quaternion
-RMDEF void QuaternionInvert(Quaternion *quat);                // Invert provided quaternion
-RMDEF Quaternion QuaternionMultiply(Quaternion q1, Quaternion q2);    // Calculate two quaternion multiplication
-RMDEF Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float slerp); // Calculates spherical linear interpolation between two quaternions
-RMDEF Quaternion QuaternionFromMatrix(Matrix matrix);                 // Returns a quaternion for a given rotation matrix
-RMDEF Matrix QuaternionToMatrix(Quaternion q);                        // Returns a matrix for a given quaternion
-RMDEF Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle);  // Returns rotation quaternion for an angle and axis
-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
-
-#endif  // notdef RAYMATH_EXTERN_INLINE
-
-#endif  // RAYMATH_H
-//////////////////////////////////////////////////////////////////// end of header file
-
-#if defined(RAYMATH_IMPLEMENTATION) || defined(RAYMATH_EXTERN_INLINE)
-
-#include <math.h>       // Required for: sinf(), cosf(), tan(), fabs()
-
-//----------------------------------------------------------------------------------
-// Module Functions Definition - Vector3 math
-//----------------------------------------------------------------------------------
-
-// Add two vectors
-RMDEF Vector3 VectorAdd(Vector3 v1, Vector3 v2)
-{
-    Vector3 result;
-
-    result.x = v1.x + v2.x;
-    result.y = v1.y + v2.y;
-    result.z = v1.z + v2.z;
-
-    return result;
-}
-
-// Substract two vectors
-RMDEF Vector3 VectorSubtract(Vector3 v1, Vector3 v2)
-{
-    Vector3 result;
-
-    result.x = v1.x - v2.x;
-    result.y = v1.y - v2.y;
-    result.z = v1.z - v2.z;
-
-    return result;
-}
-
-// Calculate two vectors cross product
-RMDEF Vector3 VectorCrossProduct(Vector3 v1, Vector3 v2)
-{
-    Vector3 result;
-
-    result.x = v1.y*v2.z - v1.z*v2.y;
-    result.y = v1.z*v2.x - v1.x*v2.z;
-    result.z = v1.x*v2.y - v1.y*v2.x;
-
-    return result;
-}
-
-// Calculate one vector perpendicular vector
-RMDEF Vector3 VectorPerpendicular(Vector3 v)
-{
-    Vector3 result;
-
-    float min = fabs(v.x);
-    Vector3 cardinalAxis = {1.0f, 0.0f, 0.0f};
-
-    if (fabs(v.y) < min)
-    {
-        min = fabs(v.y);
-        cardinalAxis = (Vector3){0.0f, 1.0f, 0.0f};
-    }
-
-    if(fabs(v.z) < min)
-    {
-        cardinalAxis = (Vector3){0.0f, 0.0f, 1.0f};
-    }
-
-    result = VectorCrossProduct(v, cardinalAxis);
-
-    return result;
-}
-
-// Calculate two vectors dot product
-RMDEF float VectorDotProduct(Vector3 v1, Vector3 v2)
-{
-    float result;
-
-    result = v1.x*v2.x + v1.y*v2.y + v1.z*v2.z;
-
-    return result;
-}
-
-// Calculate vector lenght
-RMDEF float VectorLength(const Vector3 v)
-{
-    float length;
-
-    length = sqrt(v.x*v.x + v.y*v.y + v.z*v.z);
-
-    return length;
-}
-
-// Scale provided vector
-RMDEF void VectorScale(Vector3 *v, float scale)
-{
-    v->x *= scale;
-    v->y *= scale;
-    v->z *= scale;
-}
-
-// Negate provided vector (invert direction)
-RMDEF void VectorNegate(Vector3 *v)
-{
-    v->x = -v->x;
-    v->y = -v->y;
-    v->z = -v->z;
-}
-
-// Normalize provided vector
-RMDEF void VectorNormalize(Vector3 *v)
-{
-    float length, ilength;
-
-    length = VectorLength(*v);
-
-    if (length == 0) length = 1.0f;
-
-    ilength = 1.0f/length;
-
-    v->x *= ilength;
-    v->y *= ilength;
-    v->z *= ilength;
-}
-
-// Calculate distance between two points
-RMDEF float VectorDistance(Vector3 v1, Vector3 v2)
-{
-    float result;
-
-    float dx = v2.x - v1.x;
-    float dy = v2.y - v1.y;
-    float dz = v2.z - v1.z;
-
-    result = sqrt(dx*dx + dy*dy + dz*dz);
-
-    return result;
-}
-
-// Calculate linear interpolation between two vectors
-RMDEF Vector3 VectorLerp(Vector3 v1, Vector3 v2, float amount)
-{
-    Vector3 result;
-
-    result.x = v1.x + amount*(v2.x - v1.x);
-    result.y = v1.y + amount*(v2.y - v1.y);
-    result.z = v1.z + amount*(v2.z - v1.z);
-
-    return result;
-}
-
-// Calculate reflected vector to normal
-RMDEF Vector3 VectorReflect(Vector3 vector, Vector3 normal)
-{
-    // I is the original vector
-    // N is the normal of the incident plane
-    // R = I - (2*N*( DotProduct[ I,N] ))
-
-    Vector3 result;
-
-    float dotProduct = VectorDotProduct(vector, normal);
-
-    result.x = vector.x - (2.0f*normal.x)*dotProduct;
-    result.y = vector.y - (2.0f*normal.y)*dotProduct;
-    result.z = vector.z - (2.0f*normal.z)*dotProduct;
-
-    return result;
-}
-
-// Transforms a Vector3 by a given Matrix
-// TODO: Review math (matrix transpose required?)
-RMDEF void VectorTransform(Vector3 *v, Matrix mat)
-{
-    float x = v->x;
-    float y = v->y;
-    float z = v->z;
-
-    v->x = mat.m0*x + mat.m4*y + mat.m8*z + mat.m12;
-    v->y = mat.m1*x + mat.m5*y + mat.m9*z + mat.m13;
-    v->z = mat.m2*x + mat.m6*y + mat.m10*z + mat.m14;
-};
-
-// Return a Vector3 init to zero
-RMDEF Vector3 VectorZero(void)
-{
-    Vector3 zero = { 0.0f, 0.0f, 0.0f };
-
-    return zero;
-}
-
-// Return min value for each pair of components
-RMDEF Vector3 VectorMin(Vector3 vec1, Vector3 vec2)
-{
-    Vector3 result;
-    
-    result.x = fminf(vec1.x, vec2.x);
-    result.y = fminf(vec1.y, vec2.y);
-    result.z = fminf(vec1.z, vec2.z);
-    
-    return result;
-}
-
-// Return max value for each pair of components
-RMDEF Vector3 VectorMax(Vector3 vec1, Vector3 vec2)
-{
-    Vector3 result;
-    
-    result.x = fmaxf(vec1.x, vec2.x);
-    result.y = fmaxf(vec1.y, vec2.y);
-    result.z = fmaxf(vec1.z, vec2.z);
-    
-    return result;
-}
-
-//----------------------------------------------------------------------------------
-// Module Functions Definition - Matrix math
-//----------------------------------------------------------------------------------
-
-// Compute matrix determinant
-RMDEF float MatrixDeterminant(Matrix mat)
-{
-    float result;
-
-    // Cache the matrix values (speed optimization)
-    float a00 = mat.m0, a01 = mat.m1, a02 = mat.m2, a03 = mat.m3;
-    float a10 = mat.m4, a11 = mat.m5, a12 = mat.m6, a13 = mat.m7;
-    float a20 = mat.m8, a21 = mat.m9, a22 = mat.m10, a23 = mat.m11;
-    float a30 = mat.m12, a31 = mat.m13, a32 = mat.m14, a33 = mat.m15;
-
-    result = a30*a21*a12*a03 - a20*a31*a12*a03 - a30*a11*a22*a03 + a10*a31*a22*a03 +
-             a20*a11*a32*a03 - a10*a21*a32*a03 - a30*a21*a02*a13 + a20*a31*a02*a13 +
-             a30*a01*a22*a13 - a00*a31*a22*a13 - a20*a01*a32*a13 + a00*a21*a32*a13 +
-             a30*a11*a02*a23 - a10*a31*a02*a23 - a30*a01*a12*a23 + a00*a31*a12*a23 +
-             a10*a01*a32*a23 - a00*a11*a32*a23 - a20*a11*a02*a33 + a10*a21*a02*a33 +
-             a20*a01*a12*a33 - a00*a21*a12*a33 - a10*a01*a22*a33 + a00*a11*a22*a33;
-
-    return result;
-}
-
-// Returns the trace of the matrix (sum of the values along the diagonal)
-RMDEF float MatrixTrace(Matrix mat)
-{
-    return (mat.m0 + mat.m5 + mat.m10 + mat.m15);
-}
-
-// Transposes provided matrix
-RMDEF void MatrixTranspose(Matrix *mat)
-{
-    Matrix temp;
-
-    temp.m0 = mat->m0;
-    temp.m1 = mat->m4;
-    temp.m2 = mat->m8;
-    temp.m3 = mat->m12;
-    temp.m4 = mat->m1;
-    temp.m5 = mat->m5;
-    temp.m6 = mat->m9;
-    temp.m7 = mat->m13;
-    temp.m8 = mat->m2;
-    temp.m9 = mat->m6;
-    temp.m10 = mat->m10;
-    temp.m11 = mat->m14;
-    temp.m12 = mat->m3;
-    temp.m13 = mat->m7;
-    temp.m14 = mat->m11;
-    temp.m15 = mat->m15;
-
-    *mat = temp;
-}
-
-// Invert provided matrix
-RMDEF void MatrixInvert(Matrix *mat)
-{
-    Matrix temp;
-
-    // Cache the matrix values (speed optimization)
-    float a00 = mat->m0, a01 = mat->m1, a02 = mat->m2, a03 = mat->m3;
-    float a10 = mat->m4, a11 = mat->m5, a12 = mat->m6, a13 = mat->m7;
-    float a20 = mat->m8, a21 = mat->m9, a22 = mat->m10, a23 = mat->m11;
-    float a30 = mat->m12, a31 = mat->m13, a32 = mat->m14, a33 = mat->m15;
-
-    float b00 = a00*a11 - a01*a10;
-    float b01 = a00*a12 - a02*a10;
-    float b02 = a00*a13 - a03*a10;
-    float b03 = a01*a12 - a02*a11;
-    float b04 = a01*a13 - a03*a11;
-    float b05 = a02*a13 - a03*a12;
-    float b06 = a20*a31 - a21*a30;
-    float b07 = a20*a32 - a22*a30;
-    float b08 = a20*a33 - a23*a30;
-    float b09 = a21*a32 - a22*a31;
-    float b10 = a21*a33 - a23*a31;
-    float b11 = a22*a33 - a23*a32;
-
-    // Calculate the invert determinant (inlined to avoid double-caching)
-    float invDet = 1.0f/(b00*b11 - b01*b10 + b02*b09 + b03*b08 - b04*b07 + b05*b06);
-
-    temp.m0 = (a11*b11 - a12*b10 + a13*b09)*invDet;
-    temp.m1 = (-a01*b11 + a02*b10 - a03*b09)*invDet;
-    temp.m2 = (a31*b05 - a32*b04 + a33*b03)*invDet;
-    temp.m3 = (-a21*b05 + a22*b04 - a23*b03)*invDet;
-    temp.m4 = (-a10*b11 + a12*b08 - a13*b07)*invDet;
-    temp.m5 = (a00*b11 - a02*b08 + a03*b07)*invDet;
-    temp.m6 = (-a30*b05 + a32*b02 - a33*b01)*invDet;
-    temp.m7 = (a20*b05 - a22*b02 + a23*b01)*invDet;
-    temp.m8 = (a10*b10 - a11*b08 + a13*b06)*invDet;
-    temp.m9 = (-a00*b10 + a01*b08 - a03*b06)*invDet;
-    temp.m10 = (a30*b04 - a31*b02 + a33*b00)*invDet;
-    temp.m11 = (-a20*b04 + a21*b02 - a23*b00)*invDet;
-    temp.m12 = (-a10*b09 + a11*b07 - a12*b06)*invDet;
-    temp.m13 = (a00*b09 - a01*b07 + a02*b06)*invDet;
-    temp.m14 = (-a30*b03 + a31*b01 - a32*b00)*invDet;
-    temp.m15 = (a20*b03 - a21*b01 + a22*b00)*invDet;
-
-    *mat = temp;
-}
-
-// Normalize provided matrix
-RMDEF void MatrixNormalize(Matrix *mat)
-{
-    float det = MatrixDeterminant(*mat);
-
-    mat->m0 /= det;
-    mat->m1 /= det;
-    mat->m2 /= det;
-    mat->m3 /= det;
-    mat->m4 /= det;
-    mat->m5 /= det;
-    mat->m6 /= det;
-    mat->m7 /= det;
-    mat->m8 /= det;
-    mat->m9 /= det;
-    mat->m10 /= det;
-    mat->m11 /= det;
-    mat->m12 /= det;
-    mat->m13 /= det;
-    mat->m14 /= det;
-    mat->m15 /= det;
-}
-
-// Returns identity matrix
-RMDEF Matrix MatrixIdentity(void)
-{
-    Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f, 
-                      0.0f, 1.0f, 0.0f, 0.0f, 
-                      0.0f, 0.0f, 1.0f, 0.0f,
-                      0.0f, 0.0f, 0.0f, 1.0f };
-
-    return result;
-}
-
-// Add two matrices
-RMDEF Matrix MatrixAdd(Matrix left, Matrix right)
-{
-    Matrix result = MatrixIdentity();
-
-    result.m0 = left.m0 + right.m0;
-    result.m1 = left.m1 + right.m1;
-    result.m2 = left.m2 + right.m2;
-    result.m3 = left.m3 + right.m3;
-    result.m4 = left.m4 + right.m4;
-    result.m5 = left.m5 + right.m5;
-    result.m6 = left.m6 + right.m6;
-    result.m7 = left.m7 + right.m7;
-    result.m8 = left.m8 + right.m8;
-    result.m9 = left.m9 + right.m9;
-    result.m10 = left.m10 + right.m10;
-    result.m11 = left.m11 + right.m11;
-    result.m12 = left.m12 + right.m12;
-    result.m13 = left.m13 + right.m13;
-    result.m14 = left.m14 + right.m14;
-    result.m15 = left.m15 + right.m15;
-
-    return result;
-}
-
-// Substract two matrices (left - right)
-RMDEF Matrix MatrixSubstract(Matrix left, Matrix right)
-{
-    Matrix result = MatrixIdentity();
-
-    result.m0 = left.m0 - right.m0;
-    result.m1 = left.m1 - right.m1;
-    result.m2 = left.m2 - right.m2;
-    result.m3 = left.m3 - right.m3;
-    result.m4 = left.m4 - right.m4;
-    result.m5 = left.m5 - right.m5;
-    result.m6 = left.m6 - right.m6;
-    result.m7 = left.m7 - right.m7;
-    result.m8 = left.m8 - right.m8;
-    result.m9 = left.m9 - right.m9;
-    result.m10 = left.m10 - right.m10;
-    result.m11 = left.m11 - right.m11;
-    result.m12 = left.m12 - right.m12;
-    result.m13 = left.m13 - right.m13;
-    result.m14 = left.m14 - right.m14;
-    result.m15 = left.m15 - right.m15;
-
-    return result;
-}
-
-// Returns translation matrix
-RMDEF Matrix MatrixTranslate(float x, float y, float z)
-{
-    Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f, 
-                      0.0f, 1.0f, 0.0f, 0.0f, 
-                      0.0f, 0.0f, 1.0f, 0.0f, 
-                      x, y, z, 1.0f };
-
-    return result;
-}
-
-// Create rotation matrix from axis and angle
-// NOTE: Angle should be provided in radians
-RMDEF Matrix MatrixRotate(Vector3 axis, float angle)
-{
-    Matrix result;
-
-    Matrix mat = MatrixIdentity();
-
-    float x = axis.x, y = axis.y, z = axis.z;
-
-    float length = sqrt(x*x + y*y + z*z);
-
-    if ((length != 1.0f) && (length != 0.0f))
-    {
-        length = 1.0f/length;
-        x *= length;
-        y *= length;
-        z *= length;
-    }
-
-    float sinres = sinf(angle);
-    float cosres = cosf(angle);
-    float t = 1.0f - cosres;
-
-    // Cache some matrix values (speed optimization)
-    float a00 = mat.m0, a01 = mat.m1, a02 = mat.m2, a03 = mat.m3;
-    float a10 = mat.m4, a11 = mat.m5, a12 = mat.m6, a13 = mat.m7;
-    float a20 = mat.m8, a21 = mat.m9, a22 = mat.m10, a23 = mat.m11;
-
-    // Construct the elements of the rotation matrix
-    float b00 = x*x*t + cosres, b01 = y*x*t + z*sinres, b02 = z*x*t - y*sinres;
-    float b10 = x*y*t - z*sinres, b11 = y*y*t + cosres, b12 = z*y*t + x*sinres;
-    float b20 = x*z*t + y*sinres, b21 = y*z*t - x*sinres, b22 = z*z*t + cosres;
-
-    // Perform rotation-specific matrix multiplication
-    result.m0 = a00*b00 + a10*b01 + a20*b02;
-    result.m1 = a01*b00 + a11*b01 + a21*b02;
-    result.m2 = a02*b00 + a12*b01 + a22*b02;
-    result.m3 = a03*b00 + a13*b01 + a23*b02;
-    result.m4 = a00*b10 + a10*b11 + a20*b12;
-    result.m5 = a01*b10 + a11*b11 + a21*b12;
-    result.m6 = a02*b10 + a12*b11 + a22*b12;
-    result.m7 = a03*b10 + a13*b11 + a23*b12;
-    result.m8 = a00*b20 + a10*b21 + a20*b22;
-    result.m9 = a01*b20 + a11*b21 + a21*b22;
-    result.m10 = a02*b20 + a12*b21 + a22*b22;
-    result.m11 = a03*b20 + a13*b21 + a23*b22;
-    result.m12 = mat.m12;
-    result.m13 = mat.m13;
-    result.m14 = mat.m14;
-    result.m15 = mat.m15;
-
-    return result;
-}
-
-/*
-// Another implementation for MatrixRotate...
-RMDEF Matrix MatrixRotate(float angle, float x, float y, float z)
-{
-    Matrix result = MatrixIdentity();
-
-    float c = cosf(angle);      // cosine
-    float s = sinf(angle);      // sine
-    float c1 = 1.0f - c;        // 1 - c
-
-    float m0 = result.m0, m4 = result.m4, m8 = result.m8, m12 = result.m12,
-          m1 = result.m1, m5 = result.m5, m9 = result.m9,  m13 = result.m13,
-          m2 = result.m2, m6 = result.m6, m10 = result.m10, m14 = result.m14;
-
-    // build rotation matrix
-    float r0 = x*x*c1 + c;
-    float r1 = x*y*c1 + z*s;
-    float r2 = x*z*c1 - y*s;
-    float r4 = x*y*c1 - z*s;
-    float r5 = y*y*c1 + c;
-    float r6 = y*z*c1 + x*s;
-    float r8 = x*z*c1 + y*s;
-    float r9 = y*z*c1 - x*s;
-    float r10= z*z*c1 + c;
-
-    // multiply rotation matrix
-    result.m0 = r0*m0 + r4*m1 + r8*m2;
-    result.m1 = r1*m0 + r5*m1 + r9*m2;
-    result.m2 = r2*m0 + r6*m1 + r10*m2;
-    result.m4 = r0*m4 + r4*m5 + r8*m6;
-    result.m5 = r1*m4 + r5*m5 + r9*m6;
-    result.m6 = r2*m4 + r6*m5 + r10*m6;
-    result.m8 = r0*m8 + r4*m9 + r8*m10;
-    result.m9 = r1*m8 + r5*m9 + r9*m10;
-    result.m10 = r2*m8 + r6*m9 + r10*m10;
-    result.m12 = r0*m12+ r4*m13 + r8*m14;
-    result.m13 = r1*m12+ r5*m13 + r9*m14;
-    result.m14 = r2*m12+ r6*m13 + r10*m14;
-
-    return result;
-}
-*/
-
-// Returns x-rotation matrix (angle in radians)
-RMDEF Matrix MatrixRotateX(float angle)
-{
-    Matrix result = MatrixIdentity();
-
-    float cosres = cosf(angle);
-    float sinres = sinf(angle);
-
-    result.m5 = cosres;
-    result.m6 = -sinres;
-    result.m9 = sinres;
-    result.m10 = cosres;
-
-    return result;
-}
-
-// Returns y-rotation matrix (angle in radians)
-RMDEF Matrix MatrixRotateY(float angle)
-{
-    Matrix result = MatrixIdentity();
-
-    float cosres = cosf(angle);
-    float sinres = sinf(angle);
-
-    result.m0 = cosres;
-    result.m2 = sinres;
-    result.m8 = -sinres;
-    result.m10 = cosres;
-
-    return result;
-}
-
-// Returns z-rotation matrix (angle in radians)
-RMDEF Matrix MatrixRotateZ(float angle)
-{
-    Matrix result = MatrixIdentity();
-
-    float cosres = cosf(angle);
-    float sinres = sinf(angle);
-
-    result.m0 = cosres;
-    result.m1 = -sinres;
-    result.m4 = sinres;
-    result.m5 = cosres;
-
-    return result;
-}
-
-// Returns scaling matrix
-RMDEF Matrix MatrixScale(float x, float y, float z)
-{
-    Matrix result = { x, 0.0f, 0.0f, 0.0f, 
-                      0.0f, y, 0.0f, 0.0f, 
-                      0.0f, 0.0f, z, 0.0f, 
-                      0.0f, 0.0f, 0.0f, 1.0f };
-
-    return result;
-}
-
-// Returns two matrix multiplication
-// NOTE: When multiplying matrices... the order matters!
-RMDEF Matrix MatrixMultiply(Matrix left, Matrix right)
-{
-    Matrix result;
-
-    result.m0 = right.m0*left.m0 + right.m1*left.m4 + right.m2*left.m8 + right.m3*left.m12;
-    result.m1 = right.m0*left.m1 + right.m1*left.m5 + right.m2*left.m9 + right.m3*left.m13;
-    result.m2 = right.m0*left.m2 + right.m1*left.m6 + right.m2*left.m10 + right.m3*left.m14;
-    result.m3 = right.m0*left.m3 + right.m1*left.m7 + right.m2*left.m11 + right.m3*left.m15;
-    result.m4 = right.m4*left.m0 + right.m5*left.m4 + right.m6*left.m8 + right.m7*left.m12;
-    result.m5 = right.m4*left.m1 + right.m5*left.m5 + right.m6*left.m9 + right.m7*left.m13;
-    result.m6 = right.m4*left.m2 + right.m5*left.m6 + right.m6*left.m10 + right.m7*left.m14;
-    result.m7 = right.m4*left.m3 + right.m5*left.m7 + right.m6*left.m11 + right.m7*left.m15;
-    result.m8 = right.m8*left.m0 + right.m9*left.m4 + right.m10*left.m8 + right.m11*left.m12;
-    result.m9 = right.m8*left.m1 + right.m9*left.m5 + right.m10*left.m9 + right.m11*left.m13;
-    result.m10 = right.m8*left.m2 + right.m9*left.m6 + right.m10*left.m10 + right.m11*left.m14;
-    result.m11 = right.m8*left.m3 + right.m9*left.m7 + right.m10*left.m11 + right.m11*left.m15;
-    result.m12 = right.m12*left.m0 + right.m13*left.m4 + right.m14*left.m8 + right.m15*left.m12;
-    result.m13 = right.m12*left.m1 + right.m13*left.m5 + right.m14*left.m9 + right.m15*left.m13;
-    result.m14 = right.m12*left.m2 + right.m13*left.m6 + right.m14*left.m10 + right.m15*left.m14;
-    result.m15 = right.m12*left.m3 + right.m13*left.m7 + right.m14*left.m11 + right.m15*left.m15;
-
-    return result;
-}
-
-// Returns perspective projection matrix
-RMDEF Matrix MatrixFrustum(double left, double right, double bottom, double top, double near, double far)
-{
-    Matrix result;
-
-    float rl = (right - left);
-    float tb = (top - bottom);
-    float fn = (far - near);
-
-    result.m0 = (near*2.0f)/rl;
-    result.m1 = 0.0f;
-    result.m2 = 0.0f;
-    result.m3 = 0.0f;
-
-    result.m4 = 0.0f;
-    result.m5 = (near*2.0f)/tb;
-    result.m6 = 0.0f;
-    result.m7 = 0.0f;
-
-    result.m8 = (right + left)/rl;
-    result.m9 = (top + bottom)/tb;
-    result.m10 = -(far + near)/fn;
-    result.m11 = -1.0f;
-
-    result.m12 = 0.0f;
-    result.m13 = 0.0f;
-    result.m14 = -(far*near*2.0f)/fn;
-    result.m15 = 0.0f;
-
-    return result;
-}
-
-// Returns perspective projection matrix
-RMDEF Matrix MatrixPerspective(double fovy, double aspect, double near, double far)
-{
-    double top = near*tan(fovy*PI/360.0);
-    double right = top*aspect;
-
-    return MatrixFrustum(-right, right, -top, top, near, far);
-}
-
-// Returns orthographic projection matrix
-RMDEF Matrix MatrixOrtho(double left, double right, double bottom, double top, double near, double far)
-{
-    Matrix result;
-
-    float rl = (right - left);
-    float tb = (top - bottom);
-    float fn = (far - near);
-
-    result.m0 = 2.0f/rl;
-    result.m1 = 0.0f;
-    result.m2 = 0.0f;
-    result.m3 = 0.0f;
-    result.m4 = 0.0f;
-    result.m5 = 2.0f/tb;
-    result.m6 = 0.0f;
-    result.m7 = 0.0f;
-    result.m8 = 0.0f;
-    result.m9 = 0.0f;
-    result.m10 = -2.0f/fn;
-    result.m11 = 0.0f;
-    result.m12 = -(left + right)/rl;
-    result.m13 = -(top + bottom)/tb;
-    result.m14 = -(far + near)/fn;
-    result.m15 = 1.0f;
-
-    return result;
-}
-
-// Returns camera look-at matrix (view matrix)
-RMDEF Matrix MatrixLookAt(Vector3 eye, Vector3 target, Vector3 up)
-{
-    Matrix result;
-
-    Vector3 z = VectorSubtract(eye, target);
-    VectorNormalize(&z);
-    Vector3 x = VectorCrossProduct(up, z);
-    VectorNormalize(&x);
-    Vector3 y = VectorCrossProduct(z, x);
-    VectorNormalize(&y);
-
-    result.m0 = x.x;
-    result.m1 = x.y;
-    result.m2 = x.z;
-    result.m3 = -((x.x*eye.x) + (x.y*eye.y) + (x.z*eye.z));
-    result.m4 = y.x;
-    result.m5 = y.y;
-    result.m6 = y.z;
-    result.m7 = -((y.x*eye.x) + (y.y*eye.y) + (y.z*eye.z));
-    result.m8 = z.x;
-    result.m9 = z.y;
-    result.m10 = z.z;
-    result.m11 = -((z.x*eye.x) + (z.y*eye.y) + (z.z*eye.z));
-    result.m12 = 0.0f;
-    result.m13 = 0.0f;
-    result.m14 = 0.0f;
-    result.m15 = 1.0f;
-
-    return result;
-}
-
-//----------------------------------------------------------------------------------
-// Module Functions Definition - Quaternion math
-//----------------------------------------------------------------------------------
-
-// Computes the length of a quaternion
-RMDEF float QuaternionLength(Quaternion quat)
-{
-    return sqrt(quat.x*quat.x + quat.y*quat.y + quat.z*quat.z + quat.w*quat.w);
-}
-
-// Normalize provided quaternion
-RMDEF void QuaternionNormalize(Quaternion *q)
-{
-    float length, ilength;
-
-    length = QuaternionLength(*q);
-
-    if (length == 0.0f) length = 1.0f;
-
-    ilength = 1.0f/length;
-
-    q->x *= ilength;
-    q->y *= ilength;
-    q->z *= ilength;
-    q->w *= ilength;
-}
-
-// Invert provided quaternion
-RMDEF void QuaternionInvert(Quaternion *quat)
-{
-    float length = QuaternionLength(*quat);
-    float lengthSq = length*length;
-    
-    if (lengthSq != 0.0)
-    {
-        float i = 1.0f/lengthSq;
-        
-        quat->x *= -i;
-        quat->y *= -i;
-        quat->z *= -i;
-        quat->w *= i;
-    }
-}
-
-// Calculate two quaternion multiplication
-RMDEF Quaternion QuaternionMultiply(Quaternion q1, Quaternion q2)
-{
-    Quaternion result;
-
-    float qax = q1.x, qay = q1.y, qaz = q1.z, qaw = q1.w;
-    float qbx = q2.x, qby = q2.y, qbz = q2.z, qbw = q2.w;
-
-    result.x = qax*qbw + qaw*qbx + qay*qbz - qaz*qby;
-    result.y = qay*qbw + qaw*qby + qaz*qbx - qax*qbz;
-    result.z = qaz*qbw + qaw*qbz + qax*qby - qay*qbx;
-    result.w = qaw*qbw - qax*qbx - qay*qby - qaz*qbz;
-
-    return result;
-}
-
-// Calculates spherical linear interpolation between two quaternions
-RMDEF Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount)
-{
-    Quaternion result;
-
-    float cosHalfTheta =  q1.x*q2.x + q1.y*q2.y + q1.z*q2.z + q1.w*q2.w;
-
-    if (fabs(cosHalfTheta) >= 1.0f) result = q1;
-    else
-    {
-        float halfTheta = acos(cosHalfTheta);
-        float sinHalfTheta = sqrt(1.0f - cosHalfTheta*cosHalfTheta);
-
-        if (fabs(sinHalfTheta) < 0.001f)
-        {
-            result.x = (q1.x*0.5f + q2.x*0.5f);
-            result.y = (q1.y*0.5f + q2.y*0.5f);
-            result.z = (q1.z*0.5f + q2.z*0.5f);
-            result.w = (q1.w*0.5f + q2.w*0.5f);
-        }
-        else
-        {
-            float ratioA = sinf((1 - amount)*halfTheta)/sinHalfTheta;
-            float ratioB = sinf(amount*halfTheta)/sinHalfTheta;
-
-            result.x = (q1.x*ratioA + q2.x*ratioB);
-            result.y = (q1.y*ratioA + q2.y*ratioB);
-            result.z = (q1.z*ratioA + q2.z*ratioB);
-            result.w = (q1.w*ratioA + q2.w*ratioB);
-        }
-    }
-
-    return result;
-}
-
-// Returns a quaternion for a given rotation matrix
-RMDEF Quaternion QuaternionFromMatrix(Matrix matrix)
-{
-    Quaternion result;
-
-    float trace = MatrixTrace(matrix);
-
-    if (trace > 0.0f)
-    {
-        float s = (float)sqrt(trace + 1)*2.0f;
-        float invS = 1.0f/s;
-
-        result.w = s*0.25f;
-        result.x = (matrix.m6 - matrix.m9)*invS;
-        result.y = (matrix.m8 - matrix.m2)*invS;
-        result.z = (matrix.m1 - matrix.m4)*invS;
-    }
-    else
-    {
-        float m00 = matrix.m0, m11 = matrix.m5, m22 = matrix.m10;
-
-        if (m00 > m11 && m00 > m22)
-        {
-            float s = (float)sqrt(1.0f + m00 - m11 - m22)*2.0f;
-            float invS = 1.0f/s;
-
-            result.w = (matrix.m6 - matrix.m9)*invS;
-            result.x = s*0.25f;
-            result.y = (matrix.m4 + matrix.m1)*invS;
-            result.z = (matrix.m8 + matrix.m2)*invS;
-        }
-        else if (m11 > m22)
-        {
-            float s = (float)sqrt(1.0f + m11 - m00 - m22)*2.0f;
-            float invS = 1.0f/s;
-
-            result.w = (matrix.m8 - matrix.m2)*invS;
-            result.x = (matrix.m4 + matrix.m1)*invS;
-            result.y = s*0.25f;
-            result.z = (matrix.m9 + matrix.m6)*invS;
-        }
-        else
-        {
-            float s = (float)sqrt(1.0f + m22 - m00 - m11)*2.0f;
-            float invS = 1.0f/s;
-
-            result.w = (matrix.m1 - matrix.m4)*invS;
-            result.x = (matrix.m8 + matrix.m2)*invS;
-            result.y = (matrix.m9 + matrix.m6)*invS;
-            result.z = s*0.25f;
-        }
-    }
-
-    return result;
-}
-
-// Returns a matrix for a given quaternion
-RMDEF Matrix QuaternionToMatrix(Quaternion q)
-{
-    Matrix result;
-
-    float x = q.x, y = q.y, z = q.z, w = q.w;
-
-    float x2 = x + x;
-    float y2 = y + y;
-    float z2 = z + z;
-
-    float xx = x*x2;
-    float xy = x*y2;
-    float xz = x*z2;
-
-    float yy = y*y2;
-    float yz = y*z2;
-    float zz = z*z2;
-
-    float wx = w*x2;
-    float wy = w*y2;
-    float wz = w*z2;
-
-    result.m0 = 1.0f - (yy + zz);
-    result.m1 = xy - wz;
-    result.m2 = xz + wy;
-    result.m3 = 0.0f;
-    result.m4 = xy + wz;
-    result.m5 = 1.0f - (xx + zz);
-    result.m6 = yz - wx;
-    result.m7 = 0.0f;
-    result.m8 = xz - wy;
-    result.m9 = yz + wx;
-    result.m10 = 1.0f - (xx + yy);
-    result.m11 = 0.0f;
-    result.m12 = 0.0f;
-    result.m13 = 0.0f;
-    result.m14 = 0.0f;
-    result.m15 = 1.0f;
-    
-    return result;
-}
-
-// Returns rotation quaternion for an angle and axis
-// NOTE: angle must be provided in radians
-RMDEF Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle)
-{
-    Quaternion result = { 0.0f, 0.0f, 0.0f, 1.0f };
-
-    if (VectorLength(axis) != 0.0f)
-
-    angle *= 0.5f;
-
-    VectorNormalize(&axis);
-    
-    float sinres = sinf(angle);
-    float cosres = cosf(angle);
-
-    result.x = axis.x*sinres;
-    result.y = axis.y*sinres;
-    result.z = axis.z*sinres;
-    result.w = cosres;
-
-    QuaternionNormalize(&result);
-
-    return result;
-}
-
-// Returns the rotation angle and axis for a given quaternion
-RMDEF void QuaternionToAxisAngle(Quaternion q, Vector3 *outAxis, float *outAngle)
-{
-    if (fabs(q.w) > 1.0f) QuaternionNormalize(&q);
-
-    Vector3 resAxis = { 0.0f, 0.0f, 0.0f };
-    float resAngle = 0.0f;
-
-    resAngle = 2.0f*(float)acos(q.w);
-    float den = (float)sqrt(1.0f - q.w*q.w);
-
-    if (den > 0.0001f)
-    {
-        resAxis.x = q.x/den;
-        resAxis.y = q.y/den;
-        resAxis.z = q.z/den;
-    }
-    else
-    {
-        // This occurs when the angle is zero.
-        // Not a problem: just set an arbitrary normalized axis.
-        resAxis.x = 1.0f;
-    }
-
-    *outAxis = resAxis;
-    *outAngle = resAngle;
-}
-
-// Transform a quaternion given a transformation matrix
-RMDEF void QuaternionTransform(Quaternion *q, Matrix mat)
-{
-    float x = q->x;
-    float y = q->y;
-    float z = q->z;
-    float w = q->w;
-
-    q->x = mat.m0*x + mat.m4*y + mat.m8*z + mat.m12*w;
-    q->y = mat.m1*x + mat.m5*y + mat.m9*z + mat.m13*w;
-    q->z = mat.m2*x + mat.m6*y + mat.m10*z + mat.m14*w;
-    q->w = mat.m3*x + mat.m7*y + mat.m11*z + mat.m15*w;
-}
-
-#endif  // RAYMATH_IMPLEMENTATION

+ 0 - 3801
examples/oculus_glfw_sample/rlgl.c

@@ -1,3801 +0,0 @@
-/**********************************************************************************************
-*
-*   rlgl - raylib OpenGL abstraction layer
-*
-*   raylib now uses OpenGL 1.1 style functions (rlVertex) that are mapped to selected OpenGL version:
-*       OpenGL 1.1  - Direct map rl* -> gl*
-*       OpenGL 3.3  - Vertex data is stored in VAOs, call rlglDraw() to render
-*       OpenGL ES 2 - Vertex data is stored in VBOs or VAOs (when available), call rlglDraw() to render
-*
-*   Copyright (c) 2014 Ramon Santamaria (@raysan5)
-*
-*   This software is provided "as-is", without any express or implied warranty. In no event
-*   will the authors be held liable for any damages arising from the use of this software.
-*
-*   Permission is granted to anyone to use this software for any purpose, including commercial
-*   applications, and to alter it and redistribute it freely, subject to the following restrictions:
-*
-*     1. The origin of this software must not be misrepresented; you must not claim that you
-*     wrote the original software. If you use this software in a product, an acknowledgment
-*     in the product documentation would be appreciated but is not required.
-*
-*     2. Altered source versions must be plainly marked as such, and must not be misrepresented
-*     as being the original software.
-*
-*     3. This notice may not be removed or altered from any source distribution.
-*
-**********************************************************************************************/
-
-#include "rlgl.h"
-
-#include <stdio.h>                  // Required for: fopen(), fclose(), fread()... [Used only on ReadTextFile()]
-#include <stdlib.h>                 // Required for: malloc(), free(), rand()
-#include <string.h>                 // Required for: strcmp(), strlen(), strtok()
-
-#ifndef RLGL_STANDALONE
-    #include "raymath.h"            // Required for Vector3 and Matrix functions
-#endif
-
-#if defined(GRAPHICS_API_OPENGL_11)
-    #ifdef __APPLE__                
-        #include <OpenGL/gl.h>      // OpenGL 1.1 library for OSX
-    #else
-        #include <GL/gl.h>          // OpenGL 1.1 library
-    #endif
-#endif
-
-#if defined(GRAPHICS_API_OPENGL_33)
-    #ifdef __APPLE__ 
-        #include <OpenGL/gl3.h>     // OpenGL 3 library for OSX
-    #else
-    #define GLAD_IMPLEMENTATION
-#if defined(RLGL_STANDALONE)
-    #include "glad.h"               // GLAD extensions loading library, includes OpenGL headers
-#else
-    #include "external/glad.h"      // GLAD extensions loading library, includes OpenGL headers
-#endif
-
-    #endif
-#endif
-
-#if defined(GRAPHICS_API_OPENGL_ES2)
-    #include <EGL/egl.h>            // EGL library
-    #include <GLES2/gl2.h>          // OpenGL ES 2.0 library
-    #include <GLES2/gl2ext.h>       // OpenGL ES 2.0 extensions library
-#endif
-
-#if defined(RLGL_STANDALONE)
-    #include <stdarg.h>             // Required for: va_list, va_start(), vfprintf(), va_end() [Used only on TraceLog()]
-#endif
-
-#if !defined(GRAPHICS_API_OPENGL_11)
-    #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
-//----------------------------------------------------------------------------------
-#define MATRIX_STACK_SIZE          16   // Matrix stack max size
-#define MAX_DRAWS_BY_TEXTURE      256   // Draws are organized by texture changes
-#define TEMP_VERTEX_BUFFER_SIZE  4096   // Temporal Vertex Buffer (required for vertex-transformations)
-                                        // NOTE: Every vertex are 3 floats (12 bytes)
-                                        
-#define MAX_LIGHTS                  8   // Max lights supported by standard shader
-
-#ifndef GL_SHADING_LANGUAGE_VERSION
-    #define GL_SHADING_LANGUAGE_VERSION         0x8B8C
-#endif
-
-#ifndef GL_COMPRESSED_RGB_S3TC_DXT1_EXT
-    #define GL_COMPRESSED_RGB_S3TC_DXT1_EXT     0x83F0
-#endif
-#ifndef GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
-    #define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT    0x83F1
-#endif
-#ifndef GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
-    #define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT    0x83F2
-#endif
-#ifndef GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
-    #define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT    0x83F3
-#endif
-#ifndef GL_ETC1_RGB8_OES
-    #define GL_ETC1_RGB8_OES                    0x8D64
-#endif
-#ifndef GL_COMPRESSED_RGB8_ETC2
-    #define GL_COMPRESSED_RGB8_ETC2             0x9274
-#endif
-#ifndef GL_COMPRESSED_RGBA8_ETC2_EAC
-    #define GL_COMPRESSED_RGBA8_ETC2_EAC        0x9278
-#endif
-#ifndef GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
-    #define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG  0x8C00
-#endif
-#ifndef GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
-    #define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02
-#endif
-#ifndef GL_COMPRESSED_RGBA_ASTC_4x4_KHR
-    #define GL_COMPRESSED_RGBA_ASTC_4x4_KHR     0x93b0
-#endif
-#ifndef GL_COMPRESSED_RGBA_ASTC_8x8_KHR
-    #define GL_COMPRESSED_RGBA_ASTC_8x8_KHR     0x93b7
-#endif
-
-#if defined(GRAPHICS_API_OPENGL_11)
-    #define GL_UNSIGNED_SHORT_5_6_5     0x8363
-    #define GL_UNSIGNED_SHORT_5_5_5_1   0x8034
-    #define GL_UNSIGNED_SHORT_4_4_4_4   0x8033
-#endif
-
-// Default vertex attribute names on shader to set location points
-#define DEFAULT_ATTRIB_POSITION_NAME    "vertexPosition"    // shader-location = 0
-#define DEFAULT_ATTRIB_TEXCOORD_NAME    "vertexTexCoord"    // shader-location = 1
-#define DEFAULT_ATTRIB_NORMAL_NAME      "vertexNormal"      // shader-location = 2
-#define DEFAULT_ATTRIB_COLOR_NAME       "vertexColor"       // shader-location = 3
-#define DEFAULT_ATTRIB_TANGENT_NAME     "vertexTangent"     // shader-location = 4
-#define DEFAULT_ATTRIB_TEXCOORD2_NAME   "vertexTexCoord2"   // shader-location = 5
-
-//----------------------------------------------------------------------------------
-// Types and Structures Definition
-//----------------------------------------------------------------------------------
-
-// Dynamic vertex buffers (position + texcoords + colors + indices arrays)
-typedef struct {
-    int vCounter;               // vertex position counter to process (and draw) from full buffer
-    int tcCounter;              // vertex texcoord counter to process (and draw) from full buffer
-    int cCounter;               // vertex color counter to process (and draw) from full buffer
-    float *vertices;            // vertex position (XYZ - 3 components per vertex) (shader-location = 0)
-    float *texcoords;           // vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1)
-    unsigned char *colors;      // vertex colors (RGBA - 4 components per vertex) (shader-location = 3)
-#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33)
-    unsigned int *indices;      // vertex indices (in case vertex data comes indexed) (6 indices per quad)
-#elif defined(GRAPHICS_API_OPENGL_ES2)
-    unsigned short *indices;    // vertex indices (in case vertex data comes indexed) (6 indices per quad)
-                                // NOTE: 6*2 byte = 12 byte, not alignment problem!
-#endif
-    unsigned int vaoId;         // OpenGL Vertex Array Object id
-    unsigned int vboId[4];      // OpenGL Vertex Buffer Objects id (4 types of vertex data)
-} DynamicBuffer;
-
-// Draw call type
-// NOTE: Used to track required draw-calls, organized by texture
-typedef struct {
-    int vertexCount;
-    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
-//----------------------------------------------------------------------------------
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-static Matrix stack[MATRIX_STACK_SIZE];
-static int stackCounter = 0;
-
-static Matrix modelview;
-static Matrix projection;
-static Matrix *currentMatrix;
-static int currentMatrixMode;
-
-static DrawMode currentDrawMode;
-
-static float currentDepth = -1.0f;
-
-static DynamicBuffer lines;
-static DynamicBuffer triangles;
-static DynamicBuffer quads;
-
-// Default buffers draw calls
-static DrawCall *draws;
-static int drawsCounter;
-
-// Temp vertex buffer to be used with rlTranslate, rlRotate, rlScale
-static Vector3 *tempBuffer;
-static int tempBufferCount = 0;
-static bool useTempBuffer = false;
-
-// Shader Programs
-static Shader defaultShader;
-static Shader standardShader;               // Lazy initialization when GetStandardShader()
-static Shader currentShader;                // By default, defaultShader
-static bool standardShaderLoaded = false;   
-
-// Flags for supported extensions
-static bool vaoSupported = false;           // VAO support (OpenGL ES2 could not support VAO extension)
-
-// Compressed textures support flags
-static bool texCompETC1Supported = false;   // ETC1 texture compression support
-static bool texCompETC2Supported = false;   // ETC2/EAC texture compression support
-static bool texCompPVRTSupported = false;   // PVR texture compression support
-static bool texCompASTCSupported = false;   // ASTC texture compression support
-
-// Lighting data
-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
-
-#if defined(GRAPHICS_API_OPENGL_ES2)
-// NOTE: VAO functionality is exposed through extensions (OES)
-static PFNGLGENVERTEXARRAYSOESPROC glGenVertexArrays;
-static PFNGLBINDVERTEXARRAYOESPROC glBindVertexArray;
-static PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArrays;
-//static PFNGLISVERTEXARRAYOESPROC glIsVertexArray;        // NOTE: Fails in WebGL, omitted
-#endif
-
-static int blendMode = 0;
-
-// White texture useful for plain color polys (required by shader)
-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(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)
-static void LoadDefaultShaderLocations(Shader *shader); // Bind default shader locations (attributes and uniforms)
-static void UnloadDefaultShader(void);      // Unload default shader
-static void UnloadStandardShader(void);     // Unload standard shader
-
-static void LoadDefaultBuffers(void);       // Load default internal buffers (lines, triangles, quads)
-static void UpdateDefaultBuffers(void);     // Update default internal buffers (VAOs/VBOs) with vertex data
-static void DrawDefaultBuffers(void);       // Draw default internal buffers vertex data
-static void UnloadDefaultBuffers(void);     // Unload default internal buffers vertex data from CPU and GPU
-
-static void SetShaderLights(Shader shader); // Sets shader uniform values for lights array
-
-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);
-#endif
-
-#if defined(RLGL_STANDALONE)
-float *MatrixToFloat(Matrix mat);           // Converts Matrix to float array
-#endif
-
-//----------------------------------------------------------------------------------
-// Module Functions Definition - Matrix operations
-//----------------------------------------------------------------------------------
-
-#if defined(GRAPHICS_API_OPENGL_11)
-
-// Fallback to OpenGL 1.1 function calls
-//---------------------------------------
-void rlMatrixMode(int mode)
-{
-    switch (mode)
-    {
-        case RL_PROJECTION: glMatrixMode(GL_PROJECTION); break;
-        case RL_MODELVIEW: glMatrixMode(GL_MODELVIEW); break;
-        case RL_TEXTURE: glMatrixMode(GL_TEXTURE); break;
-        default: break;
-    }
-}
-
-void rlFrustum(double left, double right, double bottom, double top, double near, double far)
-{
-    glFrustum(left, right, bottom, top, near, far);
-}
-
-void rlOrtho(double left, double right, double bottom, double top, double near, double far)
-{
-    glOrtho(left, right, bottom, top, near, far);
-}
-
-void rlPushMatrix(void) { glPushMatrix(); }
-void rlPopMatrix(void) { glPopMatrix(); }
-void rlLoadIdentity(void) { glLoadIdentity(); }
-void rlTranslatef(float x, float y, float z) { glTranslatef(x, y, z); }
-void rlRotatef(float angleDeg, float x, float y, float z) { glRotatef(angleDeg, x, y, z); }
-void rlScalef(float x, float y, float z) { glScalef(x, y, z); }
-void rlMultMatrixf(float *mat) { glMultMatrixf(mat); }
-
-#elif defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-
-// Choose the current matrix to be transformed
-void rlMatrixMode(int mode)
-{
-    if (mode == RL_PROJECTION) currentMatrix = &projection;
-    else if (mode == RL_MODELVIEW) currentMatrix = &modelview;
-    //else if (mode == RL_TEXTURE) // Not supported
-
-    currentMatrixMode = mode;
-}
-
-// Push the current matrix to stack
-void rlPushMatrix(void)
-{
-    if (stackCounter == MATRIX_STACK_SIZE - 1)
-    {
-        TraceLog(ERROR, "Stack Buffer Overflow (MAX %i Matrix)", MATRIX_STACK_SIZE);
-    }
-
-    stack[stackCounter] = *currentMatrix;
-    rlLoadIdentity();
-    stackCounter++;
-
-    if (currentMatrixMode == RL_MODELVIEW) useTempBuffer = true;
-}
-
-// Pop lattest inserted matrix from stack
-void rlPopMatrix(void)
-{
-    if (stackCounter > 0)
-    {
-        Matrix mat = stack[stackCounter - 1];
-        *currentMatrix = mat;
-        stackCounter--;
-    }
-}
-
-// Reset current matrix to identity matrix
-void rlLoadIdentity(void)
-{
-    *currentMatrix = MatrixIdentity();
-}
-
-// Multiply the current matrix by a translation matrix
-void rlTranslatef(float x, float y, float z)
-{
-    Matrix matTranslation = MatrixTranslate(x, y, z);
-    MatrixTranspose(&matTranslation);
-
-    *currentMatrix = MatrixMultiply(*currentMatrix, matTranslation);
-}
-
-// Multiply the current matrix by a rotation matrix
-void rlRotatef(float angleDeg, float x, float y, float z)
-{
-    Matrix matRotation = MatrixIdentity();
-
-    Vector3 axis = (Vector3){ x, y, z };
-    VectorNormalize(&axis);
-    matRotation = MatrixRotate(axis, angleDeg*DEG2RAD);
-    MatrixTranspose(&matRotation);
-
-    *currentMatrix = MatrixMultiply(*currentMatrix, matRotation);
-}
-
-// Multiply the current matrix by a scaling matrix
-void rlScalef(float x, float y, float z)
-{
-    Matrix matScale = MatrixScale(x, y, z);
-    MatrixTranspose(&matScale);
-
-    *currentMatrix = MatrixMultiply(*currentMatrix, matScale);
-}
-
-// Multiply the current matrix by another matrix
-void rlMultMatrixf(float *m)
-{
-    // Matrix creation from array
-    Matrix mat = { m[0], m[1], m[2], m[3],
-                   m[4], m[5], m[6], m[7],
-                   m[8], m[9], m[10], m[11],
-                   m[12], m[13], m[14], m[15] };
-
-    *currentMatrix = MatrixMultiply(*currentMatrix, mat);
-}
-
-// Multiply the current matrix by a perspective matrix generated by parameters
-void rlFrustum(double left, double right, double bottom, double top, double near, double far)
-{
-    Matrix matPerps = MatrixFrustum(left, right, bottom, top, near, far);
-    MatrixTranspose(&matPerps);
-
-    *currentMatrix = MatrixMultiply(*currentMatrix, matPerps);
-}
-
-// Multiply the current matrix by an orthographic matrix generated by parameters
-void rlOrtho(double left, double right, double bottom, double top, double near, double far)
-{
-    Matrix matOrtho = MatrixOrtho(left, right, bottom, top, near, far);
-    MatrixTranspose(&matOrtho);
-
-    *currentMatrix = MatrixMultiply(*currentMatrix, matOrtho);
-}
-
-#endif
-
-// Set the viewport area (trasnformation from normalized device coordinates to window coordinates)
-void rlViewport(int x, int y, int width, int height)
-{
-    glViewport(x, y, width, height);
-}
-
-//----------------------------------------------------------------------------------
-// Module Functions Definition - Vertex level operations
-//----------------------------------------------------------------------------------
-#if defined(GRAPHICS_API_OPENGL_11)
-
-// Fallback to OpenGL 1.1 function calls
-//---------------------------------------
-void rlBegin(int mode)
-{
-    switch (mode)
-    {
-        case RL_LINES: glBegin(GL_LINES); break;
-        case RL_TRIANGLES: glBegin(GL_TRIANGLES); break;
-        case RL_QUADS: glBegin(GL_QUADS); break;
-        default: break;
-    }
-}
-
-void rlEnd() { glEnd(); }
-void rlVertex2i(int x, int y) { glVertex2i(x, y); }
-void rlVertex2f(float x, float y) { glVertex2f(x, y); }
-void rlVertex3f(float x, float y, float z) { glVertex3f(x, y, z); }
-void rlTexCoord2f(float x, float y) { glTexCoord2f(x, y); }
-void rlNormal3f(float x, float y, float z) { glNormal3f(x, y, z); }
-void rlColor4ub(byte r, byte g, byte b, byte a) { glColor4ub(r, g, b, a); }
-void rlColor3f(float x, float y, float z) { glColor3f(x, y, z); }
-void rlColor4f(float x, float y, float z, float w) { glColor4f(x, y, z, w); }
-
-#elif defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-
-// Initialize drawing mode (how to organize vertex)
-void rlBegin(int mode)
-{
-    // Draw mode can only be RL_LINES, RL_TRIANGLES and RL_QUADS
-    currentDrawMode = mode;
-}
-
-// Finish vertex providing
-void rlEnd(void)
-{
-    if (useTempBuffer)
-    {
-        // NOTE: In this case, *currentMatrix is already transposed because transposing has been applied
-        // independently to translation-scale-rotation matrices -> t(M1 x M2) = t(M2) x t(M1)
-        // This way, rlTranslatef(), rlRotatef()... behaviour is the same than OpenGL 1.1
-
-        // Apply transformation matrix to all temp vertices
-        for (int i = 0; i < tempBufferCount; i++) VectorTransform(&tempBuffer[i], *currentMatrix);
-
-        // Deactivate tempBuffer usage to allow rlVertex3f do its job
-        useTempBuffer = false;
-
-        // Copy all transformed vertices to right VAO
-        for (int i = 0; i < tempBufferCount; i++) rlVertex3f(tempBuffer[i].x, tempBuffer[i].y, tempBuffer[i].z);
-
-        // Reset temp buffer
-        tempBufferCount = 0;
-    }
-
-    // Make sure vertexCount is the same for vertices-texcoords-normals-colors
-    // NOTE: In OpenGL 1.1, one glColor call can be made for all the subsequent glVertex calls.
-    switch (currentDrawMode)
-    {
-        case RL_LINES:
-        {
-            if (lines.vCounter != lines.cCounter)
-            {
-                int addColors = lines.vCounter - lines.cCounter;
-
-                for (int i = 0; i < addColors; i++)
-                {
-                    lines.colors[4*lines.cCounter] = lines.colors[4*lines.cCounter - 4];
-                    lines.colors[4*lines.cCounter + 1] = lines.colors[4*lines.cCounter - 3];
-                    lines.colors[4*lines.cCounter + 2] = lines.colors[4*lines.cCounter - 2];
-                    lines.colors[4*lines.cCounter + 3] = lines.colors[4*lines.cCounter - 1];
-
-                    lines.cCounter++;
-                }
-            }
-        } break;
-        case RL_TRIANGLES:
-        {
-            if (triangles.vCounter != triangles.cCounter)
-            {
-                int addColors = triangles.vCounter - triangles.cCounter;
-
-                for (int i = 0; i < addColors; i++)
-                {
-                    triangles.colors[4*triangles.cCounter] = triangles.colors[4*triangles.cCounter - 4];
-                    triangles.colors[4*triangles.cCounter + 1] = triangles.colors[4*triangles.cCounter - 3];
-                    triangles.colors[4*triangles.cCounter + 2] = triangles.colors[4*triangles.cCounter - 2];
-                    triangles.colors[4*triangles.cCounter + 3] = triangles.colors[4*triangles.cCounter - 1];
-
-                    triangles.cCounter++;
-                }
-            }
-        } break;
-        case RL_QUADS:
-        {
-            // Make sure colors count match vertex count
-            if (quads.vCounter != quads.cCounter)
-            {
-                int addColors = quads.vCounter - quads.cCounter;
-
-                for (int i = 0; i < addColors; i++)
-                {
-                    quads.colors[4*quads.cCounter] = quads.colors[4*quads.cCounter - 4];
-                    quads.colors[4*quads.cCounter + 1] = quads.colors[4*quads.cCounter - 3];
-                    quads.colors[4*quads.cCounter + 2] = quads.colors[4*quads.cCounter - 2];
-                    quads.colors[4*quads.cCounter + 3] = quads.colors[4*quads.cCounter - 1];
-
-                    quads.cCounter++;
-                }
-            }
-
-            // Make sure texcoords count match vertex count
-            if (quads.vCounter != quads.tcCounter)
-            {
-                int addTexCoords = quads.vCounter - quads.tcCounter;
-
-                for (int i = 0; i < addTexCoords; i++)
-                {
-                    quads.texcoords[2*quads.tcCounter] = 0.0f;
-                    quads.texcoords[2*quads.tcCounter + 1] = 0.0f;
-
-                    quads.tcCounter++;
-                }
-            }
-
-            // TODO: Make sure normals count match vertex count... if normals support is added in a future... :P
-
-        } break;
-        default: break;
-    }
-    
-    // NOTE: Depth increment is dependant on rlOrtho(): z-near and z-far values,
-    // as well as depth buffer bit-depth (16bit or 24bit or 32bit)
-    // Correct increment formula would be: depthInc = (zfar - znear)/pow(2, bits)
-    currentDepth += (1.0f/20000.0f);
-}
-
-// Define one vertex (position)
-void rlVertex3f(float x, float y, float z)
-{
-    if (useTempBuffer)
-    {
-        tempBuffer[tempBufferCount].x = x;
-        tempBuffer[tempBufferCount].y = y;
-        tempBuffer[tempBufferCount].z = z;
-        tempBufferCount++;
-    }
-    else
-    {
-        switch (currentDrawMode)
-        {
-            case RL_LINES:
-            {
-                // Verify that MAX_LINES_BATCH limit not reached
-                if (lines.vCounter / 2 < MAX_LINES_BATCH)
-                {
-                    lines.vertices[3*lines.vCounter] = x;
-                    lines.vertices[3*lines.vCounter + 1] = y;
-                    lines.vertices[3*lines.vCounter + 2] = z;
-
-                    lines.vCounter++;
-                }
-                else TraceLog(ERROR, "MAX_LINES_BATCH overflow");
-
-            } break;
-            case RL_TRIANGLES:
-            {
-                // Verify that MAX_TRIANGLES_BATCH limit not reached
-                if (triangles.vCounter / 3 < MAX_TRIANGLES_BATCH)
-                {
-                    triangles.vertices[3*triangles.vCounter] = x;
-                    triangles.vertices[3*triangles.vCounter + 1] = y;
-                    triangles.vertices[3*triangles.vCounter + 2] = z;
-
-                    triangles.vCounter++;
-                }
-                else TraceLog(ERROR, "MAX_TRIANGLES_BATCH overflow");
-
-            } break;
-            case RL_QUADS:
-            {
-                // Verify that MAX_QUADS_BATCH limit not reached
-                if (quads.vCounter / 4 < MAX_QUADS_BATCH)
-                {
-                    quads.vertices[3*quads.vCounter] = x;
-                    quads.vertices[3*quads.vCounter + 1] = y;
-                    quads.vertices[3*quads.vCounter + 2] = z;
-
-                    quads.vCounter++;
-
-                    draws[drawsCounter - 1].vertexCount++;
-                }
-                else TraceLog(ERROR, "MAX_QUADS_BATCH overflow");
-
-            } break;
-            default: break;
-        }
-    }
-}
-
-// Define one vertex (position)
-void rlVertex2f(float x, float y)
-{
-    rlVertex3f(x, y, currentDepth);
-}
-
-// Define one vertex (position)
-void rlVertex2i(int x, int y)
-{
-    rlVertex3f((float)x, (float)y, currentDepth);
-}
-
-// Define one vertex (texture coordinate)
-// NOTE: Texture coordinates are limited to QUADS only
-void rlTexCoord2f(float x, float y)
-{
-    if (currentDrawMode == RL_QUADS)
-    {
-        quads.texcoords[2*quads.tcCounter] = x;
-        quads.texcoords[2*quads.tcCounter + 1] = y;
-
-        quads.tcCounter++;
-    }
-}
-
-// Define one vertex (normal)
-// NOTE: Normals limited to TRIANGLES only ?
-void rlNormal3f(float x, float y, float z)
-{
-    // TODO: Normals usage...
-}
-
-// Define one vertex (color)
-void rlColor4ub(byte x, byte y, byte z, byte w)
-{
-    switch (currentDrawMode)
-    {
-        case RL_LINES:
-        {
-            lines.colors[4*lines.cCounter] = x;
-            lines.colors[4*lines.cCounter + 1] = y;
-            lines.colors[4*lines.cCounter + 2] = z;
-            lines.colors[4*lines.cCounter + 3] = w;
-
-            lines.cCounter++;
-
-        } break;
-        case RL_TRIANGLES:
-        {
-            triangles.colors[4*triangles.cCounter] = x;
-            triangles.colors[4*triangles.cCounter + 1] = y;
-            triangles.colors[4*triangles.cCounter + 2] = z;
-            triangles.colors[4*triangles.cCounter + 3] = w;
-
-            triangles.cCounter++;
-
-        } break;
-        case RL_QUADS:
-        {
-            quads.colors[4*quads.cCounter] = x;
-            quads.colors[4*quads.cCounter + 1] = y;
-            quads.colors[4*quads.cCounter + 2] = z;
-            quads.colors[4*quads.cCounter + 3] = w;
-
-            quads.cCounter++;
-
-        } break;
-        default: break;
-    }
-}
-
-// Define one vertex (color)
-void rlColor4f(float r, float g, float b, float a)
-{
-    rlColor4ub((byte)(r*255), (byte)(g*255), (byte)(b*255), (byte)(a*255));
-}
-
-// Define one vertex (color)
-void rlColor3f(float x, float y, float z)
-{
-    rlColor4ub((byte)(x*255), (byte)(y*255), (byte)(z*255), 255);
-}
-
-#endif
-
-//----------------------------------------------------------------------------------
-// Module Functions Definition - OpenGL equivalent functions (common to 1.1, 3.3+, ES2)
-//----------------------------------------------------------------------------------
-
-// Enable texture usage
-void rlEnableTexture(unsigned int id)
-{
-#if defined(GRAPHICS_API_OPENGL_11)
-    glEnable(GL_TEXTURE_2D);
-    glBindTexture(GL_TEXTURE_2D, id);
-#endif
-
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    if (draws[drawsCounter - 1].textureId != id)
-    {
-        if (draws[drawsCounter - 1].vertexCount > 0) drawsCounter++;
-
-        draws[drawsCounter - 1].textureId = id;
-        draws[drawsCounter - 1].vertexCount = 0;
-    }
-#endif
-}
-
-// Disable texture usage
-void rlDisableTexture(void)
-{
-#if defined(GRAPHICS_API_OPENGL_11)
-    glDisable(GL_TEXTURE_2D);
-    glBindTexture(GL_TEXTURE_2D, 0);
-#endif
-}
-
-// Enable rendering to texture (fbo)
-void rlEnableRenderTexture(unsigned int id)
-{
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    glBindFramebuffer(GL_FRAMEBUFFER, id);
-
-    //glDisable(GL_CULL_FACE);    // Allow double side drawing for texture flipping
-    //glCullFace(GL_FRONT);
-#endif
-}
-
-// Disable rendering to texture
-void rlDisableRenderTexture(void)
-{
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    glBindFramebuffer(GL_FRAMEBUFFER, 0);
-
-    //glEnable(GL_CULL_FACE);
-    //glCullFace(GL_BACK);
-#endif
-}
-
-// Enable depth test
-void rlEnableDepthTest(void)
-{
-    glEnable(GL_DEPTH_TEST);
-}
-
-// Disable depth test
-void rlDisableDepthTest(void)
-{
-    glDisable(GL_DEPTH_TEST);
-}
-
-// Enable wire mode
-void rlEnableWireMode(void)
-{
-#if defined (GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33)
-    // NOTE: glPolygonMode() not available on OpenGL ES
-    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
-#endif
-}
-
-// Disable wire mode
-void rlDisableWireMode(void)
-{
-#if defined (GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33)
-    // NOTE: glPolygonMode() not available on OpenGL ES
-    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
-#endif
-}
-
-// Unload texture from GPU memory
-void rlDeleteTextures(unsigned int id)
-{
-    if (id != 0) glDeleteTextures(1, &id);
-}
-
-// Unload render texture from GPU memory
-void rlDeleteRenderTextures(RenderTexture2D target)
-{
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    if (target.id != 0) glDeleteFramebuffers(1, &target.id);
-    if (target.texture.id != 0) glDeleteTextures(1, &target.texture.id);
-    if (target.depth.id != 0) glDeleteTextures(1, &target.depth.id);
-#endif
-}
-
-// Unload shader from GPU memory
-void rlDeleteShader(unsigned int id)
-{
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    if (id != 0) glDeleteProgram(id);
-#endif
-}
-
-// Unload vertex data (VAO) from GPU memory
-void rlDeleteVertexArrays(unsigned int id)
-{
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    if (vaoSupported) 
-    {
-        if (id != 0) glDeleteVertexArrays(1, &id);
-        TraceLog(INFO, "[VAO ID %i] Unloaded model data from VRAM (GPU)", id);
-    }
-#endif
-}
-
-// Unload vertex data (VBO) from GPU memory
-void rlDeleteBuffers(unsigned int id)
-{
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    if (id != 0)
-    {
-        glDeleteBuffers(1, &id);
-        if (!vaoSupported) TraceLog(INFO, "[VBO ID %i] Unloaded model vertex data from VRAM (GPU)", id);
-    }
-#endif
-}
-
-// Clear color buffer with color
-void rlClearColor(byte r, byte g, byte b, byte a)
-{
-    // Color values clamp to 0.0f(0) and 1.0f(255)
-    float cr = (float)r/255;
-    float cg = (float)g/255;
-    float cb = (float)b/255;
-    float ca = (float)a/255;
-
-    glClearColor(cr, cg, cb, ca);
-}
-
-// Clear used screen buffers (color and depth)
-void rlClearScreenBuffers(void)
-{
-    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);     // Clear used buffers: Color and Depth (Depth is used for 3D)
-    //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);     // Stencil buffer not used...
-}
-
-// Returns current OpenGL version
-int rlGetVersion(void)
-{
-#if defined(GRAPHICS_API_OPENGL_11)
-    return OPENGL_11;
-#elif defined(GRAPHICS_API_OPENGL_33)
-    return OPENGL_33;
-#elif defined(GRAPHICS_API_OPENGL_ES2)
-    return OPENGL_ES_20;
-#endif
-}
-
-//----------------------------------------------------------------------------------
-// Module Functions Definition - rlgl Functions
-//----------------------------------------------------------------------------------
-
-// Init OpenGL 3.3+ required data
-void rlglInit(void)
-{
-    // Check OpenGL information and capabilities
-    //------------------------------------------------------------------------------
-    
-    // Print current OpenGL and GLSL version
-    TraceLog(INFO, "GPU: Vendor:   %s", glGetString(GL_VENDOR));
-    TraceLog(INFO, "GPU: Renderer: %s", glGetString(GL_RENDERER));
-    TraceLog(INFO, "GPU: Version:  %s", glGetString(GL_VERSION));
-    TraceLog(INFO, "GPU: GLSL:     %s", glGetString(GL_SHADING_LANGUAGE_VERSION));
-
-    // NOTE: We can get a bunch of extra information about GPU capabilities (glGet*)
-    //int maxTexSize;
-    //glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexSize);
-    //TraceLog(INFO, "GL_MAX_TEXTURE_SIZE: %i", maxTexSize);
-    
-    //GL_MAX_TEXTURE_IMAGE_UNITS
-    //GL_MAX_VIEWPORT_DIMS
-
-    //int numAuxBuffers;
-    //glGetIntegerv(GL_AUX_BUFFERS, &numAuxBuffers);
-    //TraceLog(INFO, "GL_AUX_BUFFERS: %i", numAuxBuffers);
-    
-    //GLint numComp = 0;
-    //GLint format[32] = { 0 };
-    //glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numComp);
-    //glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, format);
-    //for (int i = 0; i < numComp; i++) TraceLog(INFO, "Supported compressed format: 0x%x", format[i]);
-
-    // NOTE: We don't need that much data on screen... right now...
-    
-#if defined(GRAPHICS_API_OPENGL_11)
-    //TraceLog(INFO, "OpenGL 1.1 (or driver default) profile initialized");
-#endif
-
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    // Get supported extensions list
-    GLint numExt = 0;
-    
-#if defined(GRAPHICS_API_OPENGL_33)
-
-    // NOTE: On OpenGL 3.3 VAO and NPOT are supported by default
-    vaoSupported = true;
-    npotSupported = true;
-
-    // We get a list of available extensions and we check for some of them (compressed textures)
-    // NOTE: We don't need to check again supported extensions but we do (GLAD already dealt with that)
-    glGetIntegerv(GL_NUM_EXTENSIONS, &numExt);
-    const char *extList[numExt];
-    
-    for (int i = 0; i < numExt; i++) extList[i] = (char *)glGetStringi(GL_EXTENSIONS, i);
-    
-#elif defined(GRAPHICS_API_OPENGL_ES2)
-    char *extensions = (char *)glGetString(GL_EXTENSIONS);  // One big const string
-    
-    // NOTE: We have to duplicate string because glGetString() returns a const value
-    // If not duplicated, it fails in some systems (Raspberry Pi)
-    // Equivalent to function: char *strdup(const char *str)
-    char *extensionsDup;
-    size_t len = strlen(extensions) + 1;
-    void *newstr = malloc(len);
-    if (newstr == NULL) extensionsDup = NULL;
-    extensionsDup = (char *)memcpy(newstr, extensions, len);
-    
-    // NOTE: String could be splitted using strtok() function (string.h)
-    // NOTE: strtok() modifies the received string, it can not be const
-    
-    char *extList[512];     // Allocate 512 strings pointers (2 KB)
-    
-    extList[numExt] = strtok(extensionsDup, " ");
-
-    while (extList[numExt] != NULL)
-    {
-        numExt++;
-        extList[numExt] = strtok(NULL, " ");
-    }
-    
-    free(extensionsDup);    // Duplicated string must be deallocated
-    
-    numExt -= 1;
-#endif
-
-    TraceLog(INFO, "Number of supported extensions: %i", numExt);
-
-    // Show supported extensions
-    //for (int i = 0; i < numExt; i++)  TraceLog(INFO, "Supported extension: %s", extList[i]);
-
-    // Check required extensions
-    for (int i = 0; i < numExt; i++)
-    {
-#if defined(GRAPHICS_API_OPENGL_ES2)
-        // Check VAO support
-        // NOTE: Only check on OpenGL ES, OpenGL 3.3 has VAO support as core feature
-        if (strcmp(extList[i], (const char *)"GL_OES_vertex_array_object") == 0)
-        {
-            vaoSupported = true;
-            
-            // The extension is supported by our hardware and driver, try to get related functions pointers           
-            // NOTE: emscripten does not support VAOs natively, it uses emulation and it reduces overall performance...
-            glGenVertexArrays = (PFNGLGENVERTEXARRAYSOESPROC)eglGetProcAddress("glGenVertexArraysOES");
-            glBindVertexArray = (PFNGLBINDVERTEXARRAYOESPROC)eglGetProcAddress("glBindVertexArrayOES");
-            glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSOESPROC)eglGetProcAddress("glDeleteVertexArraysOES");
-            //glIsVertexArray = (PFNGLISVERTEXARRAYOESPROC)eglGetProcAddress("glIsVertexArrayOES");     // NOTE: Fails in WebGL, omitted
-        }
-        
-        // Check NPOT textures support
-        // NOTE: Only check on OpenGL ES, OpenGL 3.3 has NPOT textures full support as core feature
-        if (strcmp(extList[i], (const char *)"GL_OES_texture_npot") == 0) npotSupported = true;
-#endif   
-        
-        // DDS texture compression support
-        if ((strcmp(extList[i], (const char *)"GL_EXT_texture_compression_s3tc") == 0) ||
-            (strcmp(extList[i], (const char *)"GL_WEBGL_compressed_texture_s3tc") == 0) ||
-            (strcmp(extList[i], (const char *)"GL_WEBKIT_WEBGL_compressed_texture_s3tc") == 0)) texCompDXTSupported = true; 
-        
-        // ETC1 texture compression support
-        if ((strcmp(extList[i], (const char *)"GL_OES_compressed_ETC1_RGB8_texture") == 0) ||
-            (strcmp(extList[i], (const char *)"GL_WEBGL_compressed_texture_etc1") == 0)) texCompETC1Supported = true;
-
-        // ETC2/EAC texture compression support
-        if (strcmp(extList[i], (const char *)"GL_ARB_ES3_compatibility") == 0) texCompETC2Supported = true;
-
-        // PVR texture compression support
-        if (strcmp(extList[i], (const char *)"GL_IMG_texture_compression_pvrtc") == 0) texCompPVRTSupported = true;
-
-        // ASTC texture compression support
-        if (strcmp(extList[i], (const char *)"GL_KHR_texture_compression_astc_hdr") == 0) texCompASTCSupported = true;
-    }
-    
-#if defined(GRAPHICS_API_OPENGL_ES2)
-    if (vaoSupported) TraceLog(INFO, "[EXTENSION] VAO extension detected, VAO functions initialized successfully");
-    else TraceLog(WARNING, "[EXTENSION] VAO extension not found, VAO usage not supported");
-    
-    if (npotSupported) TraceLog(INFO, "[EXTENSION] NPOT textures extension detected, full NPOT textures supported");
-    else TraceLog(WARNING, "[EXTENSION] NPOT textures extension not found, limited NPOT support (no-mipmaps, no-repeat)");
-#endif
-
-    if (texCompDXTSupported) TraceLog(INFO, "[EXTENSION] DXT compressed textures supported");
-    if (texCompETC1Supported) TraceLog(INFO, "[EXTENSION] ETC1 compressed textures supported");
-    if (texCompETC2Supported) TraceLog(INFO, "[EXTENSION] ETC2/EAC compressed textures supported");
-    if (texCompPVRTSupported) TraceLog(INFO, "[EXTENSION] PVRT compressed textures supported");
-    if (texCompASTCSupported) TraceLog(INFO, "[EXTENSION] ASTC compressed textures supported");
-
-    // Initialize buffers, default shaders and default textures
-    //----------------------------------------------------------
-    
-    // Set default draw mode
-    currentDrawMode = RL_TRIANGLES;
-
-    // Reset projection and modelview matrices
-    projection = MatrixIdentity();
-    modelview = MatrixIdentity();
-    currentMatrix = &modelview;
-
-    // Initialize matrix stack
-    for (int i = 0; i < MATRIX_STACK_SIZE; i++) stack[i] = MatrixIdentity();
-    
-    // Create default white texture for plain colors (required by shader)
-    unsigned char pixels[4] = { 255, 255, 255, 255 };   // 1 pixel RGBA (4 bytes)
-
-    whiteTexture = rlglLoadTexture(pixels, 1, 1, UNCOMPRESSED_R8G8B8A8, 1);
-
-    if (whiteTexture != 0) TraceLog(INFO, "[TEX ID %i] Base white texture loaded successfully", whiteTexture);
-    else TraceLog(WARNING, "Base white texture could not be loaded");
-
-    // Init default Shader (customized for GL 3.3 and ES2)
-    defaultShader = LoadDefaultShader();
-    currentShader = defaultShader;
-
-    LoadDefaultBuffers();        // Initialize default vertex arrays buffers (lines, triangles, quads)
-
-    // Init temp vertex buffer, used when transformation required (translate, rotate, scale)
-    tempBuffer = (Vector3 *)malloc(sizeof(Vector3)*TEMP_VERTEX_BUFFER_SIZE);
-
-    for (int i = 0; i < TEMP_VERTEX_BUFFER_SIZE; i++) tempBuffer[i] = VectorZero();
-
-    // Init draw calls tracking system
-    draws = (DrawCall *)malloc(sizeof(DrawCall)*MAX_DRAWS_BY_TEXTURE);
-
-    for (int i = 0; i < MAX_DRAWS_BY_TEXTURE; i++)
-    {
-        draws[i].textureId = 0;
-        draws[i].vertexCount = 0;
-    }
-
-    drawsCounter = 1;
-    draws[drawsCounter - 1].textureId = whiteTexture;
-#endif
-}
-
-// Vertex Buffer Object deinitialization (memory free)
-void rlglClose(void)
-{
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    UnloadDefaultShader();
-    UnloadStandardShader();
-    UnloadDefaultBuffers();
-    
-    // Delete default white texture
-    glDeleteTextures(1, &whiteTexture);
-    TraceLog(INFO, "[TEX ID %i] Unloaded texture data (base white texture) from VRAM", whiteTexture);
-    
-    // Unload lights
-    if (lightsCount > 0)
-    {
-        for (int i = 0; i < lightsCount; i++) free(lights[i]);
-        lightsCount = 0;
-    }
-
-    free(draws);
-#endif
-}
-
-// Drawing batches: triangles, quads, lines
-void rlglDraw(void)
-{
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-/*
-    for (int i = 0; i < modelsCount; i++)
-    {
-        rlglDrawMesh(models[i]->mesh, models[i]->material, models[i]->transform);
-    }
-*/
-    // NOTE: Default buffers always drawn at the end
-    UpdateDefaultBuffers();
-    DrawDefaultBuffers();
-#endif
-}
-
-// Initialize Graphics Device (OpenGL stuff)
-// NOTE: Stores global variables screenWidth and screenHeight
-void rlglInitGraphics(int offsetX, int offsetY, int width, int height)
-{   
-    // NOTE: Required! viewport must be recalculated if screen resized!
-    glViewport(offsetX/2, offsetY/2, width - offsetX, height - offsetY);    // Set viewport width and height
-
-    // NOTE: Don't confuse glViewport with the transformation matrix
-    // NOTE: glViewport just defines the area of the context that you will actually draw to.
-
-    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);                   // Set clear color (black)
-    //glClearDepth(1.0f);                                   // Clear depth buffer (default)
-    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);     // Clear used buffers, depth buffer is used for 3D
-
-    glDisable(GL_DEPTH_TEST);                               // Disable depth testing for 2D (only used for 3D)
-    glDepthFunc(GL_LEQUAL);                                 // Type of depth testing to apply
-
-    glEnable(GL_BLEND);                                     // Enable color blending (required to work with transparencies)
-    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);      // Color blending function (how colors are mixed)
-
-#if defined(GRAPHICS_API_OPENGL_11)
-    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);      // Improve quality of color and texture coordinate interpolation (Deprecated in OGL 3.0)
-                                                            // Other options: GL_FASTEST, GL_DONT_CARE (default)
-#endif
-
-    rlMatrixMode(RL_PROJECTION);                // Switch to PROJECTION matrix
-    rlLoadIdentity();                           // Reset current matrix (PROJECTION)
-
-    rlOrtho(0, width - offsetX, height - offsetY, 0, 0.0f, 1.0f); // Config orthographic mode: top-left corner --> (0,0)
-
-    rlMatrixMode(RL_MODELVIEW);                 // Switch back to MODELVIEW matrix
-    rlLoadIdentity();                           // Reset current matrix (MODELVIEW)
-
-    // NOTE: All shapes/models triangles are drawn CCW
-
-    glEnable(GL_CULL_FACE);       // Enable backface culling (Disabled by default)
-    //glCullFace(GL_BACK);        // Cull the Back face (default)
-    //glFrontFace(GL_CCW);        // Front face are defined counter clockwise (default)
-
-#if defined(GRAPHICS_API_OPENGL_11)
-    glShadeModel(GL_SMOOTH);      // Smooth shading between vertex (vertex colors interpolation) (Deprecated on OpenGL 3.3+)
-                                  // Possible options: GL_SMOOTH (Color interpolation) or GL_FLAT (no interpolation)
-#endif
-
-    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)
-{
-    Vector3 result = { 0.0f, 0.0f, 0.0f };
-    
-    // Calculate unproject matrix (multiply projection matrix and view matrix) and invert it
-    Matrix matProjView = MatrixMultiply(proj, view);
-    MatrixInvert(&matProjView);
-    
-    // Create quaternion from source point
-    Quaternion quat = { source.x, source.y, source.z, 1.0f };
-    
-    // Multiply quat point by unproject matrix
-    QuaternionTransform(&quat, matProjView);
-    
-    // Normalized world points in vectors
-    result.x = quat.x/quat.w;
-    result.y = quat.y/quat.w;
-    result.z = quat.z/quat.w;
-
-    return result;
-}
-
-// Convert image data to OpenGL texture (returns OpenGL valid Id)
-unsigned int rlglLoadTexture(void *data, int width, int height, int textureFormat, int mipmapCount)
-{
-    glBindTexture(GL_TEXTURE_2D, 0);    // Free any old binding
-
-    GLuint id = 0;
-    
-    // Check texture format support by OpenGL 1.1 (compressed textures not supported)
-#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)))
-    {
-        TraceLog(WARNING, "DXT compressed texture format not supported");
-        return id;
-    }
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)    
-    if ((!texCompETC1Supported) && (textureFormat == COMPRESSED_ETC1_RGB))
-    {
-        TraceLog(WARNING, "ETC1 compressed texture format not supported");
-        return id;
-    }
-    
-    if ((!texCompETC2Supported) && ((textureFormat == COMPRESSED_ETC2_RGB) || (textureFormat == COMPRESSED_ETC2_EAC_RGBA)))
-    {
-        TraceLog(WARNING, "ETC2 compressed texture format not supported");
-        return id;
-    }
-    
-    if ((!texCompPVRTSupported) && ((textureFormat == COMPRESSED_PVRT_RGB) || (textureFormat == COMPRESSED_PVRT_RGBA)))
-    {
-        TraceLog(WARNING, "PVRT compressed texture format not supported");
-        return id;
-    }
-    
-    if ((!texCompASTCSupported) && ((textureFormat == COMPRESSED_ASTC_4x4_RGBA) || (textureFormat == COMPRESSED_ASTC_8x8_RGBA)))
-    {
-        TraceLog(WARNING, "ASTC compressed texture format not supported");
-        return id;
-    }
-#endif
-
-    glGenTextures(1, &id);              // Generate Pointer to the texture
-
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    //glActiveTexture(GL_TEXTURE0);     // If not defined, using GL_TEXTURE0 by default (shader texture)
-#endif
-
-    glBindTexture(GL_TEXTURE_2D, id);
-
-#if defined(GRAPHICS_API_OPENGL_33)
-    // NOTE: We define internal (GPU) format as GL_RGBA8 (probably BGRA8 in practice, driver takes care)
-    // NOTE: On embedded systems, we let the driver choose the best internal format
-
-    // Support for multiple color modes (16bit color modes and grayscale)
-    // (sized)internalFormat    format          type
-    // GL_R                     GL_RED      GL_UNSIGNED_BYTE
-    // GL_RGB565                GL_RGB      GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_6_5
-    // GL_RGB5_A1               GL_RGBA     GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_5_5_1
-    // GL_RGBA4                 GL_RGBA     GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_4_4_4_4
-    // GL_RGBA8                 GL_RGBA     GL_UNSIGNED_BYTE
-    // GL_RGB8                  GL_RGB      GL_UNSIGNED_BYTE
-    
-    switch (textureFormat)
-    {
-        case UNCOMPRESSED_GRAYSCALE:
-        {
-            glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, (unsigned char *)data);
-            
-            // With swizzleMask we define how a one channel texture will be mapped to RGBA
-            // Required GL >= 3.3 or EXT_texture_swizzle/ARB_texture_swizzle
-            GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, GL_ONE };
-            glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
-            
-            TraceLog(INFO, "[TEX ID %i] Grayscale texture loaded and swizzled", id);
-        } break;
-        case UNCOMPRESSED_GRAY_ALPHA:
-        {
-            glTexImage2D(GL_TEXTURE_2D, 0, GL_RG8, width, height, 0, GL_RG, GL_UNSIGNED_BYTE, (unsigned char *)data);
-            
-            GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, GL_GREEN };
-            glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
-        } break;
-
-        case UNCOMPRESSED_R5G6B5: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, (unsigned short *)data); break;
-        case UNCOMPRESSED_R8G8B8: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, (unsigned char *)data); break;
-        case UNCOMPRESSED_R5G5B5A1: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5_A1, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, (unsigned short *)data); break;
-        case UNCOMPRESSED_R4G4B4A4: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA4, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, (unsigned short *)data); break;
-        case UNCOMPRESSED_R8G8B8A8: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)data); break;
-        case COMPRESSED_DXT1_RGB: if (texCompDXTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGB_S3TC_DXT1_EXT); break;
-        case COMPRESSED_DXT1_RGBA: if (texCompDXTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT); break;
-        case COMPRESSED_DXT3_RGBA: if (texCompDXTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT); break;
-        case COMPRESSED_DXT5_RGBA: if (texCompDXTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT); break;
-        case COMPRESSED_ETC1_RGB: if (texCompETC1Supported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_ETC1_RGB8_OES); break;           // NOTE: Requires OpenGL ES 2.0 or OpenGL 4.3
-        case COMPRESSED_ETC2_RGB: if (texCompETC2Supported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGB8_ETC2); break;    // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3
-        case COMPRESSED_ETC2_EAC_RGBA: if (texCompETC2Supported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA8_ETC2_EAC); break;    // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3
-        case COMPRESSED_PVRT_RGB: if (texCompPVRTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG); break;        // NOTE: Requires PowerVR GPU
-        case COMPRESSED_PVRT_RGBA: if (texCompPVRTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG); break;     // NOTE: Requires PowerVR GPU
-        case COMPRESSED_ASTC_4x4_RGBA: if (texCompASTCSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_ASTC_4x4_KHR); break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3
-        case COMPRESSED_ASTC_8x8_RGBA: if (texCompASTCSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_ASTC_8x8_KHR); break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3
-        default: TraceLog(WARNING, "Texture format not recognized"); break;
-    }
-#elif defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_ES2)
-    // NOTE: on OpenGL ES 2.0 (WebGL), internalFormat must match format and options allowed are: GL_LUMINANCE, GL_RGB, GL_RGBA
-    switch (textureFormat)
-    {
-        case UNCOMPRESSED_GRAYSCALE: glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, (unsigned char *)data); break;
-        case UNCOMPRESSED_GRAY_ALPHA: glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, width, height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, (unsigned char *)data); break;
-        case UNCOMPRESSED_R5G6B5: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, (unsigned short *)data); break;
-        case UNCOMPRESSED_R8G8B8: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, (unsigned char *)data); break;
-        case UNCOMPRESSED_R5G5B5A1: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, (unsigned short *)data); break;
-        case UNCOMPRESSED_R4G4B4A4: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, (unsigned short *)data); break;
-        case UNCOMPRESSED_R8G8B8A8: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)data); break;
-#if defined(GRAPHICS_API_OPENGL_ES2)
-        case COMPRESSED_DXT1_RGB: if (texCompDXTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGB_S3TC_DXT1_EXT); break;
-        case COMPRESSED_DXT1_RGBA: if (texCompDXTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT); break;
-        case COMPRESSED_DXT3_RGBA: if (texCompDXTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT); break;     // NOTE: Not supported by WebGL
-        case COMPRESSED_DXT5_RGBA: if (texCompDXTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT); break;     // NOTE: Not supported by WebGL
-        case COMPRESSED_ETC1_RGB: if (texCompETC1Supported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_ETC1_RGB8_OES); break;           // NOTE: Requires OpenGL ES 2.0 or OpenGL 4.3
-        case COMPRESSED_ETC2_RGB: if (texCompETC2Supported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGB8_ETC2); break;    // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3
-        case COMPRESSED_ETC2_EAC_RGBA: if (texCompETC2Supported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA8_ETC2_EAC); break;    // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3
-        case COMPRESSED_PVRT_RGB: if (texCompPVRTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG); break;        // NOTE: Requires PowerVR GPU
-        case COMPRESSED_PVRT_RGBA: if (texCompPVRTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG); break;     // NOTE: Requires PowerVR GPU
-        case COMPRESSED_ASTC_4x4_RGBA: if (texCompASTCSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_ASTC_4x4_KHR); break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3
-        case COMPRESSED_ASTC_8x8_RGBA: if (texCompASTCSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_ASTC_8x8_KHR); break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3
-#endif
-        default: TraceLog(WARNING, "Texture format not supported"); break;
-    }
-#endif
-
-    // Texture parameters configuration
-    // NOTE: glTexParameteri does NOT affect texture uploading, just the way it's used
-#if defined(GRAPHICS_API_OPENGL_ES2)
-    // NOTE: OpenGL ES 2.0 with no GL_OES_texture_npot support (i.e. WebGL) has limited NPOT support, so CLAMP_TO_EDGE must be used
-    if (npotSupported)
-    {
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);       // Set texture to repeat on x-axis
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);       // Set texture to repeat on y-axis
-    }
-    else
-    {
-        // NOTE: If using negative texture coordinates (LoadOBJ()), it does not work!
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);       // Set texture to clamp on x-axis
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);       // Set texture to clamp on y-axis
-    }
-#else
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);       // Set texture to repeat on x-axis
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);       // Set texture to repeat on y-axis
-#endif
-
-    // Magnification and minification filters
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);  // Alternative: GL_LINEAR
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);  // Alternative: GL_LINEAR
-   
-#if defined(GRAPHICS_API_OPENGL_33)
-    if (mipmapCount > 1)
-    {
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);   // Activate Trilinear filtering for mipmaps (must be available)
-    }
-#endif
-
-    // At this point we have the texture loaded in GPU and texture parameters configured
-    
-    // NOTE: If mipmaps were not in data, they are not generated automatically
-
-    // Unbind current texture
-    glBindTexture(GL_TEXTURE_2D, 0);
-
-    if (id > 0) TraceLog(INFO, "[TEX ID %i] Texture created successfully (%ix%i)", id, width, height);
-    else TraceLog(WARNING, "Texture could not be created");
-
-    return id;
-}
-
-// Load a texture to be used for rendering (fbo with color and depth attachments)
-RenderTexture2D rlglLoadRenderTexture(int width, int height)
-{
-    RenderTexture2D target;
-    
-    target.id = 0;
-    
-    target.texture.id = 0;
-    target.texture.width = width;
-    target.texture.height = height;
-    target.texture.format = UNCOMPRESSED_R8G8B8;
-    target.texture.mipmaps = 1;
-    
-    target.depth.id = 0;
-    target.depth.width = width;
-    target.depth.height = height;
-    target.depth.format = 19;       //DEPTH_COMPONENT_24BIT
-    target.depth.mipmaps = 1;
-
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    // Create the texture that will serve as the color attachment for the framebuffer
-    glGenTextures(1, &target.texture.id);
-    glBindTexture(GL_TEXTURE_2D, target.texture.id);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
-    glBindTexture(GL_TEXTURE_2D, 0);
-    
-#if defined(GRAPHICS_API_OPENGL_33)
-    #define USE_DEPTH_TEXTURE
-#else
-    #define USE_DEPTH_RENDERBUFFER
-#endif
-    
-#if defined(USE_DEPTH_RENDERBUFFER)
-    // Create the renderbuffer that will serve as the depth attachment for the framebuffer.
-    glGenRenderbuffers(1, &target.depth.id);
-    glBindRenderbuffer(GL_RENDERBUFFER, target.depth.id);
-    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);    // GL_DEPTH_COMPONENT24 not supported on Android
-#elif defined(USE_DEPTH_TEXTURE)
-    // NOTE: We can also use a texture for depth buffer (GL_ARB_depth_texture/GL_OES_depth_texture extension required)
-    // A renderbuffer is simpler than a texture and could offer better performance on embedded devices
-    glGenTextures(1, &target.depth.id);
-    glBindTexture(GL_TEXTURE_2D, target.depth.id);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
-    glBindTexture(GL_TEXTURE_2D, 0);
-#endif
-
-    // Create the framebuffer object
-    glGenFramebuffers(1, &target.id);
-    glBindFramebuffer(GL_FRAMEBUFFER, target.id);
-
-    // Attach color texture and depth renderbuffer to FBO
-    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, target.texture.id, 0);
-#if defined(USE_DEPTH_RENDERBUFFER)
-    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, target.depth.id);
-#elif defined(USE_DEPTH_TEXTURE)
-    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, target.depth.id, 0);
-#endif
-
-    GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
-
-    if (status != GL_FRAMEBUFFER_COMPLETE)
-    {
-        TraceLog(WARNING, "Framebuffer object could not be created...");
-        
-        switch (status)
-        {
-            case GL_FRAMEBUFFER_UNSUPPORTED: TraceLog(WARNING, "Framebuffer is unsupported"); break;
-            case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: TraceLog(WARNING, "Framebuffer incomplete attachment"); break;
-#if defined(GRAPHICS_API_OPENGL_ES2)
-            case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: TraceLog(WARNING, "Framebuffer incomplete dimensions"); break;
-#endif
-            case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: TraceLog(WARNING, "Framebuffer incomplete missing attachment"); break;
-            default: break;
-        }
-        
-        glDeleteTextures(1, &target.texture.id);
-        glDeleteTextures(1, &target.depth.id);
-        glDeleteFramebuffers(1, &target.id);
-    }
-    else TraceLog(INFO, "[FBO ID %i] Framebuffer object created successfully", target.id);
-    
-    glBindFramebuffer(GL_FRAMEBUFFER, 0);
-#endif
-
-    return target; 
-}
-
-// Update already loaded texture in GPU with new data
-void rlglUpdateTexture(unsigned int id, int width, int height, int format, void *data)
-{
-    glBindTexture(GL_TEXTURE_2D, id);
-
-#if defined(GRAPHICS_API_OPENGL_33)
-    switch (format)
-    {
-        case UNCOMPRESSED_GRAYSCALE: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE, (unsigned char *)data); break;
-        case UNCOMPRESSED_GRAY_ALPHA: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RG, GL_UNSIGNED_BYTE, (unsigned char *)data); break;
-        case UNCOMPRESSED_R5G6B5: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, (unsigned short *)data); break;
-        case UNCOMPRESSED_R8G8B8: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, (unsigned char *)data); break;
-        case UNCOMPRESSED_R5G5B5A1: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, (unsigned short *)data); break;
-        case UNCOMPRESSED_R4G4B4A4: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, (unsigned short *)data); break;
-        case UNCOMPRESSED_R8G8B8A8: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)data); break;
-        default: TraceLog(WARNING, "Texture format updating not supported"); break;
-    }
-#elif defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_ES2)
-    // NOTE: on OpenGL ES 2.0 (WebGL), internalFormat must match format and options allowed are: GL_LUMINANCE, GL_RGB, GL_RGBA
-    switch (format)
-    {
-        case UNCOMPRESSED_GRAYSCALE: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, (unsigned char *)data); break;
-        case UNCOMPRESSED_GRAY_ALPHA: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, (unsigned char *)data); break;
-        case UNCOMPRESSED_R5G6B5: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, (unsigned short *)data); break;
-        case UNCOMPRESSED_R8G8B8: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, (unsigned char *)data); break;
-        case UNCOMPRESSED_R5G5B5A1: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, (unsigned short *)data); break;
-        case UNCOMPRESSED_R4G4B4A4: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, (unsigned short *)data); break;
-        case UNCOMPRESSED_R8G8B8A8: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)data); break;
-        default: TraceLog(WARNING, "Texture format updating not supported"); break;
-    }
-#endif
-}
-
-// Generate mipmap data for selected texture
-void rlglGenerateMipmaps(Texture2D texture)
-{
-    glBindTexture(GL_TEXTURE_2D, texture.id);
-    
-    // Check if texture is power-of-two (POT)
-    bool texIsPOT = false;
-   
-    if (((texture.width > 0) && ((texture.width & (texture.width - 1)) == 0)) && 
-        ((texture.height > 0) && ((texture.height & (texture.height - 1)) == 0))) texIsPOT = true;
-
-    if ((texIsPOT) || (npotSupported))
-    {
-#if defined(GRAPHICS_API_OPENGL_11)
-        // Compute required mipmaps
-        void *data = rlglReadTexturePixels(texture);
-        
-        // NOTE: data size is reallocated to fit mipmaps data
-        // NOTE: CPU mipmap generation only supports RGBA 32bit data
-        int mipmapCount = GenerateMipmaps(data, texture.width, texture.height);
-
-        int size = texture.width*texture.height*4;  // RGBA 32bit only
-        int offset = size;
-
-        int mipWidth = texture.width/2;
-        int mipHeight = texture.height/2;
-
-        // Load the mipmaps
-        for (int level = 1; level < mipmapCount; level++)
-        {
-            glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA8, mipWidth, mipHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, data + offset);
-
-            size = mipWidth*mipHeight*4;
-            offset += size;
-
-            mipWidth /= 2;
-            mipHeight /= 2;
-        }
-        
-        TraceLog(WARNING, "[TEX ID %i] Mipmaps generated manually on CPU side", texture.id);
-        
-        // NOTE: Once mipmaps have been generated and data has been uploaded to GPU VRAM, we can discard RAM data
-        free(data);
-        
-#endif
-
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-        glGenerateMipmap(GL_TEXTURE_2D);    // Generate mipmaps automatically
-        TraceLog(INFO, "[TEX ID %i] Mipmaps generated automatically", texture.id);
-
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);   // Activate Trilinear filtering for mipmaps (must be available)
-#endif
-    }
-    else TraceLog(WARNING, "[TEX ID %i] Mipmaps can not be generated", texture.id);
-
-    glBindTexture(GL_TEXTURE_2D, 0);
-}
-
-// Upload vertex data into a VAO (if supported) and VBO
-void rlglLoadMesh(Mesh *mesh, bool dynamic)
-{
-    mesh->vaoId = 0;        // Vertex Array Object
-    mesh->vboId[0] = 0;     // Vertex positions VBO
-    mesh->vboId[1] = 0;     // Vertex texcoords VBO
-    mesh->vboId[2] = 0;     // Vertex normals VBO
-    mesh->vboId[3] = 0;     // Vertex colors VBO
-    mesh->vboId[4] = 0;     // Vertex tangents VBO
-    mesh->vboId[5] = 0;     // Vertex texcoords2 VBO
-    mesh->vboId[6] = 0;     // Vertex indices VBO
-    
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    int drawHint = GL_STATIC_DRAW;
-    if (dynamic) drawHint = GL_DYNAMIC_DRAW;
-
-    GLuint vaoId = 0;       // Vertex Array Objects (VAO)
-    GLuint vboId[7];        // Vertex Buffer Objects (VBOs)
-
-    if (vaoSupported)
-    {
-        // Initialize Quads VAO (Buffer A)
-        glGenVertexArrays(1, &vaoId);
-        glBindVertexArray(vaoId);
-    }
-
-    // NOTE: Attributes must be uploaded considering default locations points 
-    
-    // Enable vertex attributes: position (shader-location = 0)
-    glGenBuffers(1, &vboId[0]);
-    glBindBuffer(GL_ARRAY_BUFFER, vboId[0]);
-    glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh->vertexCount, mesh->vertices, drawHint);
-    glVertexAttribPointer(0, 3, GL_FLOAT, 0, 0, 0);
-    glEnableVertexAttribArray(0);
-
-    // Enable vertex attributes: texcoords (shader-location = 1)
-    glGenBuffers(1, &vboId[1]);
-    glBindBuffer(GL_ARRAY_BUFFER, vboId[1]);
-    glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*mesh->vertexCount, mesh->texcoords, drawHint);
-    glVertexAttribPointer(1, 2, GL_FLOAT, 0, 0, 0);
-    glEnableVertexAttribArray(1);
-
-    // Enable vertex attributes: normals (shader-location = 2)
-    if (mesh->normals != NULL)
-    {
-        glGenBuffers(1, &vboId[2]);
-        glBindBuffer(GL_ARRAY_BUFFER, vboId[2]);
-        glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh->vertexCount, mesh->normals, drawHint);
-        glVertexAttribPointer(2, 3, GL_FLOAT, 0, 0, 0);
-        glEnableVertexAttribArray(2);
-    }
-    else
-    {
-        // Default color vertex attribute set to WHITE
-        glVertexAttrib3f(2, 1.0f, 1.0f, 1.0f);
-        glDisableVertexAttribArray(2);
-    }
-    
-    // Default color vertex attribute (shader-location = 3)
-    if (mesh->colors != NULL)
-    {
-        glGenBuffers(1, &vboId[3]);
-        glBindBuffer(GL_ARRAY_BUFFER, vboId[3]);
-        glBufferData(GL_ARRAY_BUFFER, sizeof(unsigned char)*4*mesh->vertexCount, mesh->colors, drawHint);
-        glVertexAttribPointer(3, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
-        glEnableVertexAttribArray(3);
-    }
-    else
-    {
-        // Default color vertex attribute set to WHITE
-        glVertexAttrib4f(3, 1.0f, 1.0f, 1.0f, 1.0f);
-        glDisableVertexAttribArray(3);
-    }
-    
-    // Default tangent vertex attribute (shader-location = 4)
-    if (mesh->tangents != NULL)
-    {
-        glGenBuffers(1, &vboId[4]);
-        glBindBuffer(GL_ARRAY_BUFFER, vboId[4]);
-        glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh->vertexCount, mesh->tangents, drawHint);
-        glVertexAttribPointer(4, 3, GL_FLOAT, 0, 0, 0);
-        glEnableVertexAttribArray(4);
-    }
-    else
-    {
-        // Default tangents vertex attribute
-        glVertexAttrib3f(4, 0.0f, 0.0f, 0.0f);
-        glDisableVertexAttribArray(4);
-    }
-    
-    // Default texcoord2 vertex attribute (shader-location = 5)
-    if (mesh->texcoords2 != NULL)
-    {
-        glGenBuffers(1, &vboId[5]);
-        glBindBuffer(GL_ARRAY_BUFFER, vboId[5]);
-        glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*mesh->vertexCount, mesh->texcoords2, drawHint);
-        glVertexAttribPointer(5, 2, GL_FLOAT, 0, 0, 0);
-        glEnableVertexAttribArray(5);
-    }
-    else
-    {
-        // Default tangents vertex attribute
-        glVertexAttrib2f(5, 0.0f, 0.0f);
-        glDisableVertexAttribArray(5);
-    }
-    
-    if (mesh->indices != NULL)
-    {
-        glGenBuffers(1, &vboId[6]);
-        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboId[6]);
-        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned short)*mesh->triangleCount*3, mesh->indices, GL_STATIC_DRAW);
-    }
-
-    
-    mesh->vboId[0] = vboId[0];     // Vertex position VBO
-    mesh->vboId[1] = vboId[1];     // Texcoords VBO
-    mesh->vboId[2] = vboId[2];     // Normals VBO
-    mesh->vboId[3] = vboId[3];     // Colors VBO
-    mesh->vboId[4] = vboId[4];     // Tangents VBO
-    mesh->vboId[5] = vboId[5];     // Texcoords2 VBO
-    mesh->vboId[6] = vboId[6];     // Indices VBO
-
-    if (vaoSupported)
-    {
-        if (vaoId > 0)
-        {
-            mesh->vaoId = vaoId;
-            TraceLog(INFO, "[VAO ID %i] Mesh uploaded successfully to VRAM (GPU)", mesh->vaoId);
-        }
-        else TraceLog(WARNING, "Mesh could not be uploaded to VRAM (GPU)");
-    }
-    else
-    {
-        TraceLog(INFO, "[VBOs] Mesh uploaded successfully to VRAM (GPU)");
-    }
-#endif
-}
-
-// Update vertex data on GPU (upload new data to one buffer)
-void rlglUpdateMesh(Mesh mesh, int buffer, int numVertex)
-{
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    // Activate mesh VAO
-    if (vaoSupported) glBindVertexArray(mesh.vaoId);
-        
-    switch (buffer)
-    {
-        case 0:     // Update vertices (vertex position)
-        {
-            glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[0]);
-            if (numVertex >= mesh.vertexCount) glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*numVertex, mesh.vertices, GL_DYNAMIC_DRAW);
-            else glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*3*numVertex, mesh.vertices);
-            
-        } break;
-        case 1:     // Update texcoords (vertex texture coordinates)
-        {
-            glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[1]);
-            if (numVertex >= mesh.vertexCount) glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*numVertex, mesh.texcoords, GL_DYNAMIC_DRAW);
-            else glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*2*numVertex, mesh.texcoords);
-            
-        } break;
-        case 2:     // Update normals (vertex normals)
-        {
-            glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[0]);
-            if (numVertex >= mesh.vertexCount) glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*numVertex, mesh.normals, GL_DYNAMIC_DRAW);
-            else glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*3*numVertex, mesh.normals);
-            
-        } break;
-        case 3:     // Update colors (vertex colors)
-        {
-            glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[2]);
-            if (numVertex >= mesh.vertexCount) glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*numVertex, mesh.colors, GL_DYNAMIC_DRAW);
-            else glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(unsigned char)*4*numVertex, mesh.colors);
-            
-        } break;
-        case 4:     // Update tangents (vertex tangents)
-        {
-            glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[0]);
-            if (numVertex >= mesh.vertexCount) glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*numVertex, mesh.tangents, GL_DYNAMIC_DRAW);
-            else glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*3*numVertex, mesh.tangents);
-        } break;
-        case 5:     // Update texcoords2 (vertex second texture coordinates)
-        {
-            glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[1]);
-            if (numVertex >= mesh.vertexCount) glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*numVertex, mesh.texcoords2, GL_DYNAMIC_DRAW);
-            else glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*2*numVertex, mesh.texcoords2);
-        } break;
-        default: break;
-    }
-    
-    // Unbind the current VAO
-    if (vaoSupported) glBindVertexArray(0);
-
-    // Another option would be using buffer mapping...
-    //mesh.vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE);
-    // Now we can modify vertices
-    //glUnmapBuffer(GL_ARRAY_BUFFER);
-#endif
-}
-
-// Draw a 3d mesh with material and transform
-void rlglDrawMesh(Mesh mesh, Material material, Matrix transform)
-{
-#if defined(GRAPHICS_API_OPENGL_11)
-    glEnable(GL_TEXTURE_2D);
-    glBindTexture(GL_TEXTURE_2D, material.texDiffuse.id);
-
-    // NOTE: On OpenGL 1.1 we use Vertex Arrays to draw model
-    glEnableClientState(GL_VERTEX_ARRAY);                   // Enable vertex array
-    glEnableClientState(GL_TEXTURE_COORD_ARRAY);            // Enable texture coords array
-    if (mesh.normals != NULL) glEnableClientState(GL_NORMAL_ARRAY);     // Enable normals array
-    if (mesh.colors != NULL) glEnableClientState(GL_COLOR_ARRAY);       // Enable colors array
-
-    glVertexPointer(3, GL_FLOAT, 0, mesh.vertices);         // Pointer to vertex coords array
-    glTexCoordPointer(2, GL_FLOAT, 0, mesh.texcoords);      // Pointer to texture coords array
-    if (mesh.normals != NULL) glNormalPointer(GL_FLOAT, 0, mesh.normals);           // Pointer to normals array
-    if (mesh.colors != NULL) glColorPointer(4, GL_UNSIGNED_BYTE, 0, mesh.colors);   // Pointer to colors array
-
-    rlPushMatrix();
-        rlMultMatrixf(MatrixToFloat(transform));
-        rlColor4ub(material.colDiffuse.r, material.colDiffuse.g, material.colDiffuse.b, material.colDiffuse.a);
-        
-        if (mesh.indices != NULL) glDrawElements(GL_TRIANGLES, mesh.triangleCount*3, GL_UNSIGNED_SHORT, mesh.indices);
-        else glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount);
-    rlPopMatrix();
-
-    glDisableClientState(GL_VERTEX_ARRAY);                  // Disable vertex array
-    glDisableClientState(GL_TEXTURE_COORD_ARRAY);           // Disable texture coords array
-    if (mesh.normals != NULL) glDisableClientState(GL_NORMAL_ARRAY);    // Disable normals array
-    if (mesh.colors != NULL) glDisableClientState(GL_NORMAL_ARRAY);     // Disable colors array
-
-    glDisable(GL_TEXTURE_2D);
-    glBindTexture(GL_TEXTURE_2D, 0);
-#endif
-
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    glUseProgram(material.shader.id);
-    
-    // At this point the modelview matrix just contains the view matrix (camera)
-    // That's because Begin3dMode() sets it an no model-drawing function modifies it, all use rlPushMatrix() and rlPopMatrix()
-    Matrix matView = modelview;         // View matrix (camera)
-    Matrix matProjection = projection;  // Projection matrix (perspective)
-
-    // Calculate model-view matrix combining matModel and matView
-    Matrix matModelView = MatrixMultiply(transform, matView);           // Transform to camera-space coordinates
-
-    // Calculate model-view-projection matrix (MVP)
-    Matrix matMVP = MatrixMultiply(matModelView, matProjection);        // Transform to screen-space coordinates
-
-    // Send combined model-view-projection matrix to shader
-    glUniformMatrix4fv(material.shader.mvpLoc, 1, false, MatrixToFloat(matMVP));
-    
-    // Upload to shader material.colDiffuse
-    float vColorDiffuse[4] = { (float)material.colDiffuse.r/255, (float)material.colDiffuse.g/255, (float)material.colDiffuse.b/255, (float)material.colDiffuse.a/255 };
-    glUniform4fv(material.shader.tintColorLoc, 1, vColorDiffuse);
-
-    // Check if using standard shader to get location points
-    // NOTE: standard shader specific locations are got at render time to keep Shader struct as simple as possible (with just default shader locations)
-    if (material.shader.id == standardShader.id)
-    {
-        // 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(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);
-        
-        // Setup shader uniforms for lights
-        SetShaderLights(material.shader);
-        
-        // Upload to shader material.colAmbient
-        glUniform4f(glGetUniformLocation(material.shader.id, "colAmbient"), (float)material.colAmbient.r/255, (float)material.colAmbient.g/255, (float)material.colAmbient.b/255, (float)material.colAmbient.a/255);
-        
-        // Upload to shader material.colSpecular
-        glUniform4f(glGetUniformLocation(material.shader.id, "colSpecular"), (float)material.colSpecular.r/255, (float)material.colSpecular.g/255, (float)material.colSpecular.b/255, (float)material.colSpecular.a/255);
-    
-        // Upload to shader glossiness
-        glUniform1f(glGetUniformLocation(material.shader.id, "glossiness"), material.glossiness);
-    }    
-    
-    // Set shader textures (diffuse, normal, specular)
-    glActiveTexture(GL_TEXTURE0);
-    glBindTexture(GL_TEXTURE_2D, material.texDiffuse.id);
-    glUniform1i(material.shader.mapTexture0Loc, 0);         // Diffuse texture fits in active texture unit 0
-    
-    if ((material.texNormal.id != 0) && (material.shader.mapTexture1Loc != -1))
-    {
-        // Upload to shader specular map flag
-        glUniform1i(glGetUniformLocation(material.shader.id, "useNormal"), 1);
-        
-        glActiveTexture(GL_TEXTURE1);
-        glBindTexture(GL_TEXTURE_2D, material.texNormal.id);
-        glUniform1i(material.shader.mapTexture1Loc, 1);     // Normal texture fits in active texture unit 1
-    }
-    
-    if ((material.texSpecular.id != 0) && (material.shader.mapTexture2Loc != -1))
-    {
-        // Upload to shader specular map flag
-        glUniform1i(glGetUniformLocation(material.shader.id, "useSpecular"), 1);
-        
-        glActiveTexture(GL_TEXTURE2);
-        glBindTexture(GL_TEXTURE_2D, material.texSpecular.id);
-        glUniform1i(material.shader.mapTexture2Loc, 2);    // Specular texture fits in active texture unit 2
-    }
-
-    if (vaoSupported)
-    {
-        glBindVertexArray(mesh.vaoId);
-    }
-    else
-    {
-        // Bind mesh VBO data: vertex position (shader-location = 0)
-        glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[0]);
-        glVertexAttribPointer(material.shader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
-        glEnableVertexAttribArray(material.shader.vertexLoc);
-
-        // Bind mesh VBO data: vertex texcoords (shader-location = 1)
-        glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[1]);
-        glVertexAttribPointer(material.shader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0);
-        glEnableVertexAttribArray(material.shader.texcoordLoc);
-
-        // Bind mesh VBO data: vertex normals (shader-location = 2, if available)
-        if (material.shader.normalLoc != -1)
-        {
-            glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[2]);
-            glVertexAttribPointer(material.shader.normalLoc, 3, GL_FLOAT, 0, 0, 0);
-            glEnableVertexAttribArray(material.shader.normalLoc);
-        }
-        
-        // Bind mesh VBO data: vertex colors (shader-location = 3, if available) , tangents, texcoords2 (if available)
-        if (material.shader.colorLoc != -1)
-        {
-            glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[3]);
-            glVertexAttribPointer(material.shader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
-            glEnableVertexAttribArray(material.shader.colorLoc);
-        }
-        
-        // Bind mesh VBO data: vertex tangents (shader-location = 4, if available)
-        if (material.shader.tangentLoc != -1)
-        {
-            glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[4]);
-            glVertexAttribPointer(material.shader.tangentLoc, 3, GL_FLOAT, 0, 0, 0);
-            glEnableVertexAttribArray(material.shader.tangentLoc);
-        }
-        
-        // Bind mesh VBO data: vertex texcoords2 (shader-location = 5, if available)
-        if (material.shader.texcoord2Loc != -1)
-        {
-            glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[5]);
-            glVertexAttribPointer(material.shader.texcoord2Loc, 2, GL_FLOAT, 0, 0, 0);
-            glEnableVertexAttribArray(material.shader.texcoord2Loc);
-        }
-        
-        if (mesh.indices != NULL) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quads.vboId[3]);
-    }
-
-    // Draw call!
-    if (mesh.indices != NULL) glDrawElements(GL_TRIANGLES, mesh.triangleCount*3, GL_UNSIGNED_SHORT, 0); // Indexed vertices draw
-    else glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount);
-    
-    if (material.texNormal.id != 0)
-    {
-        glActiveTexture(GL_TEXTURE1);
-        glBindTexture(GL_TEXTURE_2D, 0);
-    }
-    
-    if (material.texSpecular.id != 0)
-    {
-        glActiveTexture(GL_TEXTURE2);
-        glBindTexture(GL_TEXTURE_2D, 0);
-    }
-
-    glActiveTexture(GL_TEXTURE0);               // Set shader active texture to default 0
-    glBindTexture(GL_TEXTURE_2D, 0);            // Unbind textures
-
-    if (vaoSupported) glBindVertexArray(0);     // Unbind VAO
-    else
-    {
-        glBindBuffer(GL_ARRAY_BUFFER, 0);      // Unbind VBOs
-        if (mesh.indices != NULL) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
-    }
-
-    glUseProgram(0);        // Unbind shader program
-#endif
-}
-
-// Unload mesh data from CPU and GPU
-void rlglUnloadMesh(Mesh *mesh)
-{
-    if (mesh->vertices != NULL) free(mesh->vertices);
-    if (mesh->texcoords != NULL) free(mesh->texcoords);
-    if (mesh->normals != NULL) free(mesh->normals);
-    if (mesh->colors != NULL) free(mesh->colors);
-    if (mesh->tangents != NULL) free(mesh->tangents);
-    if (mesh->texcoords2 != NULL) free(mesh->texcoords2);
-    if (mesh->indices != NULL) free(mesh->indices);
-
-    rlDeleteBuffers(mesh->vboId[0]);   // vertex
-    rlDeleteBuffers(mesh->vboId[1]);   // texcoords
-    rlDeleteBuffers(mesh->vboId[2]);   // normals
-    rlDeleteBuffers(mesh->vboId[3]);   // colors
-    rlDeleteBuffers(mesh->vboId[4]);   // tangents
-    rlDeleteBuffers(mesh->vboId[5]);   // texcoords2
-    rlDeleteBuffers(mesh->vboId[6]);   // indices
-
-    rlDeleteVertexArrays(mesh->vaoId);
-}
-
-// Read screen pixel data (color buffer)
-unsigned char *rlglReadScreenPixels(int width, int height)
-{
-    unsigned char *screenData = (unsigned char *)malloc(width*height*sizeof(unsigned char)*4);
-
-    // NOTE: glReadPixels returns image flipped vertically -> (0,0) is the bottom left corner of the framebuffer
-    glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, screenData);
-
-    // Flip image vertically!
-    unsigned char *imgData = (unsigned char *)malloc(width*height*sizeof(unsigned char)*4);
-
-    for (int y = height - 1; y >= 0; y--)
-    {
-        for (int x = 0; x < (width*4); x++)
-        {
-            // Flip line
-            imgData[((height - 1) - y)*width*4 + x] = screenData[(y*width*4) + x];
-            
-            // Set alpha component value to 255 (no trasparent image retrieval)
-            // NOTE: Alpha value has already been applied to RGB in framebuffer, we don't need it!
-            if (((x + 1)%4) == 0) imgData[((height - 1) - y)*width*4 + x] = 255;
-        }
-    }
-
-    free(screenData);
-
-    return imgData;     // NOTE: image data should be freed
-}
-
-// Read texture pixel data
-// NOTE: glGetTexImage() is not available on OpenGL ES 2.0
-// Texture2D width and height are required on OpenGL ES 2.0. There is no way to get it from texture id.
-void *rlglReadTexturePixels(Texture2D texture)
-{
-    void *pixels = NULL;
-    
-#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33)
-    glBindTexture(GL_TEXTURE_2D, texture.id);
-    
-    // NOTE: Using texture.id, we can retrieve some texture info (but not on OpenGL ES 2.0)
-    /*
-    int width, height, format;
-    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
-    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
-    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &format);
-    // Other texture info: GL_TEXTURE_RED_SIZE, GL_TEXTURE_GREEN_SIZE, GL_TEXTURE_BLUE_SIZE, GL_TEXTURE_ALPHA_SIZE
-    */
-    
-    int glFormat = 0, glType = 0;
-
-    unsigned int size = texture.width*texture.height;
-    
-    // NOTE: GL_LUMINANCE and GL_LUMINANCE_ALPHA are removed since OpenGL 3.1
-    // Must be replaced by GL_RED and GL_RG on Core OpenGL 3.3
-
-    switch (texture.format)
-    {
-#if defined(GRAPHICS_API_OPENGL_11)
-        case UNCOMPRESSED_GRAYSCALE: pixels = (unsigned char *)malloc(size); glFormat = GL_LUMINANCE; glType = GL_UNSIGNED_BYTE; break;            // 8 bit per pixel (no alpha)
-        case UNCOMPRESSED_GRAY_ALPHA: pixels = (unsigned char *)malloc(size*2); glFormat = GL_LUMINANCE_ALPHA; glType = GL_UNSIGNED_BYTE; break;   // 16 bpp (2 channels)
-#elif defined(GRAPHICS_API_OPENGL_33) 
-        case UNCOMPRESSED_GRAYSCALE: pixels = (unsigned char *)malloc(size); glFormat = GL_RED; glType = GL_UNSIGNED_BYTE; break;       
-        case UNCOMPRESSED_GRAY_ALPHA: pixels = (unsigned char *)malloc(size*2); glFormat = GL_RG; glType = GL_UNSIGNED_BYTE; break;
-#endif
-        case UNCOMPRESSED_R5G6B5: pixels = (unsigned short *)malloc(size); glFormat = GL_RGB; glType = GL_UNSIGNED_SHORT_5_6_5; break;             // 16 bpp
-        case UNCOMPRESSED_R8G8B8: pixels = (unsigned char *)malloc(size*3); glFormat = GL_RGB; glType = GL_UNSIGNED_BYTE; break;                   // 24 bpp
-        case UNCOMPRESSED_R5G5B5A1: pixels = (unsigned short *)malloc(size); glFormat = GL_RGBA; glType = GL_UNSIGNED_SHORT_5_5_5_1; break;        // 16 bpp (1 bit alpha)
-        case UNCOMPRESSED_R4G4B4A4: pixels = (unsigned short *)malloc(size); glFormat = GL_RGBA; glType = GL_UNSIGNED_SHORT_4_4_4_4; break;        // 16 bpp (4 bit alpha)
-        case UNCOMPRESSED_R8G8B8A8: pixels = (unsigned char *)malloc(size*4); glFormat = GL_RGBA; glType = GL_UNSIGNED_BYTE; break;                // 32 bpp
-        default: TraceLog(WARNING, "Texture data retrieval, format not suported"); break;
-    }
-    
-    // NOTE: Each row written to or read from by OpenGL pixel operations like glGetTexImage are aligned to a 4 byte boundary by default, which may add some padding.
-    // Use glPixelStorei to modify padding with the GL_[UN]PACK_ALIGNMENT setting. 
-    // GL_PACK_ALIGNMENT affects operations that read from OpenGL memory (glReadPixels, glGetTexImage, etc.) 
-    // GL_UNPACK_ALIGNMENT affects operations that write to OpenGL memory (glTexImage, etc.)
-    glPixelStorei(GL_PACK_ALIGNMENT, 1);
-
-    glGetTexImage(GL_TEXTURE_2D, 0, glFormat, glType, pixels);
-    
-    glBindTexture(GL_TEXTURE_2D, 0);
-#endif
-
-#if defined(GRAPHICS_API_OPENGL_ES2)
-
-    RenderTexture2D fbo = rlglLoadRenderTexture(texture.width, texture.height);
-
-    // NOTE: Two possible Options:
-    // 1 - Bind texture to color fbo attachment and glReadPixels()
-    // 2 - Create an fbo, activate it, render quad with texture, glReadPixels()
-    
-#define GET_TEXTURE_FBO_OPTION_1    // It works
-
-#if defined(GET_TEXTURE_FBO_OPTION_1)
-    glBindFramebuffer(GL_FRAMEBUFFER, fbo.id);
-    glBindTexture(GL_TEXTURE_2D, 0);
-
-    // Attach our texture to FBO -> Texture must be RGB
-    // NOTE: Previoust attached texture is automatically detached
-    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.id, 0);
-    
-    pixels = (unsigned char *)malloc(texture.width*texture.height*4*sizeof(unsigned char));
-    
-    // NOTE: Despite FBO color texture is RGB, we read data as RGBA... reading as RGB doesn't work... o__O
-    glReadPixels(0, 0, texture.width, texture.height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
-    
-    // Re-attach internal FBO color texture before deleting it
-    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo.texture.id, 0);
-    
-    glBindFramebuffer(GL_FRAMEBUFFER, 0);
-    
-#elif defined(GET_TEXTURE_FBO_OPTION_2)
-    // Render texture to fbo
-    glBindFramebuffer(GL_FRAMEBUFFER, fbo.id);
-    
-    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-    glClearDepthf(1.0f);
-    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-    glViewport(0, 0, width, height);
-    //glMatrixMode(GL_PROJECTION);
-    //glLoadIdentity();
-    rlOrtho(0.0, width, height, 0.0, 0.0, 1.0); 
-    //glMatrixMode(GL_MODELVIEW);
-    //glLoadIdentity();
-    //glDisable(GL_TEXTURE_2D);
-    //glDisable(GL_BLEND);
-    glEnable(GL_DEPTH_TEST);
-    
-    Model quad;
-    //quad.mesh = GenMeshQuad(width, height);
-    quad.transform = MatrixIdentity();
-    quad.shader = defaultShader;
-    
-    DrawModel(quad, (Vector3){ 0.0f, 0.0f, 0.0f }, 1.0f, WHITE);
-    
-    pixels = (unsigned char *)malloc(texture.width*texture.height*3*sizeof(unsigned char));
-    
-    glReadPixels(0, 0, texture.width, texture.height, GL_RGB, GL_UNSIGNED_BYTE, pixels);
-
-    // Bind framebuffer 0, which means render to back buffer
-    glBindFramebuffer(GL_FRAMEBUFFER, 0);
-    
-    UnloadModel(quad);
-#endif // GET_TEXTURE_FBO_OPTION
-
-    // Clean up temporal fbo
-    rlDeleteRenderTextures(fbo);
-
-#endif
-
-    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
-// NOTE: Those functions are exposed directly to the user in raylib.h
-//----------------------------------------------------------------------------------
-
-// Get default internal texture (white texture)
-Texture2D GetDefaultTexture(void)
-{
-    Texture2D texture;
-    
-    texture.id = whiteTexture;
-    texture.width = 1;
-    texture.height = 1;
-    texture.mipmaps = 1;
-    texture.format = UNCOMPRESSED_R8G8B8A8;
-    
-    return texture;
-}
-
-// Load a custom shader and bind default locations
-Shader LoadShader(char *vsFileName, char *fsFileName)
-{
-    Shader shader = { 0 };
-
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    // Shaders loading from external text file
-    char *vShaderStr = ReadTextFile(vsFileName);
-    char *fShaderStr = ReadTextFile(fsFileName);
-    
-    if ((vShaderStr != NULL) && (fShaderStr != NULL))
-    {
-        shader.id = LoadShaderProgram(vShaderStr, fShaderStr);
-
-        // After shader loading, we try to load default location names
-        if (shader.id != 0) LoadDefaultShaderLocations(&shader);
-        
-        // Shader strings must be freed
-        free(vShaderStr);
-        free(fShaderStr);
-    }
-    
-    if (shader.id == 0)
-    {
-        TraceLog(WARNING, "Custom shader could not be loaded");
-        shader = defaultShader;
-    }        
-#endif
-
-    return shader;
-}
-
-// Unload a custom shader from memory
-void UnloadShader(Shader shader)
-{
-    if (shader.id != 0)
-    {
-        rlDeleteShader(shader.id);
-        TraceLog(INFO, "[SHDR ID %i] Unloaded shader program data", shader.id);
-    }
-}
-
-// Begin custom shader mode
-void BeginShaderMode(Shader shader)
-{
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    if (currentShader.id != shader.id)
-    {
-        rlglDraw();
-        currentShader = shader;
-    }
-#endif
-}
-
-// End custom shader mode (returns to default shader)
-void EndShaderMode(void)
-{
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    BeginShaderMode(defaultShader);
-#endif
-}
-
-// Get default shader
-Shader GetDefaultShader(void)
-{
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    return defaultShader;
-#else
-    Shader shader = { 0 };
-    return shader;
-#endif
-}
-
-// Get default shader
-// NOTE: Inits global variable standardShader
-Shader GetStandardShader(void)
-{
-    Shader shader = { 0 };
-    
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    if (standardShaderLoaded) shader = standardShader;
-    else
-    {
-        // Lazy initialization of standard shader
-        standardShader = LoadStandardShader();
-        shader = standardShader;
-    }
-#endif
-
-    return shader;
-}
-
-// Get shader uniform location
-int GetShaderLocation(Shader shader, const char *uniformName)
-{
-    int location = -1;
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)   
-    location = glGetUniformLocation(shader.id, uniformName);
-    
-    if (location == -1) TraceLog(WARNING, "[SHDR ID %i] Shader location for %s could not be found", shader.id, uniformName);
-#endif
-    return location;
-}
-
-// Set shader uniform value (float)
-void SetShaderValue(Shader shader, int uniformLoc, float *value, int size)
-{
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    glUseProgram(shader.id);
-
-    if (size == 1) glUniform1fv(uniformLoc, 1, value);          // Shader uniform type: float
-    else if (size == 2) glUniform2fv(uniformLoc, 1, value);     // Shader uniform type: vec2
-    else if (size == 3) glUniform3fv(uniformLoc, 1, value);     // Shader uniform type: vec3
-    else if (size == 4) glUniform4fv(uniformLoc, 1, value);     // Shader uniform type: vec4
-    else TraceLog(WARNING, "Shader value float array size not supported");
-    
-    glUseProgram(0);
-#endif
-}
-
-// Set shader uniform value (int)
-void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size)
-{
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    glUseProgram(shader.id);
-
-    if (size == 1) glUniform1iv(uniformLoc, 1, value);          // Shader uniform type: int
-    else if (size == 2) glUniform2iv(uniformLoc, 1, value);     // Shader uniform type: ivec2
-    else if (size == 3) glUniform3iv(uniformLoc, 1, value);     // Shader uniform type: ivec3
-    else if (size == 4) glUniform4iv(uniformLoc, 1, value);     // Shader uniform type: ivec4
-    else TraceLog(WARNING, "Shader value int array size not supported");
-    
-    glUseProgram(0);
-#endif
-}
-
-// Set shader uniform value (matrix 4x4)
-void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat)
-{
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    glUseProgram(shader.id);
-
-    glUniformMatrix4fv(uniformLoc, 1, false, MatrixToFloat(mat));
-    
-    glUseProgram(0);
-#endif
-}
-
-// Set a custom projection matrix (replaces internal projection matrix)
-void SetMatrixProjection(Matrix proj)
-{
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    projection = proj;
-#endif
-}
-
-// Set a custom modelview matrix (replaces internal modelview matrix)
-void SetMatrixModelview(Matrix view)
-{
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    modelview = view;
-#endif
-}
-
-// Begin blending mode (alpha, additive, multiplied)
-// NOTE: Only 3 blending modes supported, default blend mode is alpha
-void BeginBlendMode(int mode)
-{
-    if ((blendMode != mode) && (mode < 3))
-    {
-        rlglDraw();
-        
-        switch (mode)
-        {
-            case BLEND_ALPHA: glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); break;
-            case BLEND_ADDITIVE: glBlendFunc(GL_SRC_ALPHA, GL_ONE); break; // Alternative: glBlendFunc(GL_ONE, GL_ONE);
-            case BLEND_MULTIPLIED: glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); break;
-            default: break;
-        }
-        
-        blendMode = mode;
-    }
-}
-
-// End blending mode (reset to default: alpha blending)
-void EndBlendMode(void)
-{
-    BeginBlendMode(BLEND_ALPHA);
-}
-
-// Create a new light, initialize it and add to pool
-Light CreateLight(int type, Vector3 position, Color diffuse)
-{
-    Light light = NULL;
-    
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    // Allocate dynamic memory
-    light = (Light)malloc(sizeof(LightData));
-    
-    // Initialize light values with generic values
-    light->id = lightsCount;
-    light->type = type;
-    light->enabled = true;
-    
-    light->position = position;
-    light->target = (Vector3){ 0.0f, 0.0f, 0.0f };
-    light->intensity = 1.0f;
-    light->diffuse = diffuse;
-    
-    // Add new light to the array
-    lights[lightsCount] = light;
-    
-    // Increase enabled lights count
-    lightsCount++;
-#else
-    // TODO: Support OpenGL 1.1 lighting system
-    TraceLog(WARNING, "Lighting currently not supported on OpenGL 1.1");
-#endif
-
-    return light;
-}
-
-// Destroy a light and take it out of the list
-void DestroyLight(Light light)
-{
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    // Free dynamic memory allocation
-    free(lights[light->id]);
-    
-    // Remove *obj from the pointers array
-    for (int i = light->id; i < lightsCount; i++)
-    {
-        // Resort all the following pointers of the array
-        if ((i + 1) < lightsCount)
-        {
-            lights[i] = lights[i + 1];
-            lights[i]->id = lights[i + 1]->id;
-        }
-        else free(lights[i]);
-    }
-    
-    // Decrease enabled physic objects count
-    lightsCount--;
-#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, &currentIndex);
-    ovr_GetTextureSwapChainBufferGL(session, buffer.textureChain, currentIndex, &currentTexId);
-
-    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
-//----------------------------------------------------------------------------------
-
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-// Convert image data to OpenGL texture (returns OpenGL valid Id)
-// NOTE: Expected compressed image data and POT image
-static void LoadCompressedTexture(unsigned char *data, int width, int height, int mipmapCount, int compressedFormat)
-{
-    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-
-    int blockSize = 0;      // Bytes every block
-    int offset = 0;
-
-    if ((compressedFormat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT) ||
-        (compressedFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) ||
-#if defined(GRAPHICS_API_OPENGL_ES2)
-        (compressedFormat == GL_ETC1_RGB8_OES) ||
-#endif
-        (compressedFormat == GL_COMPRESSED_RGB8_ETC2)) blockSize = 8;
-    else blockSize = 16;
-
-    // Load the mipmap levels
-    for (int level = 0; level < mipmapCount && (width || height); level++)
-    {
-        unsigned int size = 0;
-        
-        size = ((width + 3)/4)*((height + 3)/4)*blockSize;
-
-        glCompressedTexImage2D(GL_TEXTURE_2D, level, compressedFormat, width, height, 0, size, data + offset);
-
-        offset += size;
-        width  /= 2;
-        height /= 2;
-
-        // Security check for NPOT textures
-        if (width < 1) width = 1;
-        if (height < 1) height = 1;
-    }
-}
-
-// Load custom shader strings and return program id
-static unsigned int LoadShaderProgram(const char *vShaderStr, const char *fShaderStr)
-{
-    unsigned int program = 0;
-
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    GLuint vertexShader;
-    GLuint fragmentShader;
-
-    vertexShader = glCreateShader(GL_VERTEX_SHADER);
-    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
-
-    const char *pvs = vShaderStr;
-    const char *pfs = fShaderStr;
-
-    glShaderSource(vertexShader, 1, &pvs, NULL);
-    glShaderSource(fragmentShader, 1, &pfs, NULL);
-
-    GLint success = 0;
-
-    glCompileShader(vertexShader);
-
-    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
-
-    if (success != GL_TRUE)
-    {
-        TraceLog(WARNING, "[VSHDR ID %i] Failed to compile vertex shader...", vertexShader);
-
-        int maxLength = 0;
-        int length;
-
-        glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &maxLength);
-
-        char log[maxLength];
-
-        glGetShaderInfoLog(vertexShader, maxLength, &length, log);
-
-        TraceLog(INFO, "%s", log);
-    }
-    else TraceLog(INFO, "[VSHDR ID %i] Vertex shader compiled successfully", vertexShader);
-
-    glCompileShader(fragmentShader);
-
-    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
-
-    if (success != GL_TRUE)
-    {
-        TraceLog(WARNING, "[FSHDR ID %i] Failed to compile fragment shader...", fragmentShader);
-
-        int maxLength = 0;
-        int length;
-
-        glGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &maxLength);
-
-        char log[maxLength];
-
-        glGetShaderInfoLog(fragmentShader, maxLength, &length, log);
-
-        TraceLog(INFO, "%s", log);
-    }
-    else TraceLog(INFO, "[FSHDR ID %i] Fragment shader compiled successfully", fragmentShader);
-
-    program = glCreateProgram();
-
-    glAttachShader(program, vertexShader);
-    glAttachShader(program, fragmentShader);
-    
-    // NOTE: Default attribute shader locations must be binded before linking
-    glBindAttribLocation(program, 0, DEFAULT_ATTRIB_POSITION_NAME);
-    glBindAttribLocation(program, 1, DEFAULT_ATTRIB_TEXCOORD_NAME);
-    glBindAttribLocation(program, 2, DEFAULT_ATTRIB_NORMAL_NAME);
-    glBindAttribLocation(program, 3, DEFAULT_ATTRIB_COLOR_NAME);
-    glBindAttribLocation(program, 4, DEFAULT_ATTRIB_TANGENT_NAME);
-    glBindAttribLocation(program, 5, DEFAULT_ATTRIB_TEXCOORD2_NAME);
-    
-    // NOTE: If some attrib name is no found on the shader, it locations becomes -1
-    
-    glLinkProgram(program);
-    
-    // NOTE: All uniform variables are intitialised to 0 when a program links
-
-    glGetProgramiv(program, GL_LINK_STATUS, &success);
-
-    if (success == GL_FALSE)
-    {
-        TraceLog(WARNING, "[SHDR ID %i] Failed to link shader program...", program);
-
-        int maxLength = 0;
-        int length;
-
-        glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
-
-        char log[maxLength];
-
-        glGetProgramInfoLog(program, maxLength, &length, log);
-
-        TraceLog(INFO, "%s", log);
-
-        glDeleteProgram(program);
-
-        program = 0;
-    }
-    else TraceLog(INFO, "[SHDR ID %i] Shader program loaded successfully", program);
-
-    glDeleteShader(vertexShader);
-    glDeleteShader(fragmentShader);
-#endif
-    return program;
-}
-
-
-// Load default shader (just vertex positioning and texture coloring)
-// NOTE: This shader program is used for batch buffers (lines, triangles, quads)
-static Shader LoadDefaultShader(void)
-{
-    Shader shader;
-
-    // Vertex shader directly defined, no external file required
-#if defined(GRAPHICS_API_OPENGL_33)
-    char vShaderStr[] = "#version 330       \n"
-        "in vec3 vertexPosition;            \n"
-        "in vec2 vertexTexCoord;            \n"
-        "in vec4 vertexColor;               \n"
-        "out vec2 fragTexCoord;             \n"
-        "out vec4 fragColor;                \n"
-#elif defined(GRAPHICS_API_OPENGL_ES2)
-    char vShaderStr[] = "#version 100       \n"
-        "attribute vec3 vertexPosition;     \n"
-        "attribute vec2 vertexTexCoord;     \n"
-        "attribute vec4 vertexColor;        \n"
-        "varying vec2 fragTexCoord;         \n"
-        "varying vec4 fragColor;            \n"
-#endif
-        "uniform mat4 mvpMatrix;            \n"
-        "void main()                        \n"
-        "{                                  \n"
-        "    fragTexCoord = vertexTexCoord; \n"
-        "    fragColor = vertexColor;       \n"
-        "    gl_Position = mvpMatrix*vec4(vertexPosition, 1.0); \n"
-        "}                                  \n";
-
-    // Fragment shader directly defined, no external file required
-#if defined(GRAPHICS_API_OPENGL_33)
-    char fShaderStr[] = "#version 330       \n"
-        "in vec2 fragTexCoord;              \n"
-        "in vec4 fragColor;                 \n"
-        "out vec4 finalColor;               \n"
-#elif defined(GRAPHICS_API_OPENGL_ES2)
-    char fShaderStr[] = "#version 100       \n"
-        "precision mediump float;           \n"     // precision required for OpenGL ES2 (WebGL)
-        "varying vec2 fragTexCoord;         \n"
-        "varying vec4 fragColor;            \n"
-#endif
-        "uniform sampler2D texture0;        \n"
-        "uniform vec4 colDiffuse;           \n"
-        "void main()                        \n"
-        "{                                  \n"
-#if defined(GRAPHICS_API_OPENGL_33)
-        "    vec4 texelColor = texture(texture0, fragTexCoord);   \n"
-        "    finalColor = texelColor*colDiffuse*fragColor;        \n"
-#elif defined(GRAPHICS_API_OPENGL_ES2)
-        "    vec4 texelColor = texture2D(texture0, fragTexCoord); \n" // NOTE: texture2D() is deprecated on OpenGL 3.3 and ES 3.0
-        "    gl_FragColor = texelColor*colDiffuse*fragColor;      \n"
-#endif
-        "}                                  \n";
-
-    shader.id = LoadShaderProgram(vShaderStr, fShaderStr);
-
-    if (shader.id != 0) TraceLog(INFO, "[SHDR ID %i] Default shader loaded successfully", shader.id);
-    else TraceLog(WARNING, "[SHDR ID %i] Default shader could not be loaded", shader.id);
-
-    if (shader.id != 0) LoadDefaultShaderLocations(&shader);
-
-    return shader;
-}
-
-// Load standard shader
-// NOTE: This shader supports: 
-//     - Up to 3 different maps: diffuse, normal, specular
-//     - Material properties: colAmbient, colDiffuse, colSpecular, glossiness
-//     - Up to 8 lights: Point, Directional or Spot
-static Shader LoadStandardShader(void)
-{
-    Shader shader;
-    
-    // Load standard shader (embeded in standard_shader.h)
-    shader.id = LoadShaderProgram(vStandardShaderStr, fStandardShaderStr);
-
-    if (shader.id != 0)
-    {
-        LoadDefaultShaderLocations(&shader);
-        TraceLog(INFO, "[SHDR ID %i] Standard shader loaded successfully", shader.id);
-        
-        standardShaderLoaded = true;
-    }
-    else
-    {
-        TraceLog(WARNING, "[SHDR ID %i] Standard shader could not be loaded, using default shader", shader.id);
-        shader = GetDefaultShader();
-    }
-
-    return shader;
-}
-
-// Get location handlers to for shader attributes and uniforms
-// NOTE: If any location is not found, loc point becomes -1
-static void LoadDefaultShaderLocations(Shader *shader)
-{
-    // NOTE: Default shader attrib locations have been fixed before linking:
-    //          vertex position location = 0
-    //          vertex texcoord location = 1
-    //          vertex normal location = 2
-    //          vertex color location = 3
-    //          vertex tangent location = 4
-    //          vertex texcoord2 location = 5
-    
-    // Get handles to GLSL input attibute locations
-    shader->vertexLoc = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_POSITION_NAME);
-    shader->texcoordLoc = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_TEXCOORD_NAME);
-    shader->texcoord2Loc = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_TEXCOORD2_NAME);
-    shader->normalLoc = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_NORMAL_NAME);
-    shader->tangentLoc = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_TANGENT_NAME);
-    shader->colorLoc = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_COLOR_NAME);
-
-    // Get handles to GLSL uniform locations (vertex shader)
-    shader->mvpLoc  = glGetUniformLocation(shader->id, "mvpMatrix");
-
-    // Get handles to GLSL uniform locations (fragment shader)
-    shader->tintColorLoc = glGetUniformLocation(shader->id, "colDiffuse");
-    shader->mapTexture0Loc = glGetUniformLocation(shader->id, "texture0");
-    shader->mapTexture1Loc = glGetUniformLocation(shader->id, "texture1");
-    shader->mapTexture2Loc = glGetUniformLocation(shader->id, "texture2");
-}
-
-// Unload default shader 
-static void UnloadDefaultShader(void)
-{
-    glUseProgram(0);
-
-    //glDetachShader(defaultShader, vertexShader);
-    //glDetachShader(defaultShader, fragmentShader);
-    //glDeleteShader(vertexShader);     // Already deleted on shader compilation
-    //glDeleteShader(fragmentShader);   // Already deleted on shader compilation
-    glDeleteProgram(defaultShader.id);
-}
-
-// Unload standard shader 
-static void UnloadStandardShader(void)
-{
-    glUseProgram(0);
-
-    //glDetachShader(defaultShader, vertexShader);
-    //glDetachShader(defaultShader, fragmentShader);
-    //glDeleteShader(vertexShader);     // Already deleted on shader compilation
-    //glDeleteShader(fragmentShader);   // Already deleted on shader compilation
-    glDeleteProgram(standardShader.id);
-}
-
-
-// Load default internal buffers (lines, triangles, quads)
-static void LoadDefaultBuffers(void)
-{
-    // [CPU] Allocate and initialize float array buffers to store vertex data (lines, triangles, quads)
-    //--------------------------------------------------------------------------------------------
-    
-    // Lines - Initialize arrays (vertex position and color data)
-    lines.vertices = (float *)malloc(sizeof(float)*3*2*MAX_LINES_BATCH);        // 3 float by vertex, 2 vertex by line
-    lines.colors = (unsigned char *)malloc(sizeof(unsigned char)*4*2*MAX_LINES_BATCH);  // 4 float by color, 2 colors by line
-    lines.texcoords = NULL;
-    lines.indices = NULL;
-
-    for (int i = 0; i < (3*2*MAX_LINES_BATCH); i++) lines.vertices[i] = 0.0f;
-    for (int i = 0; i < (4*2*MAX_LINES_BATCH); i++) lines.colors[i] = 0;
-
-    lines.vCounter = 0;
-    lines.cCounter = 0;
-    lines.tcCounter = 0;
-
-    // Triangles - Initialize arrays (vertex position and color data)
-    triangles.vertices = (float *)malloc(sizeof(float)*3*3*MAX_TRIANGLES_BATCH);        // 3 float by vertex, 3 vertex by triangle
-    triangles.colors = (unsigned char *)malloc(sizeof(unsigned char)*4*3*MAX_TRIANGLES_BATCH);  // 4 float by color, 3 colors by triangle
-    triangles.texcoords = NULL;
-    triangles.indices = NULL;
-
-    for (int i = 0; i < (3*3*MAX_TRIANGLES_BATCH); i++) triangles.vertices[i] = 0.0f;
-    for (int i = 0; i < (4*3*MAX_TRIANGLES_BATCH); i++) triangles.colors[i] = 0;
-
-    triangles.vCounter = 0;
-    triangles.cCounter = 0;
-    triangles.tcCounter = 0;
-
-    // Quads - Initialize arrays (vertex position, texcoord, color data and indexes)
-    quads.vertices = (float *)malloc(sizeof(float)*3*4*MAX_QUADS_BATCH);        // 3 float by vertex, 4 vertex by quad
-    quads.texcoords = (float *)malloc(sizeof(float)*2*4*MAX_QUADS_BATCH);       // 2 float by texcoord, 4 texcoord by quad
-    quads.colors = (unsigned char *)malloc(sizeof(unsigned char)*4*4*MAX_QUADS_BATCH);  // 4 float by color, 4 colors by quad
-#if defined(GRAPHICS_API_OPENGL_33)
-    quads.indices = (unsigned int *)malloc(sizeof(int)*6*MAX_QUADS_BATCH);      // 6 int by quad (indices)
-#elif defined(GRAPHICS_API_OPENGL_ES2)
-    quads.indices = (unsigned short *)malloc(sizeof(short)*6*MAX_QUADS_BATCH);  // 6 int by quad (indices)
-#endif
-
-    for (int i = 0; i < (3*4*MAX_QUADS_BATCH); i++) quads.vertices[i] = 0.0f;
-    for (int i = 0; i < (2*4*MAX_QUADS_BATCH); i++) quads.texcoords[i] = 0.0f;
-    for (int i = 0; i < (4*4*MAX_QUADS_BATCH); i++) quads.colors[i] = 0;
-
-    int k = 0;
-
-    // Indices can be initialized right now
-    for (int i = 0; i < (6*MAX_QUADS_BATCH); i+=6)
-    {
-        quads.indices[i] = 4*k;
-        quads.indices[i+1] = 4*k+1;
-        quads.indices[i+2] = 4*k+2;
-        quads.indices[i+3] = 4*k;
-        quads.indices[i+4] = 4*k+2;
-        quads.indices[i+5] = 4*k+3;
-
-        k++;
-    }
-
-    quads.vCounter = 0;
-    quads.tcCounter = 0;
-    quads.cCounter = 0;
-
-    TraceLog(INFO, "[CPU] Default buffers initialized successfully (lines, triangles, quads)");
-    //--------------------------------------------------------------------------------------------
-    
-    // [GPU] Upload vertex data and initialize VAOs/VBOs (lines, triangles, quads)
-    // NOTE: Default buffers are linked to use currentShader (defaultShader)
-    //--------------------------------------------------------------------------------------------
-    
-    // Upload and link lines vertex buffers
-    if (vaoSupported)
-    {
-        // Initialize Lines VAO
-        glGenVertexArrays(1, &lines.vaoId);
-        glBindVertexArray(lines.vaoId);
-    }
-
-    // Lines - Vertex buffers binding and attributes enable 
-    // Vertex position buffer (shader-location = 0)
-    glGenBuffers(2, &lines.vboId[0]);
-    glBindBuffer(GL_ARRAY_BUFFER, lines.vboId[0]);
-    glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*2*MAX_LINES_BATCH, lines.vertices, GL_DYNAMIC_DRAW);
-    glEnableVertexAttribArray(currentShader.vertexLoc);
-    glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
-
-    // Vertex color buffer (shader-location = 3)
-    glGenBuffers(2, &lines.vboId[1]);
-    glBindBuffer(GL_ARRAY_BUFFER, lines.vboId[1]);
-    glBufferData(GL_ARRAY_BUFFER, sizeof(unsigned char)*4*2*MAX_LINES_BATCH, lines.colors, GL_DYNAMIC_DRAW);
-    glEnableVertexAttribArray(currentShader.colorLoc);
-    glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
-
-    if (vaoSupported) TraceLog(INFO, "[VAO ID %i] Default buffers VAO initialized successfully (lines)", lines.vaoId);
-    else TraceLog(INFO, "[VBO ID %i][VBO ID %i] Default buffers VBOs initialized successfully (lines)", lines.vboId[0], lines.vboId[1]);
-
-    // Upload and link triangles vertex buffers
-    if (vaoSupported)
-    {
-        // Initialize Triangles VAO
-        glGenVertexArrays(1, &triangles.vaoId);
-        glBindVertexArray(triangles.vaoId);
-    }
-
-    // Triangles - Vertex buffers binding and attributes enable 
-    // Vertex position buffer (shader-location = 0)
-    glGenBuffers(1, &triangles.vboId[0]);
-    glBindBuffer(GL_ARRAY_BUFFER, triangles.vboId[0]);
-    glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*3*MAX_TRIANGLES_BATCH, triangles.vertices, GL_DYNAMIC_DRAW);
-    glEnableVertexAttribArray(currentShader.vertexLoc);
-    glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
-
-    // Vertex color buffer (shader-location = 3)
-    glGenBuffers(1, &triangles.vboId[1]);
-    glBindBuffer(GL_ARRAY_BUFFER, triangles.vboId[1]);
-    glBufferData(GL_ARRAY_BUFFER, sizeof(unsigned char)*4*3*MAX_TRIANGLES_BATCH, triangles.colors, GL_DYNAMIC_DRAW);
-    glEnableVertexAttribArray(currentShader.colorLoc);
-    glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
-
-    if (vaoSupported) TraceLog(INFO, "[VAO ID %i] Default buffers VAO initialized successfully (triangles)", triangles.vaoId);
-    else TraceLog(INFO, "[VBO ID %i][VBO ID %i] Default buffers VBOs initialized successfully(triangles)", triangles.vboId[0], triangles.vboId[1]);
-
-    // Upload and link quads vertex buffers
-    if (vaoSupported)
-    {
-        // Initialize Quads VAO
-        glGenVertexArrays(1, &quads.vaoId);
-        glBindVertexArray(quads.vaoId);
-    }
-
-    // Quads - Vertex buffers binding and attributes enable 
-    // Vertex position buffer (shader-location = 0)
-    glGenBuffers(1, &quads.vboId[0]);
-    glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[0]);
-    glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*MAX_QUADS_BATCH, quads.vertices, GL_DYNAMIC_DRAW);
-    glEnableVertexAttribArray(currentShader.vertexLoc);
-    glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
-
-    // Vertex texcoord buffer (shader-location = 1)
-    glGenBuffers(1, &quads.vboId[1]);
-    glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[1]);
-    glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*4*MAX_QUADS_BATCH, quads.texcoords, GL_DYNAMIC_DRAW);
-    glEnableVertexAttribArray(currentShader.texcoordLoc);
-    glVertexAttribPointer(currentShader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0);
-
-    // Vertex color buffer (shader-location = 3)
-    glGenBuffers(1, &quads.vboId[2]);
-    glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[2]);
-    glBufferData(GL_ARRAY_BUFFER, sizeof(unsigned char)*4*4*MAX_QUADS_BATCH, quads.colors, GL_DYNAMIC_DRAW);
-    glEnableVertexAttribArray(currentShader.colorLoc);
-    glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
-
-    // Fill index buffer
-    glGenBuffers(1, &quads.vboId[3]);
-    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quads.vboId[3]);
-#if defined(GRAPHICS_API_OPENGL_33)
-    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int)*6*MAX_QUADS_BATCH, quads.indices, GL_STATIC_DRAW);
-#elif defined(GRAPHICS_API_OPENGL_ES2)
-    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(short)*6*MAX_QUADS_BATCH, quads.indices, GL_STATIC_DRAW);
-#endif
-
-    if (vaoSupported) TraceLog(INFO, "[VAO ID %i] Default buffers VAO initialized successfully (quads)", quads.vaoId);
-    else TraceLog(INFO, "[VBO ID %i][VBO ID %i][VBO ID %i][VBO ID %i] Default buffers VBOs initialized successfully (quads)", quads.vboId[0], quads.vboId[1], quads.vboId[2], quads.vboId[3]);
-
-    // Unbind the current VAO
-    if (vaoSupported) glBindVertexArray(0);
-    //--------------------------------------------------------------------------------------------
-}
-
-// Update default internal buffers (VAOs/VBOs) with vertex array data
-// NOTE: If there is not vertex data, buffers doesn't need to be updated (vertexCount > 0)
-// TODO: If no data changed on the CPU arrays --> No need to re-update GPU arrays (change flag required)
-static void UpdateDefaultBuffers(void)
-{
-    // Update lines vertex buffers
-    if (lines.vCounter > 0)
-    {
-        // Activate Lines VAO
-        if (vaoSupported) glBindVertexArray(lines.vaoId);
-
-        // Lines - vertex positions buffer
-        glBindBuffer(GL_ARRAY_BUFFER, lines.vboId[0]);
-        //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*2*MAX_LINES_BATCH, lines.vertices, GL_DYNAMIC_DRAW);
-        glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*3*lines.vCounter, lines.vertices);    // target - offset (in bytes) - size (in bytes) - data pointer
-
-        // Lines - colors buffer
-        glBindBuffer(GL_ARRAY_BUFFER, lines.vboId[1]);
-        //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*2*MAX_LINES_BATCH, lines.colors, GL_DYNAMIC_DRAW);
-        glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(unsigned char)*4*lines.cCounter, lines.colors);
-    }
-
-    // Update triangles vertex buffers
-    if (triangles.vCounter > 0)
-    {
-        // Activate Triangles VAO
-        if (vaoSupported) glBindVertexArray(triangles.vaoId);
-
-        // Triangles - vertex positions buffer
-        glBindBuffer(GL_ARRAY_BUFFER, triangles.vboId[0]);
-        //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*3*MAX_TRIANGLES_BATCH, triangles.vertices, GL_DYNAMIC_DRAW);
-        glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*3*triangles.vCounter, triangles.vertices);
-
-        // Triangles - colors buffer
-        glBindBuffer(GL_ARRAY_BUFFER, triangles.vboId[1]);
-        //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*3*MAX_TRIANGLES_BATCH, triangles.colors, GL_DYNAMIC_DRAW);
-        glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(unsigned char)*4*triangles.cCounter, triangles.colors);
-    }
-
-    // Update quads vertex buffers
-    if (quads.vCounter > 0)
-    {
-        // Activate Quads VAO
-        if (vaoSupported) glBindVertexArray(quads.vaoId);
-
-        // Quads - vertex positions buffer
-        glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[0]);
-        //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*MAX_QUADS_BATCH, quads.vertices, GL_DYNAMIC_DRAW);
-        glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*3*quads.vCounter, quads.vertices);
-
-        // Quads - texture coordinates buffer
-        glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[1]);
-        //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*4*MAX_QUADS_BATCH, quads.texcoords, GL_DYNAMIC_DRAW);
-        glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*2*quads.vCounter, quads.texcoords);
-
-        // Quads - colors buffer
-        glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[2]);
-        //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*4*MAX_QUADS_BATCH, quads.colors, GL_DYNAMIC_DRAW);
-        glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(unsigned char)*4*quads.vCounter, quads.colors);
-
-        // Another option would be using buffer mapping...
-        //quads.vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE);
-        // Now we can modify vertices
-        //glUnmapBuffer(GL_ARRAY_BUFFER);
-    }
-    //--------------------------------------------------------------
-
-    // Unbind the current VAO
-    if (vaoSupported) glBindVertexArray(0);
-}
-
-// Draw default internal buffers vertex data
-// NOTE: We draw in this order: lines, triangles, quads
-static void DrawDefaultBuffers(void)
-{
-    // Set current shader and upload current MVP matrix
-    if ((lines.vCounter > 0) || (triangles.vCounter > 0) || (quads.vCounter > 0))
-    {
-        glUseProgram(currentShader.id);
-        
-        // Create modelview-projection matrix
-        Matrix matMVP = MatrixMultiply(modelview, projection);
-
-        glUniformMatrix4fv(currentShader.mvpLoc, 1, false, MatrixToFloat(matMVP));
-        glUniform4f(currentShader.tintColorLoc, 1.0f, 1.0f, 1.0f, 1.0f);
-        glUniform1i(currentShader.mapTexture0Loc, 0);
-        
-        // NOTE: Additional map textures not considered for default buffers drawing
-    }
-   
-    // Draw lines buffers
-    if (lines.vCounter > 0)
-    {
-        glBindTexture(GL_TEXTURE_2D, whiteTexture);
-
-        if (vaoSupported)
-        {
-            glBindVertexArray(lines.vaoId);
-        }
-        else
-        {
-            // Bind vertex attrib: position (shader-location = 0)
-            glBindBuffer(GL_ARRAY_BUFFER, lines.vboId[0]);
-            glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
-            glEnableVertexAttribArray(currentShader.vertexLoc);
-
-            // Bind vertex attrib: color (shader-location = 3)
-            glBindBuffer(GL_ARRAY_BUFFER, lines.vboId[1]);
-            glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
-            glEnableVertexAttribArray(currentShader.colorLoc);
-        }
-
-        glDrawArrays(GL_LINES, 0, lines.vCounter);
-
-        if (!vaoSupported) glBindBuffer(GL_ARRAY_BUFFER, 0);
-        glBindTexture(GL_TEXTURE_2D, 0);
-    }
-
-    // Draw triangles buffers
-    if (triangles.vCounter > 0)
-    {
-        glBindTexture(GL_TEXTURE_2D, whiteTexture);
-
-        if (vaoSupported)
-        {
-            glBindVertexArray(triangles.vaoId);
-        }
-        else
-        {
-            // Bind vertex attrib: position (shader-location = 0)
-            glBindBuffer(GL_ARRAY_BUFFER, triangles.vboId[0]);
-            glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
-            glEnableVertexAttribArray(currentShader.vertexLoc);
-
-            // Bind vertex attrib: color (shader-location = 3)
-            glBindBuffer(GL_ARRAY_BUFFER, triangles.vboId[1]);
-            glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
-            glEnableVertexAttribArray(currentShader.colorLoc);
-        }
-
-        glDrawArrays(GL_TRIANGLES, 0, triangles.vCounter);
-
-        if (!vaoSupported) glBindBuffer(GL_ARRAY_BUFFER, 0);
-        glBindTexture(GL_TEXTURE_2D, 0);
-    }
-
-    // Draw quads buffers
-    if (quads.vCounter > 0)
-    {
-        int quadsCount = 0;
-        int numIndicesToProcess = 0;
-        int indicesOffset = 0;
-
-        if (vaoSupported)
-        {
-            glBindVertexArray(quads.vaoId);
-        }
-        else
-        {
-            // Bind vertex attrib: position (shader-location = 0)
-            glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[0]);
-            glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
-            glEnableVertexAttribArray(currentShader.vertexLoc);
-
-            // Bind vertex attrib: texcoord (shader-location = 1)
-            glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[1]);
-            glVertexAttribPointer(currentShader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0);
-            glEnableVertexAttribArray(currentShader.texcoordLoc);
-
-            // Bind vertex attrib: color (shader-location = 3)
-            glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[2]);
-            glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
-            glEnableVertexAttribArray(currentShader.colorLoc);
-            
-            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quads.vboId[3]);
-        }
-
-        //TraceLog(DEBUG, "Draws required per frame: %i", drawsCounter);
-
-        for (int i = 0; i < drawsCounter; i++)
-        {
-            quadsCount = draws[i].vertexCount/4;
-            numIndicesToProcess = quadsCount*6;  // Get number of Quads * 6 index by Quad
-
-            //TraceLog(DEBUG, "Quads to render: %i - Vertex Count: %i", quadsCount, draws[i].vertexCount);
-
-            glBindTexture(GL_TEXTURE_2D, draws[i].textureId);
-
-            // NOTE: The final parameter tells the GPU the offset in bytes from the start of the index buffer to the location of the first index to process
-#if defined(GRAPHICS_API_OPENGL_33)
-            glDrawElements(GL_TRIANGLES, numIndicesToProcess, GL_UNSIGNED_INT, (GLvoid *)(sizeof(GLuint)*indicesOffset));
-#elif defined(GRAPHICS_API_OPENGL_ES2)
-            glDrawElements(GL_TRIANGLES, numIndicesToProcess, GL_UNSIGNED_SHORT, (GLvoid *)(sizeof(GLushort)*indicesOffset));
-#endif
-            //GLenum err;
-            //if ((err = glGetError()) != GL_NO_ERROR) TraceLog(INFO, "OpenGL error: %i", (int)err);    //GL_INVALID_ENUM!
-
-            indicesOffset += draws[i].vertexCount/4*6;
-        }
-
-        if (!vaoSupported)
-        {
-            glBindBuffer(GL_ARRAY_BUFFER, 0);
-            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
-        }
-
-        glBindTexture(GL_TEXTURE_2D, 0);  // Unbind textures
-    }
-
-    if (vaoSupported) glBindVertexArray(0);   // Unbind VAO
-
-    glUseProgram(0);    // Unbind shader program
-
-    // Reset draws counter
-    drawsCounter = 1;
-    draws[0].textureId = whiteTexture;
-    draws[0].vertexCount = 0;
-
-    // Reset vertex counters for next frame
-    lines.vCounter = 0;
-    lines.cCounter = 0;
-    triangles.vCounter = 0;
-    triangles.cCounter = 0;
-    quads.vCounter = 0;
-    quads.tcCounter = 0;
-    quads.cCounter = 0;
-    
-    // Reset depth for next draw
-    currentDepth = -1.0f;
-}
-
-// Unload default internal buffers vertex data from CPU and GPU
-static void UnloadDefaultBuffers(void)
-{
-    // Unbind everything
-    if (vaoSupported) glBindVertexArray(0);
-    glDisableVertexAttribArray(0);
-    glDisableVertexAttribArray(1);
-    glDisableVertexAttribArray(2);
-    glDisableVertexAttribArray(3);
-    glBindBuffer(GL_ARRAY_BUFFER, 0);
-    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
-
-    // Delete VBOs from GPU (VRAM)
-    glDeleteBuffers(1, &lines.vboId[0]);
-    glDeleteBuffers(1, &lines.vboId[1]);
-    glDeleteBuffers(1, &triangles.vboId[0]);
-    glDeleteBuffers(1, &triangles.vboId[1]);
-    glDeleteBuffers(1, &quads.vboId[0]);
-    glDeleteBuffers(1, &quads.vboId[1]);
-    glDeleteBuffers(1, &quads.vboId[2]);
-    glDeleteBuffers(1, &quads.vboId[3]);
-
-    if (vaoSupported)
-    {
-        // Delete VAOs from GPU (VRAM)
-        glDeleteVertexArrays(1, &lines.vaoId);
-        glDeleteVertexArrays(1, &triangles.vaoId);
-        glDeleteVertexArrays(1, &quads.vaoId);
-    }
-
-    // Free vertex arrays memory from CPU (RAM)
-    free(lines.vertices);
-    free(lines.colors);
-
-    free(triangles.vertices);
-    free(triangles.colors);
-
-    free(quads.vertices);
-    free(quads.texcoords);
-    free(quads.colors);
-    free(quads.indices);
-}
-
-// Setup shader uniform values for lights array
-// NOTE: It would be far easier with shader UBOs but are not supported on OpenGL ES 2.0f
-static void SetShaderLights(Shader shader)
-{
-    int locPoint = glGetUniformLocation(shader.id, "lightsCount");
-    glUniform1i(locPoint, lightsCount);
-    
-    char locName[32] = "lights[x].position\0";
-
-    for (int i = 0; i < lightsCount; i++)
-    {
-        locName[7] = '0' + i;
-        
-        memcpy(&locName[10], "enabled\0", strlen("enabled\0") + 1);
-        locPoint = GetShaderLocation(shader, locName);
-        glUniform1i(locPoint, lights[i]->enabled);
-        
-        memcpy(&locName[10], "type\0", strlen("type\0") + 1);
-        locPoint = GetShaderLocation(shader, locName);
-        glUniform1i(locPoint, lights[i]->type);
-        
-        memcpy(&locName[10], "diffuse\0", strlen("diffuse\0") + 2);
-        locPoint = glGetUniformLocation(shader.id, locName);
-        glUniform4f(locPoint, (float)lights[i]->diffuse.r/255, (float)lights[i]->diffuse.g/255, (float)lights[i]->diffuse.b/255, (float)lights[i]->diffuse.a/255);
-        
-        memcpy(&locName[10], "intensity\0", strlen("intensity\0"));
-        locPoint = glGetUniformLocation(shader.id, locName);
-        glUniform1f(locPoint, lights[i]->intensity);
-        
-        switch (lights[i]->type)
-        {
-            case LIGHT_POINT:
-            {
-                memcpy(&locName[10], "position\0", strlen("position\0") + 1);
-                locPoint = GetShaderLocation(shader, locName);
-                glUniform3f(locPoint, lights[i]->position.x, lights[i]->position.y, lights[i]->position.z);
-                
-                memcpy(&locName[10], "radius\0", strlen("radius\0") + 2);
-                locPoint = GetShaderLocation(shader, locName);
-                glUniform1f(locPoint, lights[i]->radius);
-            } break;
-            case LIGHT_DIRECTIONAL:
-            {
-                memcpy(&locName[10], "direction\0", strlen("direction\0") + 2);
-                locPoint = GetShaderLocation(shader, locName);
-                Vector3 direction = { lights[i]->target.x - lights[i]->position.x, lights[i]->target.y - lights[i]->position.y, lights[i]->target.z - lights[i]->position.z };
-                VectorNormalize(&direction);
-                glUniform3f(locPoint, direction.x, direction.y, direction.z);
-            } break;
-            case LIGHT_SPOT:
-            {
-                memcpy(&locName[10], "position\0", strlen("position\0") + 1);
-                locPoint = GetShaderLocation(shader, locName);
-                glUniform3f(locPoint, lights[i]->position.x, lights[i]->position.y, lights[i]->position.z);
-                
-                memcpy(&locName[10], "direction\0", strlen("direction\0") + 2);
-                locPoint = GetShaderLocation(shader, locName);
-                
-                Vector3 direction = { lights[i]->target.x - lights[i]->position.x, lights[i]->target.y - lights[i]->position.y, lights[i]->target.z - lights[i]->position.z };
-                VectorNormalize(&direction);
-                glUniform3f(locPoint, direction.x, direction.y, direction.z);
-                
-                memcpy(&locName[10], "coneAngle\0", strlen("coneAngle\0"));
-                locPoint = GetShaderLocation(shader, locName);
-                glUniform1f(locPoint, lights[i]->coneAngle);
-            } break;
-            default: break;
-        }
-        
-        // TODO: Pass to the shader any other required data from LightData struct
-    }
-}
-
-// Read text data from file
-// NOTE: text chars array should be freed manually
-static char *ReadTextFile(const char *fileName)
-{
-    FILE *textFile;
-    char *text = NULL;
-
-    int count = 0;
-
-    if (fileName != NULL)
-    {
-        textFile = fopen(fileName,"rt");
-
-        if (textFile != NULL)
-        {
-            fseek(textFile, 0, SEEK_END);
-            count = ftell(textFile);
-            rewind(textFile);
-
-            if (count > 0)
-            {
-                text = (char *)malloc(sizeof(char)*(count + 1));
-                count = fread(text, sizeof(char), count, textFile);
-                text[count] = '\0';
-            }
-
-            fclose(textFile);
-        }
-        else TraceLog(WARNING, "[%s] Text file could not be opened", fileName);
-    }
-
-    return text;
-}
-#endif //defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-
-#if defined(GRAPHICS_API_OPENGL_11)
-// Mipmaps data is generated after image data
-static int GenerateMipmaps(unsigned char *data, int baseWidth, int baseHeight)
-{
-    int mipmapCount = 1;                // Required mipmap levels count (including base level)
-    int width = baseWidth;
-    int height = baseHeight;
-    int size = baseWidth*baseHeight*4;  // Size in bytes (will include mipmaps...), RGBA only
-
-    // Count mipmap levels required
-    while ((width != 1) && (height != 1))
-    {
-        if (width != 1) width /= 2;
-        if (height != 1) height /= 2;
-
-        TraceLog(DEBUG, "Next mipmap size: %i x %i", width, height);
-
-        mipmapCount++;
-
-        size += (width*height*4);       // Add mipmap size (in bytes)
-    }
-
-    TraceLog(DEBUG, "Total mipmaps required: %i", mipmapCount);
-    TraceLog(DEBUG, "Total size of data required: %i", size);
-
-    unsigned char *temp = realloc(data, size);
-
-    if (temp != NULL) data = temp;
-    else TraceLog(WARNING, "Mipmaps required memory could not be allocated");
-
-    width = baseWidth;
-    height = baseHeight;
-    size = (width*height*4);
-
-    // Generate mipmaps
-    // NOTE: Every mipmap data is stored after data
-    Color *image = (Color *)malloc(width*height*sizeof(Color));
-    Color *mipmap = NULL;
-    int offset = 0;
-    int j = 0;
-
-    for (int i = 0; i < size; i += 4)
-    {
-        image[j].r = data[i];
-        image[j].g = data[i + 1];
-        image[j].b = data[i + 2];
-        image[j].a = data[i + 3];
-        j++;
-    }
-
-    TraceLog(DEBUG, "Mipmap base (%ix%i)", width, height);
-
-    for (int mip = 1; mip < mipmapCount; mip++)
-    {
-        mipmap = GenNextMipmap(image, width, height);
-
-        offset += (width*height*4); // Size of last mipmap
-        j = 0;
-
-        width /= 2;
-        height /= 2;
-        size = (width*height*4);    // Mipmap size to store after offset
-
-        // Add mipmap to data
-        for (int i = 0; i < size; i += 4)
-        {
-            data[offset + i] = mipmap[j].r;
-            data[offset + i + 1] = mipmap[j].g;
-            data[offset + i + 2] = mipmap[j].b;
-            data[offset + i + 3] = mipmap[j].a;
-            j++;
-        }
-
-        free(image);
-
-        image = mipmap;
-        mipmap = NULL;
-    }
-
-    free(mipmap);       // free mipmap data
-
-    return mipmapCount;
-}
-
-// Manual mipmap generation (basic scaling algorithm)
-static Color *GenNextMipmap(Color *srcData, int srcWidth, int srcHeight)
-{
-    int x2, y2;
-    Color prow, pcol;
-
-    int width = srcWidth/2;
-    int height = srcHeight/2;
-
-    Color *mipmap = (Color *)malloc(width*height*sizeof(Color));
-
-    // Scaling algorithm works perfectly (box-filter)
-    for (int y = 0; y < height; y++)
-    {
-        y2 = 2*y;
-
-        for (int x = 0; x < width; x++)
-        {
-            x2 = 2*x;
-
-            prow.r = (srcData[y2*srcWidth + x2].r + srcData[y2*srcWidth + x2 + 1].r)/2;
-            prow.g = (srcData[y2*srcWidth + x2].g + srcData[y2*srcWidth + x2 + 1].g)/2;
-            prow.b = (srcData[y2*srcWidth + x2].b + srcData[y2*srcWidth + x2 + 1].b)/2;
-            prow.a = (srcData[y2*srcWidth + x2].a + srcData[y2*srcWidth + x2 + 1].a)/2;
-
-            pcol.r = (srcData[(y2+1)*srcWidth + x2].r + srcData[(y2+1)*srcWidth + x2 + 1].r)/2;
-            pcol.g = (srcData[(y2+1)*srcWidth + x2].g + srcData[(y2+1)*srcWidth + x2 + 1].g)/2;
-            pcol.b = (srcData[(y2+1)*srcWidth + x2].b + srcData[(y2+1)*srcWidth + x2 + 1].b)/2;
-            pcol.a = (srcData[(y2+1)*srcWidth + x2].a + srcData[(y2+1)*srcWidth + x2 + 1].a)/2;
-
-            mipmap[y*width + x].r = (prow.r + pcol.r)/2;
-            mipmap[y*width + x].g = (prow.g + pcol.g)/2;
-            mipmap[y*width + x].b = (prow.b + pcol.b)/2;
-            mipmap[y*width + x].a = (prow.a + pcol.a)/2;
-        }
-    }
-
-    TraceLog(DEBUG, "Mipmap generated successfully (%ix%i)", width, height);
-
-    return mipmap;
-}
-#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
-void TraceLog(int msgType, const char *text, ...)
-{
-    va_list args;
-    va_start(args, text);
-
-    switch (msgType)
-    {
-        case INFO: fprintf(stdout, "INFO: "); break;
-        case ERROR: fprintf(stdout, "ERROR: "); break;
-        case WARNING: fprintf(stdout, "WARNING: "); break;
-        case DEBUG: fprintf(stdout, "DEBUG: "); break;
-        default: break;
-    }
-
-    vfprintf(stdout, text, args);
-    fprintf(stdout, "\n");
-
-    va_end(args);
-
-    if (msgType == ERROR) exit(1);
-}
-
-// Converts Matrix to float array
-// NOTE: Returned vector is a transposed version of the Matrix struct, 
-// it should be this way because, despite raymath use OpenGL column-major convention,
-// Matrix struct memory alignment and variables naming are not coherent
-float *MatrixToFloat(Matrix mat)
-{
-    static float buffer[16];
-
-    buffer[0] = mat.m0;
-    buffer[1] = mat.m4;
-    buffer[2] = mat.m8;
-    buffer[3] = mat.m12;
-    buffer[4] = mat.m1;
-    buffer[5] = mat.m5;
-    buffer[6] = mat.m9;
-    buffer[7] = mat.m13;
-    buffer[8] = mat.m2;
-    buffer[9] = mat.m6;
-    buffer[10] = mat.m10;
-    buffer[11] = mat.m14;
-    buffer[12] = mat.m3;
-    buffer[13] = mat.m7;
-    buffer[14] = mat.m11;
-    buffer[15] = mat.m15;
-
-    return buffer;
-}
-#endif

+ 0 - 363
examples/oculus_glfw_sample/rlgl.h

@@ -1,363 +0,0 @@
-/**********************************************************************************************
-*
-*   rlgl - raylib OpenGL abstraction layer
-*
-*   raylib now uses OpenGL 1.1 style functions (rlVertex) that are mapped to selected OpenGL version:
-*       OpenGL 1.1  - Direct map rl* -> gl*
-*       OpenGL 3.3  - Vertex data is stored in VAOs, call rlglDraw() to render
-*       OpenGL ES 2 - Vertex data is stored in VBOs or VAOs (when available), call rlglDraw() to render
-*
-*   Copyright (c) 2014 Ramon Santamaria (@raysan5)
-*
-*   This software is provided "as-is", without any express or implied warranty. In no event
-*   will the authors be held liable for any damages arising from the use of this software.
-*
-*   Permission is granted to anyone to use this software for any purpose, including commercial
-*   applications, and to alter it and redistribute it freely, subject to the following restrictions:
-*
-*     1. The origin of this software must not be misrepresented; you must not claim that you
-*     wrote the original software. If you use this software in a product, an acknowledgment
-*     in the product documentation would be appreciated but is not required.
-*
-*     2. Altered source versions must be plainly marked as such, and must not be misrepresented
-*     as being the original software.
-*
-*     3. This notice may not be removed or altered from any source distribution.
-*
-**********************************************************************************************/
-
-#ifndef RLGL_H
-#define RLGL_H
-
-//#define RLGL_STANDALONE       // NOTE: To use rlgl as standalone lib, just uncomment this line
-
-#ifndef RLGL_STANDALONE
-    #include "raylib.h"         // Required for: Model, Shader, Texture2D
-    #include "utils.h"          // Required for: TraceLog()
-#endif
-
-#ifdef RLGL_STANDALONE
-    #define RAYMATH_STANDALONE
-#endif
-
-#include "raymath.h"            // Required for: Vector3, Matrix
-
-// Select desired OpenGL version
-// NOTE: Those preprocessor defines are only used on rlgl module,
-// if OpenGL version is required by any other module, it uses rlGetVersion()
-
-// 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 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
-#if !defined(GRAPHICS_API_OPENGL_11) && !defined(GRAPHICS_API_OPENGL_33) && !defined(GRAPHICS_API_OPENGL_ES2)
-    #define GRAPHICS_API_OPENGL_11
-#endif
-
-// Security check in case multiple GRAPHICS_API_OPENGL_* defined
-#if defined(GRAPHICS_API_OPENGL_11)
-    #if defined(GRAPHICS_API_OPENGL_33)
-        #undef GRAPHICS_API_OPENGL_33
-    #endif
-
-    #if defined(GRAPHICS_API_OPENGL_ES2)
-        #undef GRAPHICS_API_OPENGL_ES2
-    #endif
-#endif
-
-//----------------------------------------------------------------------------------
-// Defines and Macros
-//----------------------------------------------------------------------------------
-#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33)
-    // NOTE: This is the maximum amount of lines, triangles and quads per frame, be careful!
-    #define MAX_LINES_BATCH         8192
-    #define MAX_TRIANGLES_BATCH     4096
-    #define MAX_QUADS_BATCH         4096
-#elif defined(GRAPHICS_API_OPENGL_ES2)
-    // NOTE: Reduce memory sizes for embedded systems (RPI and HTML5)
-    // NOTE: On HTML5 (emscripten) this is allocated on heap, by default it's only 16MB!...just take care...
-    #define MAX_LINES_BATCH         1024    // Critical for wire shapes (sphere)
-    #define MAX_TRIANGLES_BATCH     2048    // Critical for some shapes (sphere)
-    #define MAX_QUADS_BATCH         1024    // Be careful with text, every letter maps a quad
-#endif
-
-//----------------------------------------------------------------------------------
-// Types and Structures Definition
-//----------------------------------------------------------------------------------
-typedef enum { RL_PROJECTION, RL_MODELVIEW, RL_TEXTURE } MatrixMode;
-
-typedef enum { RL_LINES, RL_TRIANGLES, RL_QUADS } DrawMode;
-
-typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion;
-
-#if defined(RLGL_STANDALONE)
-    #ifndef __cplusplus
-    // Boolean type
-    typedef enum { false, true } bool;
-    #endif
-
-    // byte type
-    typedef unsigned char byte;
-    
-    // Color type, RGBA (32bit)
-    typedef struct Color {
-        unsigned char r;
-        unsigned char g;
-        unsigned char b;
-        unsigned char a;
-    } Color;
-
-    // Texture formats (support depends on OpenGL version)
-    typedef enum { 
-        UNCOMPRESSED_GRAYSCALE = 1,     // 8 bit per pixel (no alpha)
-        UNCOMPRESSED_GRAY_ALPHA,
-        UNCOMPRESSED_R5G6B5,            // 16 bpp
-        UNCOMPRESSED_R8G8B8,            // 24 bpp
-        UNCOMPRESSED_R5G5B5A1,          // 16 bpp (1 bit alpha)
-        UNCOMPRESSED_R4G4B4A4,          // 16 bpp (4 bit alpha)
-        UNCOMPRESSED_R8G8B8A8,          // 32 bpp
-        COMPRESSED_DXT1_RGB,            // 4 bpp (no alpha)
-        COMPRESSED_DXT1_RGBA,           // 4 bpp (1 bit alpha)
-        COMPRESSED_DXT3_RGBA,           // 8 bpp
-        COMPRESSED_DXT5_RGBA,           // 8 bpp
-        COMPRESSED_ETC1_RGB,            // 4 bpp
-        COMPRESSED_ETC2_RGB,            // 4 bpp
-        COMPRESSED_ETC2_EAC_RGBA,       // 8 bpp
-        COMPRESSED_PVRT_RGB,            // 4 bpp
-        COMPRESSED_PVRT_RGBA,           // 4 bpp
-        COMPRESSED_ASTC_4x4_RGBA,       // 8 bpp
-        COMPRESSED_ASTC_8x8_RGBA        // 2 bpp
-    } TextureFormat;
-
-    // Vertex data definning a mesh
-    typedef struct Mesh {
-        int vertexCount;        // number of vertices stored in arrays
-        int triangleCount;      // number of triangles stored (indexed or not)
-        float *vertices;        // vertex position (XYZ - 3 components per vertex) (shader-location = 0)
-        float *texcoords;       // vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1)
-        float *texcoords2;      // vertex second texture coordinates (useful for lightmaps) (shader-location = 5)
-        float *normals;         // vertex normals (XYZ - 3 components per vertex) (shader-location = 2)
-        float *tangents;        // vertex tangents (XYZ - 3 components per vertex) (shader-location = 4)
-        unsigned char *colors;  // vertex colors (RGBA - 4 components per vertex) (shader-location = 3)
-        unsigned short *indices;// vertex indices (in case vertex data comes indexed)
-
-        unsigned int vaoId;     // OpenGL Vertex Array Object id
-        unsigned int vboId[7];  // OpenGL Vertex Buffer Objects id (7 types of vertex data)
-    } Mesh;
-
-    // Shader type (generic shader)
-    typedef struct Shader {
-        unsigned int id;        // Shader program id
-        
-        // Vertex attributes locations (default locations)
-        int vertexLoc;          // Vertex attribute location point (default-location = 0)
-        int texcoordLoc;        // Texcoord attribute location point (default-location = 1)
-        int normalLoc;          // Normal attribute location point (default-location = 2)
-        int colorLoc;           // Color attibute location point (default-location = 3)
-        int tangentLoc;         // Tangent attribute location point (default-location = 4)
-        int texcoord2Loc;       // Texcoord2 attribute location point (default-location = 5)
-
-        // Uniform locations
-        int mvpLoc;             // ModelView-Projection matrix uniform location point (vertex shader)
-        int tintColorLoc;       // Color uniform location point (fragment shader)
-        
-        // Texture map locations (generic for any kind of map)
-        int mapTexture0Loc;     // Map texture uniform location point (default-texture-unit = 0)
-        int mapTexture1Loc;     // Map texture uniform location point (default-texture-unit = 1)
-        int mapTexture2Loc;     // Map texture uniform location point (default-texture-unit = 2)
-    } Shader;
-
-    // Texture2D type
-    // NOTE: Data stored in GPU memory
-    typedef struct Texture2D {
-        unsigned int id;        // OpenGL texture id
-        int width;              // Texture base width
-        int height;             // Texture base height
-        int mipmaps;            // Mipmap levels, 1 by default
-        int format;             // Data format (TextureFormat)
-    } Texture2D;
-    
-    // RenderTexture2D type, for texture rendering
-    typedef struct RenderTexture2D {
-        unsigned int id;        // Render texture (fbo) id
-        Texture2D texture;      // Color buffer attachment texture
-        Texture2D depth;        // Depth buffer attachment texture
-    } RenderTexture2D;
-    
-    // Material type
-    typedef struct Material {
-        Shader shader;          // Standard shader (supports 3 map types: diffuse, normal, specular)
-
-        Texture2D texDiffuse;   // Diffuse texture
-        Texture2D texNormal;    // Normal texture
-        Texture2D texSpecular;  // Specular texture
-
-        Color colDiffuse;       // Diffuse color
-        Color colAmbient;       // Ambient color
-        Color colSpecular;      // Specular color
-        
-        float glossiness;       // Glossiness level (Ranges from 0 to 1000)
-    } Material;
-    
-    // Camera type, defines a camera position/orientation in 3d space
-    typedef struct Camera {
-        Vector3 position;       // Camera position
-        Vector3 target;         // Camera target it looks-at
-        Vector3 up;             // Camera up vector (rotation over its axis)
-        float fovy;             // Camera field-of-view apperture in Y (degrees)
-    } Camera;
-
-    // Light type
-    typedef struct LightData {
-        unsigned int id;        // Light unique id
-        int type;               // Light type: LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT
-        bool enabled;           // Light enabled
-        
-        Vector3 position;       // Light position
-        Vector3 target;         // Light target: LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target)
-        float radius;           // Light attenuation radius light intensity reduced with distance (world distance)
-        
-        Color diffuse;          // Light diffuse color
-        float intensity;        // Light intensity level
-        
-        float coneAngle;        // Light cone max angle: LIGHT_SPOT
-    } LightData, *Light;
-    
-    // Light types
-    typedef enum { LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT } LightType;
-
-    // Color blending modes (pre-defined)
-    typedef enum { BLEND_ALPHA = 0, BLEND_ADDITIVE, BLEND_MULTIPLIED } BlendMode;
-    
-    // TraceLog message types
-    typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType;
-#endif
-
-#ifdef __cplusplus
-extern "C" {            // Prevents name mangling of functions
-#endif
-
-//------------------------------------------------------------------------------------
-// Functions Declaration - Matrix operations
-//------------------------------------------------------------------------------------
-void rlMatrixMode(int mode);                    // Choose the current matrix to be transformed
-void rlPushMatrix(void);                        // Push the current matrix to stack
-void rlPopMatrix(void);                         // Pop lattest inserted matrix from stack
-void rlLoadIdentity(void);                      // Reset current matrix to identity matrix
-void rlTranslatef(float x, float y, float z);   // Multiply the current matrix by a translation matrix
-void rlRotatef(float angleDeg, float x, float y, float z);  // Multiply the current matrix by a rotation matrix
-void rlScalef(float x, float y, float z);       // Multiply the current matrix by a scaling matrix
-void rlMultMatrixf(float *mat);                 // Multiply the current matrix by another matrix
-void rlFrustum(double left, double right, double bottom, double top, double near, double far);
-void rlOrtho(double left, double right, double bottom, double top, double near, double far);
-void rlViewport(int x, int y, int width, int height); // Set the viewport area
-
-//------------------------------------------------------------------------------------
-// Functions Declaration - Vertex level operations
-//------------------------------------------------------------------------------------
-void rlBegin(int mode);                         // Initialize drawing mode (how to organize vertex)
-void rlEnd(void);                               // Finish vertex providing
-void rlVertex2i(int x, int y);                  // Define one vertex (position) - 2 int
-void rlVertex2f(float x, float y);              // Define one vertex (position) - 2 float
-void rlVertex3f(float x, float y, float z);     // Define one vertex (position) - 3 float
-void rlTexCoord2f(float x, float y);            // Define one vertex (texture coordinate) - 2 float
-void rlNormal3f(float x, float y, float z);     // Define one vertex (normal) - 3 float
-void rlColor4ub(byte r, byte g, byte b, byte a);    // Define one vertex (color) - 4 byte
-void rlColor3f(float x, float y, float z);          // Define one vertex (color) - 3 float
-void rlColor4f(float x, float y, float z, float w); // Define one vertex (color) - 4 float
-
-//------------------------------------------------------------------------------------
-// Functions Declaration - OpenGL equivalent functions (common to 1.1, 3.3+, ES2)
-// NOTE: This functions are used to completely abstract raylib code from OpenGL layer
-//------------------------------------------------------------------------------------
-void rlEnableTexture(unsigned int id);          // Enable texture usage
-void rlDisableTexture(void);                    // Disable texture usage
-void rlEnableRenderTexture(unsigned int id);    // Enable render texture (fbo)
-void rlDisableRenderTexture(void);              // Disable render texture (fbo), return to default framebuffer
-void rlEnableDepthTest(void);                   // Enable depth test
-void rlDisableDepthTest(void);                  // Disable depth test
-void rlEnableWireMode(void);                    // Enable wire mode
-void rlDisableWireMode(void);                   // Disable wire mode
-void rlDeleteTextures(unsigned int id);         // Delete OpenGL texture from GPU
-void rlDeleteRenderTextures(RenderTexture2D target);    // Delete render textures (fbo) from GPU
-void rlDeleteShader(unsigned int id);           // Delete OpenGL shader program from GPU
-void rlDeleteVertexArrays(unsigned int id);     // Unload vertex data (VAO) from GPU memory
-void rlDeleteBuffers(unsigned int id);          // Unload vertex data (VBO) from GPU memory
-void rlClearColor(byte r, byte g, byte b, byte a);  // Clear color buffer with color
-void rlClearScreenBuffers(void);                // Clear used screen buffers (color and depth)
-int rlGetVersion(void);                         // Returns current OpenGL version
-
-//------------------------------------------------------------------------------------
-// Functions Declaration - rlgl functionality
-//------------------------------------------------------------------------------------
-void rlglInit(void);                            // Initialize rlgl (shaders, VAO, VBO...)
-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)
-void rlglUpdateTexture(unsigned int id, int width, int height, int format, void *data);         // Update GPU texture with new data
-void rlglGenerateMipmaps(Texture2D texture);                             // Generate mipmap data for selected texture
-
-void rlglLoadMesh(Mesh *mesh, bool dynamic);                        // Upload vertex data into GPU and provided VAO/VBO ids
-void rlglUpdateMesh(Mesh mesh, int buffer, int numVertex);          // Update vertex data on GPU (upload new data to one buffer)
-void rlglDrawMesh(Mesh mesh, Material material, Matrix transform);  // Draw a 3d mesh with material and transform
-void rlglUnloadMesh(Mesh *mesh);                                    // Unload mesh data from CPU and GPU
-
-Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view);    // Get world coordinates from screen coordinates
-
-unsigned char *rlglReadScreenPixels(int width, int height);         // Read screen pixel data (color buffer)
-void *rlglReadTexturePixels(Texture2D texture);                     // Read texture pixel data
-
-// NOTE: There is a set of shader related functions that are available to end user,
-// to avoid creating function wrappers through core module, they have been directly declared in raylib.h
-
-#if defined(RLGL_STANDALONE)
-//------------------------------------------------------------------------------------
-// Shaders System Functions (Module: rlgl)
-// NOTE: This functions are useless when using OpenGL 1.1
-//------------------------------------------------------------------------------------
-Shader LoadShader(char *vsFileName, char *fsFileName);              // Load a custom shader and bind default locations
-void UnloadShader(Shader shader);                                   // Unload a custom shader from memory
-
-Shader GetDefaultShader(void);                                      // Get default shader
-Shader GetStandardShader(void);                                     // Get default shader
-Texture2D GetDefaultTexture(void);                                  // Get default texture
-
-int GetShaderLocation(Shader shader, const char *uniformName);              // Get shader uniform location
-void SetShaderValue(Shader shader, int uniformLoc, float *value, int size); // Set shader uniform value (float)
-void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size);  // Set shader uniform value (int)
-void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat);       // Set shader uniform value (matrix 4x4)
-
-void SetMatrixProjection(Matrix proj);                              // Set a custom projection matrix (replaces internal projection matrix)
-void SetMatrixModelview(Matrix view);                               // Set a custom modelview matrix (replaces internal modelview matrix)
-
-void BeginShaderMode(Shader shader);                                // Begin custom shader drawing
-void EndShaderMode(void);                                           // End custom shader drawing (use default shader)
-void BeginBlendMode(int mode);                                      // Begin blending mode (alpha, additive, multiplied)
-void EndBlendMode(void);                                            // End blending mode (reset to default: alpha blending)
-
-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
-
-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
-
-#endif // RLGL_H

+ 0 - 174
examples/oculus_glfw_sample/standard_shader.h

@@ -1,174 +0,0 @@
-
-// Vertex shader definition to embed, no external file required
-static const char vStandardShaderStr[] = 
-#if defined(GRAPHICS_API_OPENGL_21)
-"#version 120                       \n"
-#elif defined(GRAPHICS_API_OPENGL_ES2)
-"#version 100                       \n"
-#endif
-#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21)
-"attribute vec3 vertexPosition;     \n"
-"attribute vec3 vertexNormal;       \n"
-"attribute vec2 vertexTexCoord;     \n"
-"attribute vec4 vertexColor;        \n"
-"varying vec3 fragPosition;         \n"
-"varying vec3 fragNormal;           \n"
-"varying vec2 fragTexCoord;         \n"
-"varying vec4 fragColor;            \n"
-#elif defined(GRAPHICS_API_OPENGL_33)
-"#version 330                       \n"
-"in vec3 vertexPosition;            \n"
-"in vec3 vertexNormal;              \n"
-"in vec2 vertexTexCoord;            \n"
-"in vec4 vertexColor;               \n"
-"out vec3 fragPosition;             \n"
-"out vec3 fragNormal;               \n"
-"out vec2 fragTexCoord;             \n"
-"out vec4 fragColor;                \n"
-#endif
-"uniform mat4 mvpMatrix;            \n"
-"void main()                        \n"
-"{                                  \n"
-"    fragPosition = vertexPosition; \n"
-"    fragNormal = vertexNormal;     \n"
-"    fragTexCoord = vertexTexCoord; \n"
-"    fragColor = vertexColor;       \n"
-"    gl_Position = mvpMatrix*vec4(vertexPosition, 1.0); \n"
-"}                                  \n";
-
-// Fragment shader definition to embed, no external file required
-static const char fStandardShaderStr[] = 
-#if defined(GRAPHICS_API_OPENGL_21)
-"#version 120                       \n"
-#elif defined(GRAPHICS_API_OPENGL_ES2)
-"#version 100                       \n"
-"precision mediump float;           \n"     // precision required for OpenGL ES2 (WebGL)
-#endif
-#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21)
-"varying vec3 fragPosition;         \n"
-"varying vec3 fragNormal;           \n"
-"varying vec2 fragTexCoord;         \n"
-"varying vec4 fragColor;            \n"
-#elif defined(GRAPHICS_API_OPENGL_33)
-"#version 330                       \n"
-"in vec3 fragPosition;              \n"
-"in vec3 fragNormal;                \n"
-"in vec2 fragTexCoord;              \n"
-"in vec4 fragColor;                 \n"
-"out vec4 finalColor;               \n"
-#endif
-"uniform sampler2D texture0;        \n"
-"uniform sampler2D texture1;        \n"
-"uniform sampler2D texture2;        \n"
-"uniform vec4 colAmbient;           \n"
-"uniform vec4 colDiffuse;           \n"
-"uniform vec4 colSpecular;          \n"
-"uniform float glossiness;          \n"
-"uniform int useNormal;             \n"
-"uniform int useSpecular;           \n"
-"uniform mat4 modelMatrix;          \n"
-"uniform vec3 viewDir;              \n"
-"struct Light {                     \n"
-"    int enabled;                   \n"
-"    int type;                      \n"
-"    vec3 position;                 \n"
-"    vec3 direction;                \n"
-"    vec4 diffuse;                  \n"
-"    float intensity;               \n"
-"    float radius;                  \n"
-"    float coneAngle; };            \n"
-"const int maxLights = 8;           \n"
-"uniform int lightsCount;           \n"
-"uniform Light lights[maxLights];   \n"
-"\n"  
-"vec3 CalcPointLight(Light l, vec3 n, vec3 v, float s)   \n"
-"{\n"
-"    vec3 surfacePos = vec3(modelMatrix*vec4(fragPosition, 1));\n"
-"    vec3 surfaceToLight = l.position - surfacePos;\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.0 + glossiness)*s;\n"
-"    }\n"
-"    return (diff*l.diffuse.rgb + spec*colSpecular.rgb);\n"
-"}\n"
-"\n"
-"vec3 CalcDirectionalLight(Light l, vec3 n, vec3 v, float s)\n"
-"{\n"
-"    vec3 lightDir = normalize(-l.direction);\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.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.0));\n"
-"    vec3 lightToSurface = normalize(surfacePos - l.position);\n"
-"    vec3 lightDir = normalize(-l.direction);\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"
-"    float falloff = (l.coneAngle - lightToSurfaceAngle)/l.coneAngle;\n"
-"    float diffAttenuation = diff*attenuation;\n"
-"    float spec = 0.0;\n"
-"    if (diffAttenuation > 0.0)\n"
-"    {\n"
-"        vec3 h = normalize(lightDir + v);\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 = 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"
-"            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)
-"   finalColor = vec4(texelColor.rgb*lighting*colDiffuse.rgb, texelColor.a*colDiffuse.a); \n"
-#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";

BIN
examples/resources/audio/2t2m_spa.xm


+ 4 - 16
examples/resources/shaders/glsl100/distortion.fs

@@ -8,28 +8,16 @@ varying vec2 fragTexCoord;
 // Input uniform values
 uniform sampler2D texture0;
 
-// NOTE: Add here your custom variables
+// NOTE: Default parameters for Oculus Rift DK2 device
 const vec2 LeftLensCenter = vec2(0.2863248, 0.5);
 const vec2 RightLensCenter = vec2(0.7136753, 0.5);
 const vec2 LeftScreenCenter = vec2(0.25, 0.5);
 const vec2 RightScreenCenter = vec2(0.75, 0.5);
-const vec2 Scale = vec2(0.25, 0.45);    //vec2(0.1469278, 0.2350845);
-const vec2 ScaleIn = vec2(4, 2.2222);
-const vec4 HmdWarpParam = vec4(1, 0.22, 0.24, 0);
+const vec2 Scale = vec2(0.25, 0.45);
+const vec2 ScaleIn = vec2(4.0, 2.5);
+const vec4 HmdWarpParam = vec4(1.0, 0.22, 0.24, 0.0);
 const vec4 ChromaAbParam = vec4(0.996, -0.004, 1.014, 0.0);
 
-/*
-// Another set of default values
-ChromaAbCorrection = {1.0, 0.0, 1.0, 0}
-DistortionK = {1.0, 0.22, 0.24, 0}
-Scale = {0.25, 0.5*AspectRatio, 0, 0}
-ScaleIn = {4.0, 2/AspectRatio, 0, 0}
-Left Screen Center = {0.25, 0.5, 0, 0}
-Left Lens Center = {0.287994117, 0.5, 0, 0}
-Right Screen Center = {0.75, 0.5, 0, 0}
-Right Lens Center = {0.712005913, 0.5, 0, 0}
-*/
-
 void main()
 {
     // The following two variables need to be set per eye

+ 2 - 2
examples/resources/shaders/glsl100/grayscale.fs

@@ -8,14 +8,14 @@ varying vec4 fragColor;
 
 // Input uniform values
 uniform sampler2D texture0;
-uniform vec4 fragTintColor;
+uniform vec4 colDiffuse;
 
 // NOTE: Add here your custom variables
 
 void main()
 {
     // Texel color fetching from texture sampler
-    vec4 texelColor = texture2D(texture0, fragTexCoord)*fragTintColor*fragColor;
+    vec4 texelColor = texture2D(texture0, fragTexCoord)*colDiffuse*fragColor;
     
     // Convert texel color to grayscale using NTSC conversion weights
     float gray = dot(texelColor.rgb, vec3(0.299, 0.587, 0.114));

+ 4 - 4
examples/resources/shaders/glsl100/swirl.fs

@@ -8,7 +8,7 @@ varying vec4 fragColor;
 
 // Input uniform values
 uniform sampler2D texture0;
-uniform vec4 fragTintColor;
+uniform vec4 colDiffuse;
 
 // NOTE: Add here your custom variables
 
@@ -18,7 +18,7 @@ const float renderHeight = 480.0;     // Use uniforms instead...
 float radius = 250.0;
 float angle = 0.8;
 
-uniform vec2 center = vec2(200.0, 200.0);
+uniform vec2 center;
 
 void main()
 {
@@ -39,7 +39,7 @@ void main()
     }
 
     tc += center;
-    vec3 color = texture2D(texture0, tc/texSize).rgb;
+    vec4 color = texture2D(texture0, tc/texSize)*colDiffuse*fragColor;;
 
-    gl_FragColor = vec4(color, 1.0);;
+    gl_FragColor = vec4(color.rgb, 1.0);;
 }

+ 6 - 19
examples/resources/shaders/glsl330/distortion.fs

@@ -9,29 +9,16 @@ uniform sampler2D texture0;
 // Output fragment color
 out vec4 finalColor;
 
-// NOTE: Add here your custom variables
-const vec2 LeftLensCenter = vec2(0.288, 0.5);
-const vec2 RightLensCenter = vec2(0.712, 0.5);
+// NOTE: Default parameters for Oculus Rift DK2 device
+const vec2 LeftLensCenter = vec2(0.2863248, 0.5);
+const vec2 RightLensCenter = vec2(0.7136753, 0.5);
 const vec2 LeftScreenCenter = vec2(0.25, 0.5);
 const vec2 RightScreenCenter = vec2(0.75, 0.5);
-uniform vec2 Scale = vec2(0.25, 0.45);    //vec2(0.1469278, 0.2350845);
-uniform vec2 ScaleIn = vec2(4, 2.2222);
-
-const vec4 HmdWarpParam = vec4(1, 0.22, 0.24, 0);
+const vec2 Scale = vec2(0.25, 0.45);
+const vec2 ScaleIn = vec2(4.0, 2.5);
+const vec4 HmdWarpParam = vec4(1.0, 0.22, 0.24, 0.0);
 const vec4 ChromaAbParam = vec4(0.996, -0.004, 1.014, 0.0);
 
-/*
-// Another set of default values
-ChromaAbCorrection = {1.0, 0.0, 1.0, 0}
-DistortionK = {1.0, 0.22, 0.24, 0}
-Scale = {0.25, 0.5*AspectRatio, 0, 0}
-ScaleIn = {4.0, 2/AspectRatio, 0, 0}
-Left Screen Center = {0.25, 0.5, 0, 0}
-Left Lens Center = {0.287994117, 0.5, 0, 0}
-Right Screen Center = {0.75, 0.5, 0, 0}
-Right Lens Center = {0.712005913, 0.5, 0, 0}
-*/
-
 void main()
 {
     // The following two variables need to be set per eye

+ 3 - 3
examples/resources/shaders/glsl330/swirl.fs

@@ -6,7 +6,7 @@ in vec4 fragColor;
 
 // Input uniform values
 uniform sampler2D texture0;
-uniform vec4 fragTintColor;
+uniform vec4 colDiffuse;
 
 // Output fragment color
 out vec4 finalColor;
@@ -40,7 +40,7 @@ void main()
     }
 
     tc += center;
-    vec3 color = texture(texture0, tc/texSize).rgb;
+    vec4 color = texture2D(texture0, tc/texSize)*colDiffuse*fragColor;;
 
-    finalColor = vec4(color, 1.0);;
+    finalColor = vec4(color.rgb, 1.0);;
 }

+ 67 - 170
examples/oculus_glfw_sample/rlgl_standalone_stereo.c → examples/rlgl_oculus_rift.c

@@ -1,15 +1,25 @@
 /*******************************************************************************************
 *
-*   raylib [rlgl] example - Using rlgl module as standalone module
+*   raylib [rlgl] example - Oculus minimum sample
 *
 *   NOTE: This example requires OpenGL 3.3 or ES2 versions for shaders support,
 *         OpenGL 1.1 does not support shaders but it can also be used.
 *
 *   Compile rlgl module using:
-*   gcc -c rlgl.c -Wall -std=c99 -DRLGL_STANDALONE -DRAYMATH_IMPLEMENTATION -DGRAPHICS_API_OPENGL_33
+*   gcc -c rlgl.c -Wall -std=c99 -DRLGL_STANDALONE -DRAYMATH_IMPLEMENTATION -DGRAPHICS_API_OPENGL_33 -DRLGL_OCULUS_SUPPORT
+*
+*   NOTE 1: rlgl module requires the following header-only files:
+*       external/glad.h - OpenGL extensions loader (stripped to only required extensions)
+*       shader_standard.h - Standard shader for materials and lighting
+*       shader_distortion.h - Distortion shader for VR
+*       raymath.h - Vector and matrix math functions
+*
+*   NOTE 2: rlgl requires LibOVR (Oculus PC SDK) to support Oculus Rift CV1
 *
 *   Compile example using:
-*   gcc -o $(NAME_PART).exe $(FILE_NAME) rlgl.o -lglfw3 -lopengl32 -lgdi32 -std=c99
+*   gcc -o rlgl_oculus_rift.exe rlgl_oculus_rift.c rlgl.o -L. -lLibOVRRT32_1 -lglfw3 -lopengl32 -lgdi32 -std=c99
+*
+*   NOTE: Example must be linked against LibOVRRT32_1.dll that comes with Oculus Rift runtime.
 *
 *   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)
@@ -18,32 +28,20 @@
 *
 ********************************************************************************************/
 
-#include "glad.h"               // Extensions loading library
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
 #include <GLFW/glfw3.h>         // Windows/Context and inputs management
 
 #define RLGL_STANDALONE
 #include "rlgl.h"               // rlgl library: OpenGL 1.1 immediate-mode style coding
 
-#include <stdlib.h>             // Required for: abs()
-
-
 #define RED        (Color){ 230, 41, 55, 255 }     // Red
-#define MAROON     (Color){ 190, 33, 55, 255 }     // Maroon
 #define RAYWHITE   (Color){ 245, 245, 245, 255 }   // My own White (raylib logo)
 #define DARKGRAY   (Color){ 80, 80, 80, 255 }      // Dark Gray
-#define WHITE      (Color){ 255, 255, 255, 255 }   // White
-
-//----------------------------------------------------------------------------------
-// Types and Structures Definition
-//----------------------------------------------------------------------------------
-
-// Rectangle type
-typedef struct Rectangle {
-    int x;
-    int y;
-    int width;
-    int height;
-} Rectangle;
 
 //----------------------------------------------------------------------------------
 // Module specific Functions Declaration
@@ -56,8 +54,6 @@ static void DrawGrid(int slices, float spacing);
 static void DrawCube(Vector3 position, float width, float height, float length, Color color);
 static void DrawCubeWires(Vector3 position, float width, float height, float length, Color color);
 static void DrawRectangleV(Vector2 position, Vector2 size, Color color);
-static void DrawTextureRec(Texture2D texture, Rectangle sourceRec, Vector2 position, Color tint);
-static void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle destRec, Vector2 origin, float rotation, Color tint);
 
 //----------------------------------------------------------------------------------
 // Main Entry point
@@ -66,8 +62,10 @@ int main(void)
 {
     // Initialization
     //--------------------------------------------------------------------------------------
-    const int screenWidth = 1080;
-    const int screenHeight = 600;
+    int screenWidth = 1080;     // Mirror screen width (set to hmdDesc.Resolution.w/2)
+    int screenHeight = 600;     // Mirror screen height (set to hmdDesc.Resolution.h/2)
+    
+    // NOTE: Mirror screen size can be set to any desired resolution!
     
     // GLFW3 Initialization + OpenGL 3.3 Context + Extensions
     //--------------------------------------------------------
@@ -87,7 +85,7 @@ int main(void)
     glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
     glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
    
-    GLFWwindow *window = glfwCreateWindow(screenWidth, screenHeight, "rlgl standalone", NULL, NULL);
+    GLFWwindow *window = glfwCreateWindow(screenWidth, screenHeight, "rlgl oculus rift", NULL, NULL);
     
     if (!window)
     {
@@ -99,38 +97,46 @@ int main(void)
     glfwSetKeyCallback(window, KeyCallback);
     
     glfwMakeContextCurrent(window);
-    glfwSwapInterval(1);
+    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");
+    // Load OpenGL 3.3 supported extensions
+    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
-    
-    Shader distortion = LoadShader("base.vs", "distortion.fs");
+    // Initialize OpenGL context (states and resources)
+    rlglInit(screenWidth, screenHeight);
     
-    // TODO: Upload to distortion shader configuration parameters (screen size, etc.)
-    //SetShaderValue(Shader shader, int uniformLoc, float *value, int size);
-    
-    // Create a RenderTexture2D to be used for render to texture
-    RenderTexture2D target = rlglLoadRenderTexture(screenWidth, screenHeight);
-    
-    Vector3 cubePosition = { 0.0f, 0.0f, 0.0f };
+    rlClearColor(245, 245, 245, 255);                   // Define clear color
+    rlEnableDepthTest();                                // Enable DEPTH_TEST for 3D
     
+    // Define custom camera to initialize projection and view matrices
     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 = 60.0f;                               // Camera field-of-view Y
+    camera.fovy = 45.0f;                                // Camera field-of-view Y
+
+    // Initialize viewport and internal projection/modelview matrices
+    rlViewport(0, 0, screenWidth, screenHeight);
+    rlMatrixMode(RL_PROJECTION);                        // Switch to PROJECTION matrix
+    rlLoadIdentity();                                   // Reset current matrix (PROJECTION)
+    
+    // Setup perspective projection
+    float aspect = (float)screenWidth/(float)screenHeight;
+    double top = 0.01*tan(camera.fovy*PI/360.0);
+    double right = top*aspect;
+    rlFrustum(-right, right, -top, top, 0.01, 1000.0);
+    
+    rlMatrixMode(RL_MODELVIEW);                         // Switch back to MODELVIEW matrix
+    rlLoadIdentity();                                   // Reset current matrix (MODELVIEW)
+    
+    // Setup Camera view
+    Matrix cameraView = MatrixLookAt(camera.position, camera.target, camera.up);
+    rlMultMatrixf(MatrixToFloat(cameraView));      // Multiply MODELVIEW matrix by view matrix (camera)
+
+    InitOculusDevice();                                 // Initialize Oculus Rift CV1
+    
+    Vector3 cubePosition = { 0.0f, 0.0f, 0.0f };
     //--------------------------------------------------------------------------------------    
 
     // Main game loop    
@@ -138,29 +144,14 @@ int main(void)
     {
         // Update
         //----------------------------------------------------------------------------------
-        // ...
+        UpdateOculusTracking();
         //----------------------------------------------------------------------------------
 
         // Draw
         //----------------------------------------------------------------------------------
-        rlEnableRenderTexture(target.id);   // Enable render target
-    
-        rlClearScreenBuffers();             // Clear current framebuffer
-    
-        for (int i = 0; i < 2; i++)
-        {
-            rlViewport(i*screenWidth/2, 0, screenWidth/2, screenHeight); 
-    
-            // Calculate projection matrix (from perspective) and view matrix from camera look at
-            // TODO: Consider every eye fovy
-            Matrix matProj = MatrixPerspective(camera.fovy, (double)(screenWidth/2)/(double)screenHeight, 0.01, 1000.0);
-            MatrixTranspose(&matProj);
-            
-            // TODO: Recalculate view matrix considering IPD (inter-pupillary-distance)
-            Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up);
-
-            SetMatrixModelview(matView);    // Replace internal modelview matrix by a custom one
-            SetMatrixProjection(matProj);   // Replace internal projection matrix by a custom one
+        BeginOculusDrawing();
+        
+            rlClearScreenBuffers();             // Clear current framebuffer(s)
 
             DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED);
             DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, RAYWHITE);
@@ -168,51 +159,9 @@ int main(void)
 
             // NOTE: Internal buffers drawing (3D data)
             rlglDraw();
-            
-            // Draw '2D' elements in the scene (GUI)
-#define RLGL_CREATE_MATRIX_MANUALLY
-#if defined(RLGL_CREATE_MATRIX_MANUALLY)
-
-            matProj = MatrixOrtho(0.0, screenWidth/2, screenHeight, 0.0, 0.0, 1.0);
-            MatrixTranspose(&matProj);
-            matView = MatrixIdentity();
-            
-            SetMatrixModelview(matView);    // Replace internal modelview matrix by a custom one
-            SetMatrixProjection(matProj);   // Replace internal projection matrix by a custom one
-
-#else   // Let rlgl generate and multiply matrix internally
-
-            rlMatrixMode(RL_PROJECTION);                            // Enable internal projection matrix
-            rlLoadIdentity();                                       // Reset internal projection matrix
-            rlOrtho(0.0, screenWidth/2, screenHeight, 0.0, 0.0, 1.0); // Recalculate internal projection matrix
-            rlMatrixMode(RL_MODELVIEW);                             // Enable internal modelview matrix
-            rlLoadIdentity();                                       // Reset internal modelview matrix
-#endif
-            // TODO: 2D not drawing properly on stereo rendering
-            //DrawRectangleV((Vector2){ 10.0f, 10.0f }, (Vector2){ 500.0f, 20.0f }, DARKGRAY);
-
-            // NOTE: Internal buffers drawing (2D data)
-            rlglDraw();
-        }
-        
-        rlDisableRenderTexture();           // Disable render target
 
-        // Set viewport to default framebuffer size (screen size)
-        rlViewport(0, 0, screenWidth, screenHeight);
-        
-        // Let rlgl reconfigure internal matrices using OpenGL 1.1 style coding
-        rlMatrixMode(RL_PROJECTION);                            // Enable internal projection matrix
-        rlLoadIdentity();                                       // Reset internal projection matrix
-        rlOrtho(0.0, screenWidth, screenHeight, 0.0, 0.0, 1.0); // Recalculate internal projection matrix
-        rlMatrixMode(RL_MODELVIEW);                             // Enable internal modelview matrix
-        rlLoadIdentity();                                       // Reset internal modelview matrix
-    
-        // Draw RenderTexture (fbo) using distortion shader 
-        BeginShaderMode(distortion);
-            // NOTE: Render texture must be y-flipped due to default OpenGL coordinates (left-bottom)
-            DrawTextureRec(target.texture, (Rectangle){ 0, 0, target.texture.width, -target.texture.height }, (Vector2){ 0, 0 }, WHITE);
-        EndShaderMode();
-            
+        EndOculusDrawing();
+
         glfwSwapBuffers(window);
         glfwPollEvents();
         //----------------------------------------------------------------------------------
@@ -220,12 +169,12 @@ int main(void)
 
     // De-Initialization
     //--------------------------------------------------------------------------------------
-    UnloadShader(distortion);
-    
-    rlglClose();                // Unload rlgl internal buffers and default shader/texture
+    CloseOculusDevice();            // Close Oculus device and clear resources
+
+    rlglClose();                    // Unload rlgl internal buffers and default shader/texture
     
-    glfwDestroyWindow(window);
-    glfwTerminate();
+    glfwDestroyWindow(window);      // Close window
+    glfwTerminate();                // Free GLFW3 resources
     //--------------------------------------------------------------------------------------
     
     return 0;
@@ -441,56 +390,4 @@ void DrawCubeWires(Vector3 position, float width, float height, float length, Co
             rlVertex3f(x+width/2, y-height/2, z-length/2);  // Top Right Back
         rlEnd();
     rlPopMatrix();
-}
-
-// Draw a part of a texture (defined by a rectangle)
-static void DrawTextureRec(Texture2D texture, Rectangle sourceRec, Vector2 position, Color tint)
-{
-    Rectangle destRec = { (int)position.x, (int)position.y, abs(sourceRec.width), abs(sourceRec.height) };
-    Vector2 origin = { 0, 0 };
-
-    DrawTexturePro(texture, sourceRec, destRec, origin, 0.0f, tint);
-}
-
-// Draw a part of a texture (defined by a rectangle) with 'pro' parameters
-// NOTE: origin is relative to destination rectangle size
-static void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle destRec, Vector2 origin, float rotation, Color tint)
-{
-    // Check if texture is valid
-    if (texture.id != 0)
-    {
-        if (sourceRec.width < 0) sourceRec.x -= sourceRec.width;
-        if (sourceRec.height < 0) sourceRec.y -= sourceRec.height;
-        
-        rlEnableTexture(texture.id);
-
-        rlPushMatrix();
-            rlTranslatef(destRec.x, destRec.y, 0);
-            rlRotatef(rotation, 0, 0, 1);
-            rlTranslatef(-origin.x, -origin.y, 0);
-
-            rlBegin(RL_QUADS);
-                rlColor4ub(tint.r, tint.g, tint.b, tint.a);
-                rlNormal3f(0.0f, 0.0f, 1.0f);                          // Normal vector pointing towards viewer
-
-                // Bottom-left corner for texture and quad
-                rlTexCoord2f((float)sourceRec.x / texture.width, (float)sourceRec.y / texture.height);
-                rlVertex2f(0.0f, 0.0f);
-
-                // Bottom-right corner for texture and quad
-                rlTexCoord2f((float)sourceRec.x / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height);
-                rlVertex2f(0.0f, destRec.height);
-
-                // Top-right corner for texture and quad
-                rlTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height);
-                rlVertex2f(destRec.width, destRec.height);
-
-                // Top-left corner for texture and quad
-                rlTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)sourceRec.y / texture.height);
-                rlVertex2f(destRec.width, 0.0f);
-            rlEnd();
-        rlPopMatrix();
-
-        rlDisableTexture();
-    }
-}
+}

+ 21 - 23
examples/oculus_glfw_sample/rlgl_standalone.c → examples/rlgl_standalone.c

@@ -8,8 +8,14 @@
 *   Compile rlgl module using:
 *   gcc -c rlgl.c -Wall -std=c99 -DRLGL_STANDALONE -DRAYMATH_IMPLEMENTATION -DGRAPHICS_API_OPENGL_33
 *
+*   NOTE: rlgl module requires the following header-only files:
+*       external/glad.h - OpenGL extensions loader (stripped to only required extensions)
+*       shader_standard.h - Standard shader for materials and lighting
+*       shader_distortion.h - Distortion shader for VR
+*       raymath.h - Vector and matrix math functions
+*
 *   Compile example using:
-*   gcc -o $(NAME_PART).exe $(FILE_NAME) rlgl.o -lglfw3 -lopengl32 -lgdi32 -std=c99
+*   gcc -o rlgl_standalone.exe rlgl_standalone.c rlgl.o -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)
@@ -18,15 +24,12 @@
 *
 ********************************************************************************************/
 
-#include "glad.h"               // Extensions loading library
 #include <GLFW/glfw3.h>         // Windows/Context and inputs management
 
 #define RLGL_STANDALONE
 #include "rlgl.h"               // rlgl library: OpenGL 1.1 immediate-mode style coding
 
-
 #define RED        (Color){ 230, 41, 55, 255 }     // Red
-#define MAROON     (Color){ 190, 33, 55, 255 }     // Maroon
 #define RAYWHITE   (Color){ 245, 245, 245, 255 }   // My own White (raylib logo)
 #define DARKGRAY   (Color){ 80, 80, 80, 255 }      // Dark Gray
 
@@ -52,7 +55,6 @@ int main(void)
     const int screenWidth = 800;
     const int screenHeight = 450;
     
-    
     // GLFW3 Initialization + OpenGL 3.3 Context + Extensions
     //--------------------------------------------------------
     glfwSetErrorCallback(ErrorCallback);
@@ -80,23 +82,20 @@ int main(void)
     }
     else TraceLog(INFO, "GLFW3: Window created successfully");
     
+    glfwSetWindowPos(window, 200, 200);
+    
     glfwSetKeyCallback(window, KeyCallback);
     
     glfwMakeContextCurrent(window);
     glfwSwapInterval(1);
-
-    // 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");
-    //--------------------------------------------------------
     
-    // Initialize rlgl internal buffers and OpenGL state
-    rlglInit();
+    // Load OpenGL 3.3 supported extensions
+    rlglLoadExtensions(glfwGetProcAddress);
+    //--------------------------------------------------------
     
+    // Initialize OpenGL context (states and resources)
+    rlglInit(screenWidth, screenHeight);
+
     // Initialize viewport and internal projection/modelview matrices
     rlViewport(0, 0, screenWidth, screenHeight);
     rlMatrixMode(RL_PROJECTION);                        // Switch to PROJECTION matrix
@@ -108,13 +107,13 @@ int main(void)
     rlClearColor(245, 245, 245, 255);                   // Define clear color
     rlEnableDepthTest();                                // Enable DEPTH_TEST for 3D
     
-    Vector3 cubePosition = { 0.0f, 0.0f, 0.0f };        // Cube default position (center)
-    
     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 };        // Cube default position (center)
     //--------------------------------------------------------------------------------------    
 
     // Main game loop    
@@ -147,7 +146,6 @@ int main(void)
             // Draw '2D' elements in the scene (GUI)
 #define RLGL_CREATE_MATRIX_MANUALLY
 #if defined(RLGL_CREATE_MATRIX_MANUALLY)
-
             matProj = MatrixOrtho(0.0, screenWidth, screenHeight, 0.0, 0.0, 1.0);
             MatrixTranspose(&matProj);
             matView = MatrixIdentity();
@@ -163,7 +161,7 @@ int main(void)
             rlMatrixMode(RL_MODELVIEW);                             // Enable internal modelview matrix
             rlLoadIdentity();                                       // Reset internal modelview matrix
 #endif
-            DrawRectangleV((Vector2){ 10.0f, 10.0f }, (Vector2){ 600.0f, 20.0f }, DARKGRAY);
+            DrawRectangleV((Vector2){ 10.0f, 10.0f }, (Vector2){ 780.0f, 20.0f }, DARKGRAY);
 
             // NOTE: Internal buffers drawing (2D data)
             rlglDraw();
@@ -175,10 +173,10 @@ int main(void)
 
     // De-Initialization
     //--------------------------------------------------------------------------------------
-    rlglClose();                            // Unload rlgl internal buffers and default shader/texture
+    rlglClose();                    // Unload rlgl internal buffers and default shader/texture
     
-    glfwDestroyWindow(window);
-    glfwTerminate();
+    glfwDestroyWindow(window);      // Close window
+    glfwTerminate();                // Free GLFW3 resources
     //--------------------------------------------------------------------------------------
     
     return 0;

BIN
examples/shaders_custom_uniform.png


BIN
examples/shaders_postprocessing.png


BIN
examples/shaders_standard_lighting.png


BIN
release/android/armeabi/libraylib.a


+ 33 - 24
release/android/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)
@@ -431,8 +431,8 @@ typedef struct Model {
 // Light type
 typedef struct LightData {
     unsigned int id;        // Light unique id
-    int type;               // Light type: LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT
     bool enabled;           // Light enabled
+    int type;               // Light type: LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT
     
     Vector3 position;       // Light position
     Vector3 target;         // Light target: LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target)
@@ -468,8 +468,6 @@ typedef struct Wave {
     short channels;
 } Wave;
 
-typedef int RawAudioContext;
-
 // Texture formats
 // NOTE: Support depends on OpenGL version and platform
 typedef enum {
@@ -527,6 +525,19 @@ typedef struct GestureEvent {
 // Camera system modes
 typedef enum { CAMERA_CUSTOM = 0, CAMERA_FREE, CAMERA_ORBITAL, CAMERA_FIRST_PERSON, CAMERA_THIRD_PERSON } CameraMode;
 
+// Head Mounted Display devices
+typedef enum {
+    HMD_DEFAULT_DEVICE = 0,
+    HMD_OCULUS_RIFT_DK2,
+    HMD_OCULUS_RIFT_CV1,
+    HMD_VALVE_HTC_VIVE,
+    HMD_SAMSUNG_GEAR_VR,
+    HMD_GOOGLE_CARDBOARD,
+    HMD_SONY_PLAYSTATION_VR,
+    HMD_RAZER_OSVR,
+    HMD_FOVE_VR,
+} HmdDevice;
+
 #ifdef __cplusplus
 extern "C" {            // Prevents name mangling of functions
 #endif
@@ -545,12 +556,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)
@@ -644,13 +649,13 @@ 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
+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
@@ -800,7 +805,6 @@ Model LoadModelFromRES(const char *rresName, int resId);        // Load a 3d mod
 Model LoadHeightmap(Image heightmap, Vector3 size);             // Load a heightmap image as a 3d model
 Model LoadCubicmap(Image cubicmap);                             // Load a map image as a 3d model (cubes based)
 void UnloadModel(Model model);                                  // Unload 3d model from memory
-void SetModelTexture(Model *model, Texture2D texture);          // Link a texture to a model
 
 Material LoadMaterial(const char *fileName);                    // Load material data (from file)
 Material LoadDefaultMaterial(void);                             // Load default material (uses default models shader)
@@ -852,6 +856,18 @@ 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
 
+//------------------------------------------------------------------------------------
+// VR experience Functions (Module: rlgl)
+// NOTE: This functions are useless when using OpenGL 1.1
+//------------------------------------------------------------------------------------
+void InitVrDevice(int hmdDevice);           // Init VR device
+void CloseVrDevice(void);                   // Close VR device
+void UpdateVrTracking(void);                // Update VR tracking (position and orientation)
+void BeginVrDrawing(void);                  // Begin VR drawing configuration
+void EndVrDrawing(void);                    // End VR drawing process (and desktop mirror)
+bool IsVrDeviceReady(void);                 // Detect if VR device (or simulator) is ready
+void ToggleVrMode(void);                    // Enable/Disable VR experience (device or simulator)
+
 //------------------------------------------------------------------------------------
 // Audio Loading and Playing Functions (Module: audio)
 //------------------------------------------------------------------------------------
@@ -877,17 +893,10 @@ void PauseMusicStream(int index);                               // Pause music p
 void ResumeMusicStream(int index);                              // Resume playing paused music
 bool IsMusicPlaying(int index);                                 // Check if music is playing
 void SetMusicVolume(int index, float volume);                   // Set volume for music (1.0 is max level)
+void SetMusicPitch(int index, float pitch);                     // Set pitch for a music (1.0 is base level)
 float GetMusicTimeLength(int index);                            // Get current music time length (in seconds)
 float GetMusicTimePlayed(int index);                            // Get current music time played (in seconds)
-int GetMusicStreamCount(void);
-void SetMusicPitch(int index, float pitch);
-
-// used to output raw audio streams, returns negative numbers on error
-// if floating point is false the data size is 16bit short, otherwise it is float 32bit
-RawAudioContext InitRawAudioContext(int sampleRate, int channels, bool floatingPoint);
-
-void CloseRawAudioContext(RawAudioContext ctx);
-int BufferRawAudioContext(RawAudioContext ctx, void *data, unsigned short numberElements); // returns number of elements buffered
+int GetMusicStreamCount(void);                                  // Get number of streams loaded
 
 #ifdef __cplusplus
 }

BIN
release/html5/libraylib.bc


+ 33 - 24
release/html5/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)
@@ -431,8 +431,8 @@ typedef struct Model {
 // Light type
 typedef struct LightData {
     unsigned int id;        // Light unique id
-    int type;               // Light type: LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT
     bool enabled;           // Light enabled
+    int type;               // Light type: LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT
     
     Vector3 position;       // Light position
     Vector3 target;         // Light target: LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target)
@@ -468,8 +468,6 @@ typedef struct Wave {
     short channels;
 } Wave;
 
-typedef int RawAudioContext;
-
 // Texture formats
 // NOTE: Support depends on OpenGL version and platform
 typedef enum {
@@ -527,6 +525,19 @@ typedef struct GestureEvent {
 // Camera system modes
 typedef enum { CAMERA_CUSTOM = 0, CAMERA_FREE, CAMERA_ORBITAL, CAMERA_FIRST_PERSON, CAMERA_THIRD_PERSON } CameraMode;
 
+// Head Mounted Display devices
+typedef enum {
+    HMD_DEFAULT_DEVICE = 0,
+    HMD_OCULUS_RIFT_DK2,
+    HMD_OCULUS_RIFT_CV1,
+    HMD_VALVE_HTC_VIVE,
+    HMD_SAMSUNG_GEAR_VR,
+    HMD_GOOGLE_CARDBOARD,
+    HMD_SONY_PLAYSTATION_VR,
+    HMD_RAZER_OSVR,
+    HMD_FOVE_VR,
+} HmdDevice;
+
 #ifdef __cplusplus
 extern "C" {            // Prevents name mangling of functions
 #endif
@@ -545,12 +556,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)
@@ -644,13 +649,13 @@ 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
+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
@@ -800,7 +805,6 @@ Model LoadModelFromRES(const char *rresName, int resId);        // Load a 3d mod
 Model LoadHeightmap(Image heightmap, Vector3 size);             // Load a heightmap image as a 3d model
 Model LoadCubicmap(Image cubicmap);                             // Load a map image as a 3d model (cubes based)
 void UnloadModel(Model model);                                  // Unload 3d model from memory
-void SetModelTexture(Model *model, Texture2D texture);          // Link a texture to a model
 
 Material LoadMaterial(const char *fileName);                    // Load material data (from file)
 Material LoadDefaultMaterial(void);                             // Load default material (uses default models shader)
@@ -852,6 +856,18 @@ 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
 
+//------------------------------------------------------------------------------------
+// VR experience Functions (Module: rlgl)
+// NOTE: This functions are useless when using OpenGL 1.1
+//------------------------------------------------------------------------------------
+void InitVrDevice(int hmdDevice);           // Init VR device
+void CloseVrDevice(void);                   // Close VR device
+void UpdateVrTracking(void);                // Update VR tracking (position and orientation)
+void BeginVrDrawing(void);                  // Begin VR drawing configuration
+void EndVrDrawing(void);                    // End VR drawing process (and desktop mirror)
+bool IsVrDeviceReady(void);                 // Detect if VR device (or simulator) is ready
+void ToggleVrMode(void);                    // Enable/Disable VR experience (device or simulator)
+
 //------------------------------------------------------------------------------------
 // Audio Loading and Playing Functions (Module: audio)
 //------------------------------------------------------------------------------------
@@ -877,17 +893,10 @@ void PauseMusicStream(int index);                               // Pause music p
 void ResumeMusicStream(int index);                              // Resume playing paused music
 bool IsMusicPlaying(int index);                                 // Check if music is playing
 void SetMusicVolume(int index, float volume);                   // Set volume for music (1.0 is max level)
+void SetMusicPitch(int index, float pitch);                     // Set pitch for a music (1.0 is base level)
 float GetMusicTimeLength(int index);                            // Get current music time length (in seconds)
 float GetMusicTimePlayed(int index);                            // Get current music time played (in seconds)
-int GetMusicStreamCount(void);
-void SetMusicPitch(int index, float pitch);
-
-// used to output raw audio streams, returns negative numbers on error
-// if floating point is false the data size is 16bit short, otherwise it is float 32bit
-RawAudioContext InitRawAudioContext(int sampleRate, int channels, bool floatingPoint);
-
-void CloseRawAudioContext(RawAudioContext ctx);
-int BufferRawAudioContext(RawAudioContext ctx, void *data, unsigned short numberElements); // returns number of elements buffered
+int GetMusicStreamCount(void);                                  // Get number of streams loaded
 
 #ifdef __cplusplus
 }

BIN
release/win32/mingw32/libraylib.a


+ 3 - 3
src/Makefile

@@ -49,10 +49,10 @@ ifeq ($(PLATFORM),PLATFORM_RPI)
     # define raylib graphics api to use (on RPI, OpenGL ES 2.0 must be used)
     GRAPHICS = GRAPHICS_API_OPENGL_ES2
 else
-    # define raylib graphics api to use (OpenGL 1.1 by default)
-    GRAPHICS ?= GRAPHICS_API_OPENGL_11
+    # define raylib graphics api to use (OpenGL 3.3 by default)
+    GRAPHICS ?= GRAPHICS_API_OPENGL_33
+    #GRAPHICS = GRAPHICS_API_OPENGL_11  # Uncomment to use OpenGL 1.1
     #GRAPHICS = GRAPHICS_API_OPENGL_21  # Uncomment to use OpenGL 2.1
-    #GRAPHICS = GRAPHICS_API_OPENGL_33  # Uncomment to use OpenGL 3.3
 endif
 ifeq ($(PLATFORM),PLATFORM_WEB)
     GRAPHICS = GRAPHICS_API_OPENGL_ES2

+ 257 - 239
src/audio.c

@@ -2,13 +2,26 @@
 *
 *   raylib.audio
 *
-*   Basic functions to manage Audio: InitAudioDevice, LoadAudioFiles, PlayAudioFiles
+*   Basic functions to manage Audio: 
+*       Manage audio device (init/close)
+*       Load and Unload audio files
+*       Play/Stop/Pause/Resume loaded audio
+*       Manage mixing channels
+*       Manage raw audio context
 *
 *   Uses external lib:
 *       OpenAL Soft - Audio device management lib (http://kcat.strangesoft.net/openal.html)
 *       stb_vorbis - Ogg audio files loading (http://www.nothings.org/stb_vorbis/)
+*       jar_xm - XM module file loading
+*       jar_mod - MOD audio file loading
 *
-*   Copyright (c) 2014 Ramon Santamaria (@raysan5)
+*   Many thanks to Joshua Reisenauer (github: @kd7tck) for the following additions:
+*       XM audio module support (jar_xm)
+*       MOD audio module support (jar_mod)
+*       Mixing channels support
+*       Raw audio context support
+*
+*   Copyright (c) 2014-2016 Ramon Santamaria (@raysan5)
 *
 *   This software is provided "as-is", without any express or implied warranty. In no event
 *   will the authors be held liable for any damages arising from the use of this software.
@@ -68,9 +81,9 @@
 //----------------------------------------------------------------------------------
 // Defines and Macros
 //----------------------------------------------------------------------------------
-#define MAX_STREAM_BUFFERS          2             // Number of buffers for each alSource
-#define MAX_MIX_CHANNELS            4             // Number of open AL sources
+#define MAX_STREAM_BUFFERS          2             // Number of buffers for each source
 #define MAX_MUSIC_STREAMS           2             // Number of simultanious music sources
+#define MAX_MIX_CHANNELS            4             // Number of mix channels (OpenAL sources)
 
 #if defined(PLATFORM_RPI) || defined(PLATFORM_ANDROID)
     // NOTE: On RPI and Android should be lower to avoid frame-stalls
@@ -86,10 +99,10 @@
 // Types and Structures Definition
 //----------------------------------------------------------------------------------
 
-// Used to create custom audio streams that are not bound to a specific file. There can be
-// no more than 4 concurrent mixchannels in use. This is due to each active mixc being tied to
-// a dedicated mix channel.
-typedef struct MixChannel_t {
+// Used to create custom audio streams that are not bound to a specific file. 
+// There can be no more than 4 concurrent mixchannels in use. 
+// This is due to each active mixc being tied to a dedicated mix channel.
+typedef struct MixChannel {
     unsigned short sampleRate;           // default is 48000
     unsigned char channels;              // 1=mono,2=stereo
     unsigned char mixChannel;            // 0-3 or mixA-mixD, each mix channel can receive up to one dedicated audio stream
@@ -99,40 +112,40 @@ typedef struct MixChannel_t {
     ALenum alFormat;                     // OpenAL format specifier
     ALuint alSource;                     // OpenAL source
     ALuint alBuffer[MAX_STREAM_BUFFERS]; // OpenAL sample buffer
-} MixChannel_t;
+} MixChannel;
 
 // Music type (file streaming from memory)
 // NOTE: Anything longer than ~10 seconds should be streamed into a mix channel...
 typedef struct Music {
     stb_vorbis *stream;
-    jar_xm_context_t *xmctx;   // XM chiptune context
-    jar_mod_context_t modctx;  // MOD chiptune context
-    MixChannel_t *mixc;        // mix channel
+    jar_xm_context_t *xmctx;    // XM chiptune context
+    jar_mod_context_t modctx;   // MOD chiptune context
+    MixChannel *mixc;           // Mix channel
     
     unsigned int totalSamplesLeft;
     float totalLengthSeconds;
     bool loop;
-    bool chipTune;             // chiptune is loaded?
+    bool chipTune;              // chiptune is loaded?
     bool enabled;
 } Music;
 
 // Audio errors registered
 typedef enum {
-    ERROR_RAW_CONTEXT_CREATION = 1,
-    ERROR_XM_CONTEXT_CREATION = 2,
-    ERROR_MOD_CONTEXT_CREATION = 4,
-    ERROR_MIX_CHANNEL_CREATION = 8,
-    ERROR_MUSIC_CHANNEL_CREATION = 16,
-    ERROR_LOADING_XM = 32,
-    ERROR_LOADING_MOD = 64,
-    ERROR_LOADING_WAV = 128,
-    ERROR_LOADING_OGG = 256,
-    ERROR_OUT_OF_MIX_CHANNELS = 512,
-    ERROR_EXTENSION_NOT_RECOGNIZED = 1024,
-    ERROR_UNABLE_TO_OPEN_RRES_FILE = 2048,
-    ERROR_INVALID_RRES_FILE = 4096,
-    ERROR_INVALID_RRES_RESOURCE = 8192,
-    ERROR_UNINITIALIZED_CHANNELS = 16384
+    ERROR_RAW_CONTEXT_CREATION      = 1,
+    ERROR_XM_CONTEXT_CREATION       = 2,
+    ERROR_MOD_CONTEXT_CREATION      = 4,
+    ERROR_MIX_CHANNEL_CREATION      = 8,
+    ERROR_MUSIC_CHANNEL_CREATION    = 16,
+    ERROR_LOADING_XM                = 32,
+    ERROR_LOADING_MOD               = 64,
+    ERROR_LOADING_WAV               = 128,
+    ERROR_LOADING_OGG               = 256,
+    ERROR_OUT_OF_MIX_CHANNELS       = 512,
+    ERROR_EXTENSION_NOT_RECOGNIZED  = 1024,
+    ERROR_UNABLE_TO_OPEN_RRES_FILE  = 2048,
+    ERROR_INVALID_RRES_FILE         = 4096,
+    ERROR_INVALID_RRES_RESOURCE     = 8192,
+    ERROR_UNINITIALIZED_CHANNELS    = 16384
 } AudioError;
 
 #if defined(AUDIO_STANDALONE)
@@ -142,10 +155,10 @@ typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType;
 //----------------------------------------------------------------------------------
 // Global Variables Definition
 //----------------------------------------------------------------------------------
-static Music musicChannels_g[MAX_MUSIC_STREAMS];             // Current music loaded, up to two can play at the same time
-static MixChannel_t *mixChannels_g[MAX_MIX_CHANNELS];        // What mix channels are currently active
+static Music musicStreams[MAX_MUSIC_STREAMS];            // Current music loaded, up to two can play at the same time
+static MixChannel *mixChannels[MAX_MIX_CHANNELS];        // Mix channels currently active (from music streams)
 
-static int lastAudioError = 0;                               // Registers last audio error
+static int lastAudioError = 0;                           // Registers last audio error
 
 //----------------------------------------------------------------------------------
 // Module specific Functions Declaration
@@ -157,13 +170,11 @@ static void UnloadWave(Wave wave);                 // Unload wave data
 static bool BufferMusicStream(int index, int numBuffers); // Fill music buffers with data
 static void EmptyMusicStream(int index);                  // Empty music buffers
 
-static MixChannel_t *InitMixChannel(unsigned short sampleRate, unsigned char mixChannel, unsigned char channels, bool floatingPoint); // For streaming into mix channels.
-static void CloseMixChannel(MixChannel_t *mixc); // Frees mix channel
-static int BufferMixChannel(MixChannel_t *mixc, void *data, int numberElements); // Pushes more audio data into mixc mix channel, if NULL is passed it pauses
-static int FillAlBufferWithSilence(MixChannel_t *mixc, ALuint buffer); // Fill buffer with zeros, returns number processed
-static void ResampleShortToFloat(short *shorts, float *floats, unsigned short len); // Pass two arrays of the same legnth in
-static void ResampleByteToFloat(char *chars, float *floats, unsigned short len); // Pass two arrays of same length in
-static int IsMusicStreamReadyForBuffering(int index); // Checks if music buffer is ready to be refilled
+static MixChannel *InitMixChannel(unsigned short sampleRate, unsigned char mixChannel, unsigned char channels, bool floatingPoint);
+static void CloseMixChannel(MixChannel *mixc); // Frees mix channel
+static int BufferMixChannel(MixChannel *mixc, void *data, int numberElements); // Pushes more audio data into mix channel
+//static void ResampleShortToFloat(short *shorts, float *floats, unsigned short len); // Pass two arrays of the same legnth in
+//static void ResampleByteToFloat(char *chars, float *floats, unsigned short len); // Pass two arrays of same length in
 
 #if defined(AUDIO_STANDALONE)
 const char *GetExtension(const char *fileName);     // Get the extension for a filename
@@ -204,9 +215,9 @@ void InitAudioDevice(void)
 // Close the audio device for all contexts
 void CloseAudioDevice(void)
 {
-    for (int index=0; index<MAX_MUSIC_STREAMS; index++)
+    for (int index = 0; index < MAX_MUSIC_STREAMS; index++)
     {
-        if (musicChannels_g[index].mixc) StopMusicStream(index);      // Stop music streaming and close current stream
+        if (musicStreams[index].mixc) StopMusicStream(index);      // Stop music streaming and close current stream
     }
 
     ALCdevice *device;
@@ -221,7 +232,7 @@ void CloseAudioDevice(void)
     alcCloseDevice(device);
 }
 
-// True if call to InitAudioDevice() was successful and CloseAudioDevice() has not been called yet
+// Check if device has been initialized successfully
 bool IsAudioDeviceReady(void)
 {
     ALCcontext *context = alcGetCurrentContext();
@@ -240,22 +251,22 @@ bool IsAudioDeviceReady(void)
 // Module Functions Definition - Custom audio output
 //----------------------------------------------------------------------------------
 
-// For streaming into mix channels.
-// The mixChannel is what audio muxing channel you want to operate on, 0-3 are the ones available. Each mix channel can only be used one at a time.
-// exmple usage is InitMixChannel(48000, 0, 2, true); // mixchannel 1, 48khz, stereo, floating point
-static MixChannel_t *InitMixChannel(unsigned short sampleRate, unsigned char mixChannel, unsigned char channels, bool floatingPoint)
+// Init mix channel for streaming
+// The mixChannel is what audio muxing channel you want to operate on, 0-3 are the ones available. 
+// Each mix channel can only be used one at a time.
+static MixChannel *InitMixChannel(unsigned short sampleRate, unsigned char mixChannel, unsigned char channels, bool floatingPoint)
 {
     if (mixChannel >= MAX_MIX_CHANNELS) return NULL;
     if (!IsAudioDeviceReady()) InitAudioDevice();
     
-    if (!mixChannels_g[mixChannel])
+    if (!mixChannels[mixChannel])
     {
-        MixChannel_t *mixc = (MixChannel_t *)malloc(sizeof(MixChannel_t));
+        MixChannel *mixc = (MixChannel *)malloc(sizeof(MixChannel));
         mixc->sampleRate = sampleRate;
         mixc->channels = channels;
         mixc->mixChannel = mixChannel;
         mixc->floatingPoint = floatingPoint;
-        mixChannels_g[mixChannel] = mixc;
+        mixChannels[mixChannel] = mixc;
         
         // Setup OpenAL format
         if (channels == 1)
@@ -280,7 +291,20 @@ static MixChannel_t *InitMixChannel(unsigned short sampleRate, unsigned char mix
         alGenBuffers(MAX_STREAM_BUFFERS, mixc->alBuffer);
         
         // Fill buffers
-        for (int i = 0; i < MAX_STREAM_BUFFERS; i++) FillAlBufferWithSilence(mixc, mixc->alBuffer[i]);
+        for (int i = 0; i < MAX_STREAM_BUFFERS; i++)
+        {
+            // Initialize buffer with zeros by default
+            if (mixc->floatingPoint)
+            {
+                float pcm[MUSIC_BUFFER_SIZE_FLOAT] = { 0.0f };
+                alBufferData(mixc->alBuffer[i], mixc->alFormat, pcm, MUSIC_BUFFER_SIZE_FLOAT*sizeof(float), mixc->sampleRate);
+            }
+            else
+            {
+                short pcm[MUSIC_BUFFER_SIZE_SHORT] = { 0 };
+                alBufferData(mixc->alBuffer[i], mixc->alFormat, pcm, MUSIC_BUFFER_SIZE_SHORT*sizeof(short), mixc->sampleRate);
+            }
+        }
         
         alSourceQueueBuffers(mixc->alSource, MAX_STREAM_BUFFERS, mixc->alBuffer);
         mixc->playing = true;
@@ -293,7 +317,7 @@ static MixChannel_t *InitMixChannel(unsigned short sampleRate, unsigned char mix
 }
 
 // Frees buffer in mix channel
-static void CloseMixChannel(MixChannel_t *mixc)
+static void CloseMixChannel(MixChannel *mixc)
 {
     if (mixc)
     {
@@ -314,18 +338,18 @@ static void CloseMixChannel(MixChannel_t *mixc)
         // Delete source and buffers
         alDeleteSources(1, &mixc->alSource);
         alDeleteBuffers(MAX_STREAM_BUFFERS, mixc->alBuffer);
-        mixChannels_g[mixc->mixChannel] = NULL;
+        mixChannels[mixc->mixChannel] = NULL;
         free(mixc);
         mixc = NULL;
     }
 }
 
-// Pushes more audio data into mixc mix channel, only one buffer per call
+// Pushes more audio data into mix channel, only one buffer per call
 // Call "BufferMixChannel(mixc, NULL, 0)" if you want to pause the audio.
-// @Returns number of samples that where processed.
-static int BufferMixChannel(MixChannel_t *mixc, void *data, int numberElements)
+// Returns number of samples that where processed.
+static int BufferMixChannel(MixChannel *mixc, void *data, int numberElements)
 {
-    if (!mixc || (mixChannels_g[mixc->mixChannel] != mixc)) return 0; // When there is two channels there must be an even number of samples
+    if (!mixc || (mixChannels[mixc->mixChannel] != mixc)) return 0; // When there is two channels there must be an even number of samples
     
     if (!data || !numberElements)   
     { 
@@ -368,28 +392,11 @@ static int BufferMixChannel(MixChannel_t *mixc, void *data, int numberElements)
     return numberElements;
 }
 
-// fill buffer with zeros, returns number processed
-static int FillAlBufferWithSilence(MixChannel_t *mixc, ALuint buffer)
-{
-    if (mixc->floatingPoint)
-    {
-        float pcm[MUSIC_BUFFER_SIZE_FLOAT] = { 0.0f };
-        alBufferData(buffer, mixc->alFormat, pcm, MUSIC_BUFFER_SIZE_FLOAT*sizeof(float), mixc->sampleRate);
-        
-        return MUSIC_BUFFER_SIZE_FLOAT;
-    }
-    else
-    {
-        short pcm[MUSIC_BUFFER_SIZE_SHORT] = { 0 };
-        alBufferData(buffer, mixc->alFormat, pcm, MUSIC_BUFFER_SIZE_SHORT*sizeof(short), mixc->sampleRate);
-        
-        return MUSIC_BUFFER_SIZE_SHORT;
-    }
-}
-
+/*
+// Convert data from short to float
 // example usage:
-// short sh[3] = {1,2,3};float fl[3];
-// ResampleShortToFloat(sh,fl,3);
+//      short sh[3] = {1,2,3};float fl[3];
+//      ResampleShortToFloat(sh,fl,3);
 static void ResampleShortToFloat(short *shorts, float *floats, unsigned short len)
 {
     for (int i = 0; i < len; i++)
@@ -399,9 +406,10 @@ static void ResampleShortToFloat(short *shorts, float *floats, unsigned short le
     }
 }
 
+// Convert data from float to short
 // example usage:
-// char ch[3] = {1,2,3};float fl[3];
-// ResampleByteToFloat(ch,fl,3);
+//      char ch[3] = {1,2,3};float fl[3];
+//      ResampleByteToFloat(ch,fl,3);
 static void ResampleByteToFloat(char *chars, float *floats, unsigned short len)
 {
     for (int i = 0; i < len; i++)
@@ -410,43 +418,55 @@ static void ResampleByteToFloat(char *chars, float *floats, unsigned short len)
         else floats[i] = (float)chars[i]/128.0f;
     }
 }
+*/
 
-// used to output raw audio streams, returns negative numbers on error, + number represents the mix channel index
-// if floating point is false the data size is 16bit short, otherwise it is float 32bit
-RawAudioContext InitRawAudioContext(int sampleRate, int channels, bool floatingPoint)
+// Initialize raw audio mix channel for audio buffering
+// NOTE: Returns mix channel index or -1 if it fails (errors are registered on lastAudioError)
+int InitRawMixChannel(int sampleRate, int channels, bool floatingPoint)
 {
     int mixIndex;
+
     for (mixIndex = 0; mixIndex < MAX_MIX_CHANNELS; mixIndex++) // find empty mix channel slot
     {
-        if (mixChannels_g[mixIndex] == NULL) break;
-        else if (mixIndex == (MAX_MIX_CHANNELS - 1)) return ERROR_OUT_OF_MIX_CHANNELS; // error
+        if (mixChannels[mixIndex] == NULL) break;
+        else if (mixIndex == (MAX_MIX_CHANNELS - 1))
+        {
+            lastAudioError = ERROR_OUT_OF_MIX_CHANNELS;
+            return -1;
+        }
     }
     
     if (InitMixChannel(sampleRate, mixIndex, channels, floatingPoint)) return mixIndex;
-    else return ERROR_RAW_CONTEXT_CREATION; // error
-}
-
-void CloseRawAudioContext(RawAudioContext ctx)
-{
-    if (mixChannels_g[ctx]) CloseMixChannel(mixChannels_g[ctx]);
+    else
+    {
+        lastAudioError = ERROR_RAW_CONTEXT_CREATION;
+        return -1;
+    }
 }
 
-// if 0 is returned, the buffers are still full and you need to keep trying with the same data until a + number is returned.
-// any + number returned is the number of samples that was processed and passed into buffer.
-// data either needs to be array of floats or shorts.
-int BufferRawAudioContext(RawAudioContext ctx, void *data, unsigned short numberElements)
+// Buffers data directly to raw mix channel
+// if 0 is returned, buffers are still full and you need to keep trying with the same data
+// otherwise it will return number of samples buffered.
+// NOTE: Data could be either be an array of floats or shorts, depending on the created context
+int BufferRawAudioContext(int ctx, void *data, unsigned short numberElements)
 {
     int numBuffered = 0;
     
     if (ctx >= 0)
     {
-        MixChannel_t* mixc = mixChannels_g[ctx];
+        MixChannel *mixc = mixChannels[ctx];
         numBuffered = BufferMixChannel(mixc, data, numberElements);
     }
     
     return numBuffered;
 }
 
+// Closes and frees raw mix channel
+void CloseRawAudioContext(int ctx)
+{
+    if (mixChannels[ctx]) CloseMixChannel(mixChannels[ctx]);
+}
+
 //----------------------------------------------------------------------------------
 // Module Functions Definition - Sounds loading and playing (.WAV)
 //----------------------------------------------------------------------------------
@@ -804,25 +824,25 @@ void SetSoundPitch(Sound sound, float pitch)
 //----------------------------------------------------------------------------------
 
 // Start music playing (open stream)
-// returns 0 on success
+// returns 0 on success or error code
 int PlayMusicStream(int index, char *fileName)
 {
     int mixIndex;
     
-    if (musicChannels_g[index].stream || musicChannels_g[index].xmctx) return ERROR_UNINITIALIZED_CHANNELS; // error
+    if (musicStreams[index].stream || musicStreams[index].xmctx) return ERROR_UNINITIALIZED_CHANNELS; // error
     
     for (mixIndex = 0; mixIndex < MAX_MIX_CHANNELS; mixIndex++) // find empty mix channel slot
     {
-        if (mixChannels_g[mixIndex] == NULL) break;
+        if (mixChannels[mixIndex] == NULL) break;
         else if (mixIndex == (MAX_MIX_CHANNELS - 1)) return ERROR_OUT_OF_MIX_CHANNELS; // error
     }
     
     if (strcmp(GetExtension(fileName),"ogg") == 0)
     {
         // Open audio stream
-        musicChannels_g[index].stream = stb_vorbis_open_filename(fileName, NULL, NULL);
+        musicStreams[index].stream = stb_vorbis_open_filename(fileName, NULL, NULL);
 
-        if (musicChannels_g[index].stream == NULL)
+        if (musicStreams[index].stream == NULL)
         {
             TraceLog(WARNING, "[%s] OGG audio file could not be opened", fileName);
             return ERROR_LOADING_OGG; // error
@@ -830,53 +850,53 @@ int PlayMusicStream(int index, char *fileName)
         else
         {
             // Get file info
-            stb_vorbis_info info = stb_vorbis_get_info(musicChannels_g[index].stream);
+            stb_vorbis_info info = stb_vorbis_get_info(musicStreams[index].stream);
 
             TraceLog(INFO, "[%s] Ogg sample rate: %i", fileName, info.sample_rate);
             TraceLog(INFO, "[%s] Ogg channels: %i", fileName, info.channels);
             TraceLog(DEBUG, "[%s] Temp memory required: %i", fileName, info.temp_memory_required);
 
-            musicChannels_g[index].loop = true;                  // We loop by default
-            musicChannels_g[index].enabled = true;
+            musicStreams[index].loop = true;                  // We loop by default
+            musicStreams[index].enabled = true;
             
 
-            musicChannels_g[index].totalSamplesLeft = (unsigned int)stb_vorbis_stream_length_in_samples(musicChannels_g[index].stream) * info.channels;
-            musicChannels_g[index].totalLengthSeconds = stb_vorbis_stream_length_in_seconds(musicChannels_g[index].stream);
+            musicStreams[index].totalSamplesLeft = (unsigned int)stb_vorbis_stream_length_in_samples(musicStreams[index].stream) * info.channels;
+            musicStreams[index].totalLengthSeconds = stb_vorbis_stream_length_in_seconds(musicStreams[index].stream);
             
             if (info.channels == 2)
             {
-                musicChannels_g[index].mixc = InitMixChannel(info.sample_rate, mixIndex, 2, false);
-                musicChannels_g[index].mixc->playing = true;
+                musicStreams[index].mixc = InitMixChannel(info.sample_rate, mixIndex, 2, false);
+                musicStreams[index].mixc->playing = true;
             }
             else
             {
-                musicChannels_g[index].mixc = InitMixChannel(info.sample_rate, mixIndex, 1, false);
-                musicChannels_g[index].mixc->playing = true;
+                musicStreams[index].mixc = InitMixChannel(info.sample_rate, mixIndex, 1, false);
+                musicStreams[index].mixc->playing = true;
             }
             
-            if (!musicChannels_g[index].mixc) return ERROR_LOADING_OGG; // error
+            if (!musicStreams[index].mixc) return ERROR_LOADING_OGG; // error
         }
     }
     else if (strcmp(GetExtension(fileName),"xm") == 0)
     {
         // only stereo is supported for xm
-        if (!jar_xm_create_context_from_file(&musicChannels_g[index].xmctx, 48000, fileName))
+        if (!jar_xm_create_context_from_file(&musicStreams[index].xmctx, 48000, fileName))
         {
-            musicChannels_g[index].chipTune = true;
-            musicChannels_g[index].loop = true;
-            jar_xm_set_max_loop_count(musicChannels_g[index].xmctx, 0); // infinite number of loops
-            musicChannels_g[index].totalSamplesLeft =  (unsigned int)jar_xm_get_remaining_samples(musicChannels_g[index].xmctx);
-            musicChannels_g[index].totalLengthSeconds = ((float)musicChannels_g[index].totalSamplesLeft) / 48000.f;
-            musicChannels_g[index].enabled = true;
+            musicStreams[index].chipTune = true;
+            musicStreams[index].loop = true;
+            jar_xm_set_max_loop_count(musicStreams[index].xmctx, 0); // infinite number of loops
+            musicStreams[index].totalSamplesLeft =  (unsigned int)jar_xm_get_remaining_samples(musicStreams[index].xmctx);
+            musicStreams[index].totalLengthSeconds = ((float)musicStreams[index].totalSamplesLeft)/48000.0f;
+            musicStreams[index].enabled = true;
             
-            TraceLog(INFO, "[%s] XM number of samples: %i", fileName, musicChannels_g[index].totalSamplesLeft);
-            TraceLog(INFO, "[%s] XM track length: %11.6f sec", fileName, musicChannels_g[index].totalLengthSeconds);
+            TraceLog(INFO, "[%s] XM number of samples: %i", fileName, musicStreams[index].totalSamplesLeft);
+            TraceLog(INFO, "[%s] XM track length: %11.6f sec", fileName, musicStreams[index].totalLengthSeconds);
             
-            musicChannels_g[index].mixc = InitMixChannel(48000, mixIndex, 2, true);
+            musicStreams[index].mixc = InitMixChannel(48000, mixIndex, 2, true);
             
-            if (!musicChannels_g[index].mixc) return ERROR_XM_CONTEXT_CREATION; // error
+            if (!musicStreams[index].mixc) return ERROR_XM_CONTEXT_CREATION; // error
             
-            musicChannels_g[index].mixc->playing = true;
+            musicStreams[index].mixc->playing = true;
         }
         else
         {
@@ -886,24 +906,24 @@ int PlayMusicStream(int index, char *fileName)
     }
     else if (strcmp(GetExtension(fileName),"mod") == 0)
     {
-        jar_mod_init(&musicChannels_g[index].modctx);
+        jar_mod_init(&musicStreams[index].modctx);
         
-        if (jar_mod_load_file(&musicChannels_g[index].modctx, fileName))
+        if (jar_mod_load_file(&musicStreams[index].modctx, fileName))
         {
-            musicChannels_g[index].chipTune = true;
-            musicChannels_g[index].loop = true;
-            musicChannels_g[index].totalSamplesLeft = (unsigned int)jar_mod_max_samples(&musicChannels_g[index].modctx);
-            musicChannels_g[index].totalLengthSeconds = ((float)musicChannels_g[index].totalSamplesLeft) / 48000.f;
-            musicChannels_g[index].enabled = true;
+            musicStreams[index].chipTune = true;
+            musicStreams[index].loop = true;
+            musicStreams[index].totalSamplesLeft = (unsigned int)jar_mod_max_samples(&musicStreams[index].modctx);
+            musicStreams[index].totalLengthSeconds = ((float)musicStreams[index].totalSamplesLeft)/48000.0f;
+            musicStreams[index].enabled = true;
             
-            TraceLog(INFO, "[%s] MOD number of samples: %i", fileName, musicChannels_g[index].totalSamplesLeft);
-            TraceLog(INFO, "[%s] MOD track length: %11.6f sec", fileName, musicChannels_g[index].totalLengthSeconds);
+            TraceLog(INFO, "[%s] MOD number of samples: %i", fileName, musicStreams[index].totalSamplesLeft);
+            TraceLog(INFO, "[%s] MOD track length: %11.6f sec", fileName, musicStreams[index].totalLengthSeconds);
             
-            musicChannels_g[index].mixc = InitMixChannel(48000, mixIndex, 2, false);
+            musicStreams[index].mixc = InitMixChannel(48000, mixIndex, 2, false);
             
-            if (!musicChannels_g[index].mixc) return ERROR_MOD_CONTEXT_CREATION; // error
+            if (!musicStreams[index].mixc) return ERROR_MOD_CONTEXT_CREATION; // error
             
-            musicChannels_g[index].mixc->playing = true;
+            musicStreams[index].mixc->playing = true;
         }
         else
         {
@@ -920,30 +940,75 @@ int PlayMusicStream(int index, char *fileName)
     return 0; // normal return
 }
 
-// Stop music playing for individual music index of musicChannels_g array (close stream)
+// Stop music playing for individual music index of musicStreams array (close stream)
 void StopMusicStream(int index)
 {
-    if (index < MAX_MUSIC_STREAMS && musicChannels_g[index].mixc)
+    if (index < MAX_MUSIC_STREAMS && musicStreams[index].mixc)
     {
-        CloseMixChannel(musicChannels_g[index].mixc);
+        CloseMixChannel(musicStreams[index].mixc);
         
-        if (musicChannels_g[index].xmctx)
-            jar_xm_free_context(musicChannels_g[index].xmctx);
-        else if (musicChannels_g[index].modctx.mod_loaded)
-            jar_mod_unload(&musicChannels_g[index].modctx);
+        if (musicStreams[index].xmctx)
+            jar_xm_free_context(musicStreams[index].xmctx);
+        else if (musicStreams[index].modctx.mod_loaded)
+            jar_mod_unload(&musicStreams[index].modctx);
         else
-            stb_vorbis_close(musicChannels_g[index].stream);
+            stb_vorbis_close(musicStreams[index].stream);
         
-        musicChannels_g[index].enabled = false;
+        musicStreams[index].enabled = false;
         
-        if (musicChannels_g[index].stream || musicChannels_g[index].xmctx)
+        if (musicStreams[index].stream || musicStreams[index].xmctx)
         {
-            musicChannels_g[index].stream = NULL;
-            musicChannels_g[index].xmctx = NULL;
+            musicStreams[index].stream = NULL;
+            musicStreams[index].xmctx = NULL;
         }
     }
 }
 
+// Update (re-fill) music buffers if data already processed
+void UpdateMusicStream(int index)
+{
+    ALenum state;
+    bool active = true;
+    ALint processed = 0;
+    
+    // Determine if music stream is ready to be written
+    alGetSourcei(musicStreams[index].mixc->alSource, AL_BUFFERS_PROCESSED, &processed);
+    
+    if (musicStreams[index].mixc->playing && (index < MAX_MUSIC_STREAMS) && musicStreams[index].enabled && musicStreams[index].mixc && (processed > 0))
+    {
+        active = BufferMusicStream(index, processed);
+        
+        if (!active && musicStreams[index].loop)
+        {
+            if (musicStreams[index].chipTune)
+            {
+                if(musicStreams[index].modctx.mod_loaded) jar_mod_seek_start(&musicStreams[index].modctx);
+                
+                musicStreams[index].totalSamplesLeft = musicStreams[index].totalLengthSeconds*48000.0f;
+            }
+            else
+            {
+                stb_vorbis_seek_start(musicStreams[index].stream);
+                musicStreams[index].totalSamplesLeft = stb_vorbis_stream_length_in_samples(musicStreams[index].stream)*musicStreams[index].mixc->channels;
+            }
+            
+            // Determine if music stream is ready to be written
+            alGetSourcei(musicStreams[index].mixc->alSource, AL_BUFFERS_PROCESSED, &processed);
+            
+            active = BufferMusicStream(index, processed);
+        }
+
+        if (alGetError() != AL_NO_ERROR) TraceLog(WARNING, "Error buffering data...");
+        
+        alGetSourcei(musicStreams[index].mixc->alSource, AL_SOURCE_STATE, &state);
+
+        if (state != AL_PLAYING && active) alSourcePlay(musicStreams[index].mixc->alSource);
+
+        if (!active) StopMusicStream(index);
+        
+    }
+}
+
 //get number of music channels active at this time, this does not mean they are playing
 int GetMusicStreamCount(void)
 {
@@ -952,7 +1017,7 @@ int GetMusicStreamCount(void)
     // Find empty music slot
     for (int musicIndex = 0; musicIndex < MAX_MUSIC_STREAMS; musicIndex++)
     {
-        if(musicChannels_g[musicIndex].stream != NULL || musicChannels_g[musicIndex].chipTune) musicCount++;
+        if(musicStreams[musicIndex].stream != NULL || musicStreams[musicIndex].chipTune) musicCount++;
     }
     
     return musicCount;
@@ -962,11 +1027,11 @@ int GetMusicStreamCount(void)
 void PauseMusicStream(int index)
 {
     // Pause music stream if music available!
-    if (index < MAX_MUSIC_STREAMS && musicChannels_g[index].mixc && musicChannels_g[index].enabled)
+    if (index < MAX_MUSIC_STREAMS && musicStreams[index].mixc && musicStreams[index].enabled)
     {
         TraceLog(INFO, "Pausing music stream");
-        alSourcePause(musicChannels_g[index].mixc->alSource);
-        musicChannels_g[index].mixc->playing = false;
+        alSourcePause(musicStreams[index].mixc->alSource);
+        musicStreams[index].mixc->playing = false;
     }
 }
 
@@ -976,15 +1041,15 @@ void ResumeMusicStream(int index)
     // Resume music playing... if music available!
     ALenum state;
     
-    if (index < MAX_MUSIC_STREAMS && musicChannels_g[index].mixc)
+    if (index < MAX_MUSIC_STREAMS && musicStreams[index].mixc)
     {
-        alGetSourcei(musicChannels_g[index].mixc->alSource, AL_SOURCE_STATE, &state);
+        alGetSourcei(musicStreams[index].mixc->alSource, AL_SOURCE_STATE, &state);
         
         if (state == AL_PAUSED)
         {
             TraceLog(INFO, "Resuming music stream");
-            alSourcePlay(musicChannels_g[index].mixc->alSource);
-            musicChannels_g[index].mixc->playing = true;
+            alSourcePlay(musicStreams[index].mixc->alSource);
+            musicStreams[index].mixc->playing = true;
         }
     }
 }
@@ -995,9 +1060,9 @@ bool IsMusicPlaying(int index)
     bool playing = false;
     ALint state;
     
-    if (index < MAX_MUSIC_STREAMS && musicChannels_g[index].mixc)
+    if (index < MAX_MUSIC_STREAMS && musicStreams[index].mixc)
     {
-        alGetSourcei(musicChannels_g[index].mixc->alSource, AL_SOURCE_STATE, &state);
+        alGetSourcei(musicStreams[index].mixc->alSource, AL_SOURCE_STATE, &state);
         
         if (state == AL_PLAYING) playing = true;
     }
@@ -1008,18 +1073,18 @@ bool IsMusicPlaying(int index)
 // Set volume for music
 void SetMusicVolume(int index, float volume)
 {
-    if (index < MAX_MUSIC_STREAMS && musicChannels_g[index].mixc)
+    if (index < MAX_MUSIC_STREAMS && musicStreams[index].mixc)
     {
-        alSourcef(musicChannels_g[index].mixc->alSource, AL_GAIN, volume);
+        alSourcef(musicStreams[index].mixc->alSource, AL_GAIN, volume);
     }
 }
 
 // Set pitch for music
 void SetMusicPitch(int index, float pitch)
 {
-    if (index < MAX_MUSIC_STREAMS && musicChannels_g[index].mixc)
+    if (index < MAX_MUSIC_STREAMS && musicStreams[index].mixc)
     {
-        alSourcef(musicChannels_g[index].mixc->alSource, AL_PITCH, pitch);
+        alSourcef(musicStreams[index].mixc->alSource, AL_PITCH, pitch);
     }
 }
 
@@ -1028,8 +1093,8 @@ float GetMusicTimeLength(int index)
 {
     float totalSeconds;
     
-    if (musicChannels_g[index].chipTune) totalSeconds = (float)musicChannels_g[index].totalLengthSeconds;
-    else totalSeconds = stb_vorbis_stream_length_in_seconds(musicChannels_g[index].stream);
+    if (musicStreams[index].chipTune) totalSeconds = (float)musicStreams[index].totalLengthSeconds;
+    else totalSeconds = stb_vorbis_stream_length_in_seconds(musicStreams[index].stream);
 
     return totalSeconds;
 }
@@ -1039,24 +1104,24 @@ float GetMusicTimePlayed(int index)
 {
     float secondsPlayed = 0.0f;
     
-    if (index < MAX_MUSIC_STREAMS && musicChannels_g[index].mixc)
+    if (index < MAX_MUSIC_STREAMS && musicStreams[index].mixc)
     {
-        if (musicChannels_g[index].chipTune && musicChannels_g[index].xmctx)
+        if (musicStreams[index].chipTune && musicStreams[index].xmctx)
         {
             uint64_t samples;
-            jar_xm_get_position(musicChannels_g[index].xmctx, NULL, NULL, NULL, &samples);
-            secondsPlayed = (float)samples / (48000.f * musicChannels_g[index].mixc->channels); // Not sure if this is the correct value
+            jar_xm_get_position(musicStreams[index].xmctx, NULL, NULL, NULL, &samples);
+            secondsPlayed = (float)samples/(48000.0f*musicStreams[index].mixc->channels); // Not sure if this is the correct value
         }
-        else if(musicChannels_g[index].chipTune && musicChannels_g[index].modctx.mod_loaded)
+        else if(musicStreams[index].chipTune && musicStreams[index].modctx.mod_loaded)
         {
-            long numsamp = jar_mod_current_samples(&musicChannels_g[index].modctx);
-            secondsPlayed = (float)numsamp / (48000.f);
+            long numsamp = jar_mod_current_samples(&musicStreams[index].modctx);
+            secondsPlayed = (float)numsamp/(48000.0f);
         }
         else
         {
-            int totalSamples = stb_vorbis_stream_length_in_samples(musicChannels_g[index].stream) * musicChannels_g[index].mixc->channels;
-            int samplesPlayed = totalSamples - musicChannels_g[index].totalSamplesLeft;
-            secondsPlayed = (float)samplesPlayed / (musicChannels_g[index].mixc->sampleRate * musicChannels_g[index].mixc->channels);
+            int totalSamples = stb_vorbis_stream_length_in_samples(musicStreams[index].stream)*musicStreams[index].mixc->channels;
+            int samplesPlayed = totalSamples - musicStreams[index].totalSamplesLeft;
+            secondsPlayed = (float)samplesPlayed/(musicStreams[index].mixc->sampleRate*musicStreams[index].mixc->channels);
         }
     }
 
@@ -1076,30 +1141,30 @@ static bool BufferMusicStream(int index, int numBuffers)
     int size = 0;              // Total size of data steamed in L+R samples for xm floats, individual L or R for ogg shorts
     bool active = true;        // We can get more data from stream (not finished)
     
-    if (musicChannels_g[index].chipTune) // There is no end of stream for xmfiles, once the end is reached zeros are generated for non looped chiptunes.
+    if (musicStreams[index].chipTune) // There is no end of stream for xmfiles, once the end is reached zeros are generated for non looped chiptunes.
     {
         for (int i = 0; i < numBuffers; i++)
         {
-            if (musicChannels_g[index].modctx.mod_loaded)
+            if (musicStreams[index].modctx.mod_loaded)
             {
-                if (musicChannels_g[index].totalSamplesLeft >= MUSIC_BUFFER_SIZE_SHORT) size = MUSIC_BUFFER_SIZE_SHORT/2;
-                else size = musicChannels_g[index].totalSamplesLeft/2;
+                if (musicStreams[index].totalSamplesLeft >= MUSIC_BUFFER_SIZE_SHORT) size = MUSIC_BUFFER_SIZE_SHORT/2;
+                else size = musicStreams[index].totalSamplesLeft/2;
                 
-                jar_mod_fillbuffer(&musicChannels_g[index].modctx, pcm, size, 0 );
-                BufferMixChannel(musicChannels_g[index].mixc, pcm, size*2);
+                jar_mod_fillbuffer(&musicStreams[index].modctx, pcm, size, 0 );
+                BufferMixChannel(musicStreams[index].mixc, pcm, size*2);
             }
-            else if (musicChannels_g[index].xmctx)
+            else if (musicStreams[index].xmctx)
             {
-                if (musicChannels_g[index].totalSamplesLeft >= MUSIC_BUFFER_SIZE_FLOAT) size = MUSIC_BUFFER_SIZE_FLOAT/2;
-                else size = musicChannels_g[index].totalSamplesLeft/2;
+                if (musicStreams[index].totalSamplesLeft >= MUSIC_BUFFER_SIZE_FLOAT) size = MUSIC_BUFFER_SIZE_FLOAT/2;
+                else size = musicStreams[index].totalSamplesLeft/2;
                 
-                jar_xm_generate_samples(musicChannels_g[index].xmctx, pcmf, size); // reads 2*readlen shorts and moves them to buffer+size memory location
-                BufferMixChannel(musicChannels_g[index].mixc, pcmf, size*2);
+                jar_xm_generate_samples(musicStreams[index].xmctx, pcmf, size); // reads 2*readlen shorts and moves them to buffer+size memory location
+                BufferMixChannel(musicStreams[index].mixc, pcmf, size*2);
             }
 
-            musicChannels_g[index].totalSamplesLeft -= size;
+            musicStreams[index].totalSamplesLeft -= size;
             
-            if (musicChannels_g[index].totalSamplesLeft <= 0)
+            if (musicStreams[index].totalSamplesLeft <= 0)
             {
                 active = false;
                 break;
@@ -1108,16 +1173,16 @@ static bool BufferMusicStream(int index, int numBuffers)
     }
     else
     {
-        if (musicChannels_g[index].totalSamplesLeft >= MUSIC_BUFFER_SIZE_SHORT) size = MUSIC_BUFFER_SIZE_SHORT;
-        else size = musicChannels_g[index].totalSamplesLeft;
+        if (musicStreams[index].totalSamplesLeft >= MUSIC_BUFFER_SIZE_SHORT) size = MUSIC_BUFFER_SIZE_SHORT;
+        else size = musicStreams[index].totalSamplesLeft;
         
         for (int i = 0; i < numBuffers; i++)
         {
-            int streamedBytes = stb_vorbis_get_samples_short_interleaved(musicChannels_g[index].stream, musicChannels_g[index].mixc->channels, pcm, size);
-            BufferMixChannel(musicChannels_g[index].mixc, pcm, streamedBytes * musicChannels_g[index].mixc->channels);
-            musicChannels_g[index].totalSamplesLeft -= streamedBytes * musicChannels_g[index].mixc->channels;
+            int streamedBytes = stb_vorbis_get_samples_short_interleaved(musicStreams[index].stream, musicStreams[index].mixc->channels, pcm, size);
+            BufferMixChannel(musicStreams[index].mixc, pcm, streamedBytes * musicStreams[index].mixc->channels);
+            musicStreams[index].totalSamplesLeft -= streamedBytes * musicStreams[index].mixc->channels;
             
-            if (musicChannels_g[index].totalSamplesLeft <= 0)
+            if (musicStreams[index].totalSamplesLeft <= 0)
             {
                 active = false;
                 break;
@@ -1134,63 +1199,16 @@ static void EmptyMusicStream(int index)
     ALuint buffer = 0;
     int queued = 0;
 
-    alGetSourcei(musicChannels_g[index].mixc->alSource, AL_BUFFERS_QUEUED, &queued);
+    alGetSourcei(musicStreams[index].mixc->alSource, AL_BUFFERS_QUEUED, &queued);
 
     while (queued > 0)
     {
-        alSourceUnqueueBuffers(musicChannels_g[index].mixc->alSource, 1, &buffer);
+        alSourceUnqueueBuffers(musicStreams[index].mixc->alSource, 1, &buffer);
 
         queued--;
     }
 }
 
-// Determine if a music stream is ready to be written
-static int IsMusicStreamReadyForBuffering(int index)
-{
-    ALint processed = 0;
-    alGetSourcei(musicChannels_g[index].mixc->alSource, AL_BUFFERS_PROCESSED, &processed);
-    return processed;
-}
-
-// Update (re-fill) music buffers if data already processed
-void UpdateMusicStream(int index)
-{
-    ALenum state;
-    bool active = true;
-    int numBuffers = IsMusicStreamReadyForBuffering(index);
-    
-    if (musicChannels_g[index].mixc->playing && (index < MAX_MUSIC_STREAMS) && musicChannels_g[index].enabled && musicChannels_g[index].mixc && numBuffers)
-    {
-        active = BufferMusicStream(index, numBuffers);
-        
-        if (!active && musicChannels_g[index].loop)
-        {
-            if (musicChannels_g[index].chipTune)
-            {
-                if(musicChannels_g[index].modctx.mod_loaded) jar_mod_seek_start(&musicChannels_g[index].modctx);
-                
-                musicChannels_g[index].totalSamplesLeft = musicChannels_g[index].totalLengthSeconds * 48000.f;
-            }
-            else
-            {
-                stb_vorbis_seek_start(musicChannels_g[index].stream);
-                musicChannels_g[index].totalSamplesLeft = stb_vorbis_stream_length_in_samples(musicChannels_g[index].stream) * musicChannels_g[index].mixc->channels;
-            }
-            
-            active = BufferMusicStream(index, IsMusicStreamReadyForBuffering(index));
-        }
-
-        if (alGetError() != AL_NO_ERROR) TraceLog(WARNING, "Error buffering data...");
-        
-        alGetSourcei(musicChannels_g[index].mixc->alSource, AL_SOURCE_STATE, &state);
-
-        if (state != AL_PLAYING && active) alSourcePlay(musicChannels_g[index].mixc->alSource);
-
-        if (!active) StopMusicStream(index);
-        
-    }
-}
-
 // Load WAV file into Wave structure
 static Wave LoadWAV(const char *fileName)
 {

+ 25 - 19
src/audio.h

@@ -2,13 +2,26 @@
 *
 *   raylib.audio
 *
-*   Basic functions to manage Audio: InitAudioDevice, LoadAudioFiles, PlayAudioFiles
+*   Basic functions to manage Audio: 
+*       Manage audio device (init/close)
+*       Load and Unload audio files
+*       Play/Stop/Pause/Resume loaded audio
+*       Manage mixing channels
+*       Manage raw audio context
 *
 *   Uses external lib:
 *       OpenAL Soft - Audio device management lib (http://kcat.strangesoft.net/openal.html)
 *       stb_vorbis - Ogg audio files loading (http://www.nothings.org/stb_vorbis/)
+*       jar_xm - XM module file loading
+*       jar_mod - MOD audio file loading
 *
-*   Copyright (c) 2015 Ramon Santamaria (@raysan5)
+*   Many thanks to Joshua Reisenauer (github: @kd7tck) for the following additions:
+*       XM audio module support (jar_xm)
+*       MOD audio module support (jar_mod)
+*       Mixing channels support
+*       Raw audio context support
+*
+*   Copyright (c) 2014-2016 Ramon Santamaria (@raysan5)
 *
 *   This software is provided "as-is", without any express or implied warranty. In no event
 *   will the authors be held liable for any damages arising from the use of this software.
@@ -49,23 +62,19 @@
 
 // Sound source type
 typedef struct Sound {
-    unsigned int source;
-    unsigned int buffer;
-    AudioError error; // if there was any error during the creation or use of this Sound
+    unsigned int source;    // Sound audio source id
+    unsigned int buffer;    // Sound audio buffer id
 } Sound;
 
 // Wave type, defines audio wave data
 typedef struct Wave {
     void *data;                 // Buffer data pointer
     unsigned int dataSize;      // Data size in bytes
-    unsigned int sampleRate;
-    short bitsPerSample;
+    unsigned int sampleRate;    // Samples per second to be played
+    short bitsPerSample;        // Sample size in bits
     short channels;
 } Wave;
 
-typedef int RawAudioContext;
-
-
 #ifdef __cplusplus
 extern "C" {            // Prevents name mangling of functions
 #endif
@@ -80,7 +89,7 @@ extern "C" {            // Prevents name mangling of functions
 //----------------------------------------------------------------------------------
 void InitAudioDevice(void);                                     // Initialize audio device and context
 void CloseAudioDevice(void);                                    // Close the audio device and context (and music stream)
-bool IsAudioDeviceReady(void);                                  // True if call to InitAudioDevice() was successful and CloseAudioDevice() has not been called yet
+bool IsAudioDeviceReady(void);                                  // Check if device has been initialized successfully
 
 Sound LoadSound(char *fileName);                                // Load sound to memory
 Sound LoadSoundFromWave(Wave wave);                             // Load sound to memory from wave data
@@ -100,17 +109,14 @@ void PauseMusicStream(int index);                               // Pause music p
 void ResumeMusicStream(int index);                              // Resume playing paused music
 bool IsMusicPlaying(int index);                                 // Check if music is playing
 void SetMusicVolume(int index, float volume);                   // Set volume for music (1.0 is max level)
+void SetMusicPitch(int index, float pitch);                     // Set pitch for a music (1.0 is base level)
 float GetMusicTimeLength(int index);                            // Get music time length (in seconds)
 float GetMusicTimePlayed(int index);                            // Get current music time played (in seconds)
-int GetMusicStreamCount(void);
-void SetMusicPitch(int index, float pitch);
-
-// used to output raw audio streams, returns negative numbers on error
-// if floating point is false the data size is 16bit short, otherwise it is float 32bit
-RawAudioContext InitRawAudioContext(int sampleRate, int channels, bool floatingPoint);
+int GetMusicStreamCount(void);                                  // Get number of streams loaded
 
-void CloseRawAudioContext(RawAudioContext ctx);
-int BufferRawAudioContext(RawAudioContext ctx, void *data, unsigned short numberElements); // returns number of elements buffered
+int InitRawMixChannel(int sampleRate, int channels, bool floatingPoint);        // Initialize raw audio mix channel for audio buffering
+int BufferRawMixChannel(int mixc, void *data, unsigned short numberElements);   // Buffers data directly to raw mix channel
+void CloseRawMixChannel(int mixc);                                              // Closes and frees raw mix channel
 
 #ifdef __cplusplus
 }

+ 5 - 6
src/core.c

@@ -181,11 +181,10 @@ static uint64_t baseTime;               // Base time measure for hi-res timer
 static bool windowShouldClose = false;  // Flag to set window for closing
 #endif
 
-static unsigned int displayWidth, displayHeight;     // Display width and height (monitor, device-screen, LCD, ...)
+// Display size-related data
+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)
-                                            // NOTE: Framebuffer could include black bars
-
+static int renderWidth, renderHeight;       // Framebuffer width and height (render area, including black bars if required)
 static int renderOffsetX = 0;               // Offset X from render area (must be divided by 2)
 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)
@@ -214,7 +213,7 @@ static bool cursorHidden;                   // Track if cursor is hidden
 #endif
 
 static Vector2 mousePosition;               // Mouse position on screen
-static Vector2 touchPosition[MAX_TOUCH_POINTS];     // Touch position on screen
+static Vector2 touchPosition[MAX_TOUCH_POINTS]; // Touch position on screen
 
 #if defined(PLATFORM_DESKTOP)
 static char **dropFilesPath;                // Store dropped files paths as strings
@@ -226,7 +225,7 @@ static double updateTime, drawTime;         // Time measures for update and draw
 static double frameTime;                    // Time measure for one frame
 static double targetTime = 0.0;             // Desired time for one frame, if 0 not applied
 
-static char configFlags = 0;                // Configuration flags (bit  based)
+static char configFlags = 0;                // Configuration flags (bit based)
 static bool showLogo = false;               // Track if showing logo at init is enabled
 
 //----------------------------------------------------------------------------------

+ 3 - 12
src/raylib.h

@@ -431,8 +431,8 @@ typedef struct Model {
 // Light type
 typedef struct LightData {
     unsigned int id;        // Light unique id
-    int type;               // Light type: LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT
     bool enabled;           // Light enabled
+    int type;               // Light type: LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT
     
     Vector3 position;       // Light position
     Vector3 target;         // Light target: LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target)
@@ -468,8 +468,6 @@ typedef struct Wave {
     short channels;
 } Wave;
 
-typedef int RawAudioContext;
-
 // Texture formats
 // NOTE: Support depends on OpenGL version and platform
 typedef enum {
@@ -895,17 +893,10 @@ void PauseMusicStream(int index);                               // Pause music p
 void ResumeMusicStream(int index);                              // Resume playing paused music
 bool IsMusicPlaying(int index);                                 // Check if music is playing
 void SetMusicVolume(int index, float volume);                   // Set volume for music (1.0 is max level)
+void SetMusicPitch(int index, float pitch);                     // Set pitch for a music (1.0 is base level)
 float GetMusicTimeLength(int index);                            // Get current music time length (in seconds)
 float GetMusicTimePlayed(int index);                            // Get current music time played (in seconds)
-int GetMusicStreamCount(void);
-void SetMusicPitch(int index, float pitch);
-
-// used to output raw audio streams, returns negative numbers on error
-// if floating point is false the data size is 16bit short, otherwise it is float 32bit
-RawAudioContext InitRawAudioContext(int sampleRate, int channels, bool floatingPoint);
-
-void CloseRawAudioContext(RawAudioContext ctx);
-int BufferRawAudioContext(RawAudioContext ctx, void *data, unsigned short numberElements); // returns number of elements buffered
+int GetMusicStreamCount(void);                                  // Get number of streams loaded
 
 #ifdef __cplusplus
 }

ファイルの差分が大きいため隠しています
+ 426 - 339
src/rlgl.c


+ 23 - 2
src/rlgl.h

@@ -218,9 +218,9 @@ typedef enum { OPENGL_11 = 1, OPENGL_21, OPENGL_33, OPENGL_ES_20 } GlVersion;
     // Light type
     typedef struct LightData {
         unsigned int id;        // Light unique id
-        int type;               // Light type: LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT
         bool enabled;           // Light enabled
-        
+        int type;               // Light type: LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT
+
         Vector3 position;       // Light position
         Vector3 target;         // Light target: LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target)
         float radius;           // Light attenuation radius light intensity reduced with distance (world distance)
@@ -239,6 +239,19 @@ typedef enum { OPENGL_11 = 1, OPENGL_21, OPENGL_33, OPENGL_ES_20 } GlVersion;
     
     // TraceLog message types
     typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType;
+    
+    // Head Mounted Display devices
+    typedef enum {
+        HMD_DEFAULT_DEVICE = 0,
+        HMD_OCULUS_RIFT_DK2,
+        HMD_OCULUS_RIFT_CV1,
+        HMD_VALVE_HTC_VIVE,
+        HMD_SAMSUNG_GEAR_VR,
+        HMD_GOOGLE_CARDBOARD,
+        HMD_SONY_PLAYSTATION_VR,
+        HMD_RAZER_OSVR,
+        HMD_FOVE_VR,
+    } HmdDevice;
 #endif
 
 #ifdef __cplusplus
@@ -350,6 +363,7 @@ Light CreateLight(int type, Vector3 position, Color diffuse);       // Create a
 void DestroyLight(Light light);                                     // Destroy a light and take it out of the list
 
 void TraceLog(int msgType, const char *text, ...);
+float *MatrixToFloat(Matrix mat);
 
 void InitVrDevice(int hmdDevice);           // Init VR device
 void CloseVrDevice(void);                   // Close VR device
@@ -358,6 +372,13 @@ void BeginVrDrawing(void);                  // Begin VR drawing configuration
 void EndVrDrawing(void);                    // End VR drawing process (and desktop mirror)
 bool IsVrDeviceReady(void);                 // Detect if VR device (or simulator) is ready
 void ToggleVrMode(void);                    // Enable/Disable VR experience (device or simulator)
+
+// Oculus Rift API for direct access the device (no simulator)
+bool InitOculusDevice(void);                // Initialize Oculus device (returns true if success)
+void CloseOculusDevice(void);               // Close Oculus device
+void UpdateOculusTracking(void);            // Update Oculus head position-orientation tracking
+void BeginOculusDrawing(void);              // Setup Oculus buffers for drawing
+void EndOculusDrawing(void);                // Finish Oculus drawing and blit framebuffer to mirror
 #endif
 
 #ifdef __cplusplus

+ 106 - 0
src/shader_distortion.h

@@ -0,0 +1,106 @@
+
+// Vertex shader definition to embed, no external file required
+static const char vDistortionShaderStr[] = 
+#if defined(GRAPHICS_API_OPENGL_21)
+"#version 120                       \n"
+#elif defined(GRAPHICS_API_OPENGL_ES2)
+"#version 100                       \n"
+#endif
+#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21)
+"attribute vec3 vertexPosition;     \n"
+"attribute vec2 vertexTexCoord;     \n"
+"attribute vec4 vertexColor;        \n"
+"varying vec2 fragTexCoord;         \n"
+"varying vec4 fragColor;            \n"
+#elif defined(GRAPHICS_API_OPENGL_33)
+"#version 330                       \n"
+"in vec3 vertexPosition;            \n"
+"in vec2 vertexTexCoord;            \n"
+"in vec4 vertexColor;               \n"
+"out vec2 fragTexCoord;             \n"
+"out vec4 fragColor;                \n"
+#endif
+"uniform mat4 mvpMatrix;            \n"
+"void main()                        \n"
+"{                                  \n"
+"    fragTexCoord = vertexTexCoord; \n"
+"    fragColor = vertexColor;       \n"
+"    gl_Position = mvpMatrix*vec4(vertexPosition, 1.0); \n"
+"}                                  \n";
+
+// Fragment shader definition to embed, no external file required
+static const char fDistortionShaderStr[] = 
+#if defined(GRAPHICS_API_OPENGL_21)
+"#version 120                       \n"
+#elif defined(GRAPHICS_API_OPENGL_ES2)
+"#version 100                       \n"
+"precision mediump float;           \n"     // precision required for OpenGL ES2 (WebGL)
+#endif
+#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21)
+"varying vec2 fragTexCoord;         \n"
+"varying vec4 fragColor;            \n"
+#elif defined(GRAPHICS_API_OPENGL_33)
+"#version 330                       \n"
+"in vec2 fragTexCoord;              \n"
+"in vec4 fragColor;                 \n"
+"out vec4 finalColor;               \n"
+#endif
+"uniform sampler2D texture0;                                     \n"
+#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21)
+"uniform vec2 leftLensCenter;       \n"
+"uniform vec2 rightLensCenter;      \n"
+"uniform vec2 leftScreenCenter;     \n"
+"uniform vec2 rightScreenCenter;    \n"
+"uniform vec2 scale;                \n"
+"uniform vec2 scaleIn;              \n"
+"uniform vec4 hmdWarpParam;         \n"
+"uniform vec4 chromaAbParam;        \n"
+#elif defined(GRAPHICS_API_OPENGL_33)
+"uniform vec2 leftLensCenter = vec2(0.288, 0.5);                 \n"
+"uniform vec2 rightLensCenter = vec2(0.712, 0.5);                \n"
+"uniform vec2 leftScreenCenter = vec2(0.25, 0.5);                \n"
+"uniform vec2 rightScreenCenter = vec2(0.75, 0.5);               \n"
+"uniform vec2 scale = vec2(0.25, 0.45);                          \n"
+"uniform vec2 scaleIn = vec2(4, 2.2222);                         \n"
+"uniform vec4 hmdWarpParam = vec4(1, 0.22, 0.24, 0);             \n"
+"uniform vec4 chromaAbParam = vec4(0.996, -0.004, 1.014, 0.0);   \n"
+#endif
+"void main() \n"
+"{ \n"
+"   vec2 lensCenter = fragTexCoord.x < 0.5 ? leftLensCenter : rightLensCenter; \n"
+"   vec2 screenCenter = fragTexCoord.x < 0.5 ? leftScreenCenter : rightScreenCenter; \n"
+"   vec2 theta = (fragTexCoord - lensCenter)*scaleIn; \n"
+"   float rSq = theta.x*theta.x + theta.y*theta.y; \n"
+"   vec2 theta1 = theta*(hmdWarpParam.x + hmdWarpParam.y*rSq + hmdWarpParam.z*rSq*rSq + hmdWarpParam.w*rSq*rSq*rSq); \n"
+"   vec2 thetaBlue = theta1*(chromaAbParam.z + chromaAbParam.w*rSq); \n"
+"   vec2 tcBlue = lensCenter + scale*thetaBlue; \n"
+"   if (any(bvec2(clamp(tcBlue, screenCenter - vec2(0.25, 0.5), screenCenter + vec2(0.25, 0.5)) - tcBlue))) \n"
+"   { \n"
+#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21)
+"       gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); \n"
+#elif defined(GRAPHICS_API_OPENGL_33)
+"       finalColor = vec4(0.0, 0.0, 0.0, 1.0); \n"
+#endif
+"   } \n"
+"   else \n"
+"   { \n"
+#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21)
+"       float blue = texture2D(texture0, tcBlue).b; \n"
+"       vec2 tcGreen = lensCenter + scale*theta1; \n"
+"       float green = texture2D(texture0, tcGreen).g; \n"
+#elif defined(GRAPHICS_API_OPENGL_33)
+"       float blue = texture(texture0, tcBlue).b; \n"
+"       vec2 tcGreen = lensCenter + scale*theta1; \n"
+"       float green = texture(texture0, tcGreen).g; \n"
+#endif
+"       vec2 thetaRed = theta1*(chromaAbParam.x + chromaAbParam.y*rSq); \n"
+"       vec2 tcRed = lensCenter + scale*thetaRed; \n"
+#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21)
+"       float red = texture2D(texture0, tcRed).r; \n"
+"       gl_FragColor = vec4(red, green, blue, 1.0); \n"
+#elif defined(GRAPHICS_API_OPENGL_33)
+"       float red = texture(texture0, tcRed).r; \n"
+"       finalColor = vec4(red, green, blue, 1.0); \n"
+#endif
+"    } \n"
+"} \n";

+ 1 - 2
src/standard_shader.h → src/shader_standard.h

@@ -78,7 +78,6 @@ static const char fStandardShaderStr[] =
 "    float radius;                  \n"
 "    float coneAngle; };            \n"
 "const int maxLights = 8;           \n"
-"uniform int lightsCount;           \n"
 "uniform Light lights[maxLights];   \n"
 "\n"  
 "vec3 CalcPointLight(Light l, vec3 n, vec3 v, float s)   \n"
@@ -157,7 +156,7 @@ static const char fStandardShaderStr[] =
 #elif defined(GRAPHICS_API_OPENGL_33)
 "    if (useSpecular == 1) spec *= normalize(texture(texture2, fragTexCoord).r);\n"
 #endif
-"    for (int i = 0; i < lightsCount; i++)\n"
+"    for (int i = 0; i < maxLights; i++)\n"
 "    {\n"
 "        if (lights[i].enabled == 1)\n"
 "        {\n"

+ 23 - 6
src/shapes.c

@@ -276,12 +276,29 @@ void DrawRectangleLines(int posX, int posY, int width, int height, Color color)
 // Draw a triangle
 void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color)
 {
-    rlBegin(RL_TRIANGLES);
-        rlColor4ub(color.r, color.g, color.b, color.a);
-        rlVertex2f(v1.x, v1.y);
-        rlVertex2f(v2.x, v2.y);
-        rlVertex2f(v3.x, v3.y);
-    rlEnd();
+    if (rlGetVersion() == OPENGL_11)
+    {
+        rlBegin(RL_TRIANGLES);
+            rlColor4ub(color.r, color.g, color.b, color.a);
+            rlVertex2f(v1.x, v1.y);
+            rlVertex2f(v2.x, v2.y);
+            rlVertex2f(v3.x, v3.y);
+        rlEnd();
+    }
+    else if ((rlGetVersion() == OPENGL_21) || (rlGetVersion() == OPENGL_33) || (rlGetVersion() == OPENGL_ES_20))
+    {
+        rlEnableTexture(GetDefaultTexture().id); // Default white texture
+
+        rlBegin(RL_QUADS);
+            rlColor4ub(color.r, color.g, color.b, color.a);
+            rlVertex2f(v1.x, v1.y);
+            rlVertex2f(v2.x, v2.y);
+            rlVertex2f(v2.x, v2.y);
+            rlVertex2f(v3.x, v3.y);
+        rlEnd();
+        
+        rlDisableTexture();
+    }
 }
 
 void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color)

+ 10 - 7
src/text.c

@@ -782,12 +782,15 @@ static SpriteFont LoadBMFont(const char *fileName)
     char *texPath = NULL;
     char *lastSlash = NULL;
 
-    lastSlash = strrchr(fileName, '/'); // you need escape character
-    texPath = malloc(strlen(fileName) - strlen(lastSlash) + 1 + strlen(texFileName) + 1);
-    memcpy(texPath, fileName, strlen(fileName) - strlen(lastSlash));
-    strcat(texPath, "/");
-    strcat(texPath, texFileName);
-    strcat(texPath, "\0");
+    lastSlash = strrchr(fileName, '/');
+    
+    // NOTE: We need some extra space to avoid memory corruption on next allocations!
+    texPath = malloc(strlen(fileName) - strlen(lastSlash) + strlen(texFileName) + 4);
+    
+    // NOTE: strcat() and strncat() required a '\0' terminated string to work!
+    *texPath = '\0';
+    strncat(texPath, fileName, strlen(fileName) - strlen(lastSlash) + 1);
+    strncat(texPath, texFileName, strlen(texFileName));
 
     TraceLog(DEBUG, "[%s] Font texture loading path: %s", fileName, texPath);
     
@@ -828,7 +831,7 @@ static SpriteFont LoadBMFont(const char *fileName)
     else if (unorderedChars) TraceLog(WARNING, "BMFont not supported: unordered chars data, falling back to default font");
     
     // NOTE: Font data could be not ordered by charId: 32,33,34,35... raylib does not support unordered BMFonts
-    if ((firstChar != FONT_FIRST_CHAR) || (unorderedChars))
+    if ((firstChar != FONT_FIRST_CHAR) || (unorderedChars) || (font.texture.id == 0))
     {
         UnloadSpriteFont(font);
         font = GetDefaultFont();

+ 231 - 180
templates/android_project/jni/include/raylib.h

@@ -1,6 +1,6 @@
 /**********************************************************************************************
 *
-*   raylib 1.4.0 (www.raylib.com)
+*   raylib 1.5.0 (www.raylib.com)
 *
 *   A simple and easy-to-use library to learn videogames programming
 *
@@ -64,6 +64,7 @@
 //#define PLATFORM_ANDROID      // Android device
 //#define PLATFORM_RPI          // Raspberry Pi
 //#define PLATFORM_WEB          // HTML5 (emscripten, asm.js)
+//#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)
@@ -71,7 +72,7 @@
 #endif
 
 #if defined(PLATFORM_ANDROID)
-    typedef struct android_app;     // Define android_app struct (android_native_app_glue.h)
+    typedef struct android_app; // Define android_app struct (android_native_app_glue.h)
 #endif
 
 //----------------------------------------------------------------------------------
@@ -174,8 +175,8 @@
 // Gamepad Number
 #define GAMEPAD_PLAYER1       0
 #define GAMEPAD_PLAYER2       1
-#define GAMEPAD_PLAYER3       2
-#define GAMEPAD_PLAYER4       3
+#define GAMEPAD_PLAYER3       2     // Not supported
+#define GAMEPAD_PLAYER4       3     // Not supported
 
 // Gamepad Buttons
 // NOTE: Adjusted for a PS3 USB Controller
@@ -190,7 +191,35 @@
 #define GAMEPAD_BUTTON_SELECT   9
 #define GAMEPAD_BUTTON_START   10
 
-// TODO: Review Xbox360 USB Controller Buttons
+// Xbox360 USB Controller Buttons
+#define GAMEPAD_XBOX_BUTTON_A       0
+#define GAMEPAD_XBOX_BUTTON_B       1
+#define GAMEPAD_XBOX_BUTTON_X       2
+#define GAMEPAD_XBOX_BUTTON_Y       3
+#define GAMEPAD_XBOX_BUTTON_LB      4
+#define GAMEPAD_XBOX_BUTTON_RB      5
+#define GAMEPAD_XBOX_BUTTON_SELECT  6
+#define GAMEPAD_XBOX_BUTTON_START   7
+
+#if defined(PLATFORM_RPI)
+    #define GAMEPAD_XBOX_AXIS_DPAD_X    7
+    #define GAMEPAD_XBOX_AXIS_DPAD_Y    6
+    #define GAMEPAD_XBOX_AXIS_RIGHT_X   3
+    #define GAMEPAD_XBOX_AXIS_RIGHT_Y   4
+    #define GAMEPAD_XBOX_AXIS_LT        2
+    #define GAMEPAD_XBOX_AXIS_RT        5
+#else
+    #define GAMEPAD_XBOX_BUTTON_UP      10
+    #define GAMEPAD_XBOX_BUTTON_DOWN    12
+    #define GAMEPAD_XBOX_BUTTON_LEFT    13
+    #define GAMEPAD_XBOX_BUTTON_RIGHT   11
+    #define GAMEPAD_XBOX_AXIS_RIGHT_X   4
+    #define GAMEPAD_XBOX_AXIS_RIGHT_Y   3
+    #define GAMEPAD_XBOX_AXIS_LT_RT     2
+#endif
+
+#define GAMEPAD_XBOX_AXIS_LEFT_X    0
+#define GAMEPAD_XBOX_AXIS_LEFT_Y    1
 
 // Android Physic Buttons
 #define ANDROID_BACK            4
@@ -233,7 +262,10 @@
 //----------------------------------------------------------------------------------
 #ifndef __cplusplus
 // Boolean type
-typedef enum { false, true } bool;
+    #if !defined(_STDBOOL_H)
+        typedef enum { false, true } bool;
+        #define _STDBOOL_H
+    #endif
 #endif
 
 // byte type
@@ -296,6 +328,13 @@ typedef struct Texture2D {
     int format;             // Data format (TextureFormat)
 } Texture2D;
 
+// RenderTexture2D type, for texture rendering
+typedef struct RenderTexture2D {
+    unsigned int id;        // Render texture (fbo) id
+    Texture2D texture;      // Color buffer attachment texture
+    Texture2D depth;        // Depth buffer attachment texture
+} RenderTexture2D;
+
 // SpriteFont type, includes texture and charSet array data
 typedef struct SpriteFont {
     Texture2D texture;      // Font texture
@@ -309,102 +348,123 @@ typedef struct SpriteFont {
 
 // Camera type, defines a camera position/orientation in 3d space
 typedef struct Camera {
-    Vector3 position;
-    Vector3 target;
-    Vector3 up;
+    Vector3 position;       // Camera position
+    Vector3 target;         // Camera target it looks-at
+    Vector3 up;             // Camera up vector (rotation over its axis)
+    float fovy;             // Camera field-of-view apperture in Y (degrees)
 } Camera;
 
+// Camera2D type, defines a 2d camera
+typedef struct Camera2D {
+    Vector2 offset;         // Camera offset (displacement from target)
+    Vector2 target;         // Camera target (rotation and zoom origin)
+    float rotation;         // Camera rotation in degrees
+    float zoom;             // Camera zoom (scaling), should be 1.0f by default
+} Camera2D;
+
 // Bounding box type
 typedef struct BoundingBox {
-    Vector3 min;
-    Vector3 max;
+    Vector3 min;            // minimum vertex box-corner
+    Vector3 max;            // maximum vertex box-corner
 } BoundingBox;
 
 // Vertex data definning a mesh
 typedef struct Mesh {
-    int vertexCount;            // num vertices
-    float *vertices;            // vertex position (XYZ - 3 components per vertex)
-    float *texcoords;           // vertex texture coordinates (UV - 2 components per vertex)
-    float *texcoords2;          // vertex second texture coordinates (useful for lightmaps)
-    float *normals;             // vertex normals (XYZ - 3 components per vertex)
-    float *tangents;            // vertex tangents (XYZ - 3 components per vertex)
-    unsigned char *colors;      // vertex colors (RGBA - 4 components per vertex)
-    
-    BoundingBox bounds;         // mesh limits defined by min and max points
-    
-    unsigned int vaoId;         // OpenGL Vertex Array Object id
-    unsigned int vboId[6];      // OpenGL Vertex Buffer Objects id (6 types of vertex data)
+    int vertexCount;        // number of vertices stored in arrays
+    int triangleCount;      // number of triangles stored (indexed or not)
+    float *vertices;        // vertex position (XYZ - 3 components per vertex) (shader-location = 0)
+    float *texcoords;       // vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1)
+    float *texcoords2;      // vertex second texture coordinates (useful for lightmaps) (shader-location = 5)
+    float *normals;         // vertex normals (XYZ - 3 components per vertex) (shader-location = 2)
+    float *tangents;        // vertex tangents (XYZ - 3 components per vertex) (shader-location = 4)
+    unsigned char *colors;  // vertex colors (RGBA - 4 components per vertex) (shader-location = 3)
+    unsigned short *indices;// vertex indices (in case vertex data comes indexed)
+
+    unsigned int vaoId;     // OpenGL Vertex Array Object id
+    unsigned int vboId[7];  // OpenGL Vertex Buffer Objects id (7 types of vertex data)
 } Mesh;
 
 // Shader type (generic shader)
 typedef struct Shader {
-    unsigned int id;                // Shader program id
-
-    // TODO: This should be Texture2D objects
-    unsigned int texDiffuseId;      // Diffuse texture id
-    unsigned int texNormalId;       // Normal texture id
-    unsigned int texSpecularId;     // Specular texture id
+    unsigned int id;        // Shader program id
     
-    // Variable attributes
-    int vertexLoc;        // Vertex attribute location point (vertex shader)
-    int texcoordLoc;      // Texcoord attribute location point (vertex shader)
-    int normalLoc;        // Normal attribute location point (vertex shader)
-    int colorLoc;         // Color attibute location point (vertex shader)
-
-    // Uniforms
-    int mvpLoc;           // ModelView-Projection matrix uniform location point (vertex shader)
-    int tintColorLoc;     // Color uniform location point (fragment shader)
+    // Vertex attributes locations (default locations)
+    int vertexLoc;          // Vertex attribute location point    (default-location = 0)
+    int texcoordLoc;        // Texcoord attribute location point  (default-location = 1)
+    int texcoord2Loc;       // Texcoord2 attribute location point (default-location = 5)
+    int normalLoc;          // Normal attribute location point    (default-location = 2)
+    int tangentLoc;         // Tangent attribute location point   (default-location = 4)
+    int colorLoc;           // Color attibute location point      (default-location = 3)
+
+    // Uniform locations
+    int mvpLoc;             // ModelView-Projection matrix uniform location point (vertex shader)
+    int tintColorLoc;       // Diffuse color uniform location point (fragment shader)
     
-    int mapDiffuseLoc;    // Diffuse map texture uniform location point (fragment shader)
-    int mapNormalLoc;     // Normal map texture uniform location point (fragment shader)
-    int mapSpecularLoc;   // Specular map texture uniform location point (fragment shader)
+    // Texture map locations (generic for any kind of map)
+    int mapTexture0Loc;     // Map texture uniform location point (default-texture-unit = 0)
+    int mapTexture1Loc;     // Map texture uniform location point (default-texture-unit = 1)
+    int mapTexture2Loc;     // Map texture uniform location point (default-texture-unit = 2)
 } Shader;
 
 // Material type
-// TODO: Redesign material-shaders-textures system
 typedef struct Material {
-    //Shader shader;
+    Shader shader;          // Standard shader (supports 3 map textures)
 
-    //Texture2D texDiffuse;      // Diffuse texture
-    //Texture2D texNormal;       // Normal texture
-    //Texture2D texSpecular;     // Specular texture
+    Texture2D texDiffuse;   // Diffuse texture  (binded to shader mapTexture0Loc)
+    Texture2D texNormal;    // Normal texture   (binded to shader mapTexture1Loc)
+    Texture2D texSpecular;  // Specular texture (binded to shader mapTexture2Loc)
     
-    Color colDiffuse;
-    Color colAmbient;
-    Color colSpecular;
+    Color colDiffuse;       // Diffuse color
+    Color colAmbient;       // Ambient color
+    Color colSpecular;      // Specular color
     
-    float glossiness;
-    float normalDepth;
+    float glossiness;       // Glossiness level (Ranges from 0 to 1000)
 } Material;
 
-// 3d Model type
-// TODO: Replace shader/testure by material
+// Model type
 typedef struct Model {
-    Mesh mesh;
-    Matrix transform;
-    Texture2D texture;    // Only for OpenGL 1.1, on newer versions this should be in the shader
-    Shader shader;
-	//Material material;
+    Mesh mesh;              // Vertex data buffers (RAM and VRAM)
+    Matrix transform;       // Local transform matrix
+    Material material;      // Shader and textures data
 } Model;
 
+// Light type
+typedef struct LightData {
+    unsigned int id;        // Light unique id
+    bool enabled;           // Light enabled
+    int type;               // Light type: LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT
+    
+    Vector3 position;       // Light position
+    Vector3 target;         // Light target: LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target)
+    float radius;           // Light attenuation radius light intensity reduced with distance (world distance)
+    
+    Color diffuse;          // Light diffuse color
+    float intensity;        // Light intensity level
+    
+    float coneAngle;        // Light cone max angle: LIGHT_SPOT
+} LightData, *Light;
+
+// Light types
+typedef enum { LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT } LightType;
+
 // Ray type (useful for raycast)
 typedef struct Ray {
-    Vector3 position;
-    Vector3 direction;
+    Vector3 position;       // Ray position (origin)
+    Vector3 direction;      // Ray direction
 } Ray;
 
 // Sound source type
 typedef struct Sound {
-    unsigned int source;
-    unsigned int buffer;
+    unsigned int source;    // Sound audio source id
+    unsigned int buffer;    // Sound audio buffer id
 } Sound;
 
 // Wave type, defines audio wave data
 typedef struct Wave {
     void *data;                 // Buffer data pointer
     unsigned int dataSize;      // Data size in bytes
-    unsigned int sampleRate;
-    short bitsPerSample;
+    unsigned int sampleRate;    // Samples per second to be played
+    short bitsPerSample;        // Sample size in bits
     short channels;
 } Wave;
 
@@ -455,7 +515,7 @@ typedef enum { TOUCH_UP, TOUCH_DOWN, TOUCH_MOVE } TouchAction;
 
 // Gesture events
 // NOTE: MAX_TOUCH_POINTS fixed to 2
-typedef struct {
+typedef struct GestureEvent {
     int touchAction;
     int pointCount;
     int pointerId[MAX_TOUCH_POINTS];
@@ -465,36 +525,18 @@ typedef struct {
 // Camera system modes
 typedef enum { CAMERA_CUSTOM = 0, CAMERA_FREE, CAMERA_ORBITAL, CAMERA_FIRST_PERSON, CAMERA_THIRD_PERSON } CameraMode;
 
-// Collider types
-typedef enum { COLLIDER_CIRCLE, COLLIDER_RECTANGLE, COLLIDER_CAPSULE } ColliderType;
-
-// Transform struct
-typedef struct Transform {
-    Vector2 position;
-    float rotation;
-    Vector2 scale;
-} Transform;
-
-// Rigidbody struct
-typedef struct Rigidbody {
-    bool enabled;
-    float mass;
-    Vector2 acceleration;
-    Vector2 velocity;
-    bool isGrounded;
-    bool isContact;     // Avoid freeze player when touching floor
-    bool applyGravity;
-    float friction;     // 0.0f to 1.0f
-    float bounciness;   // 0.0f to 1.0f
-} Rigidbody;
-
-// Collider struct
-typedef struct Collider {
-    bool enabled;
-    ColliderType type;
-    Rectangle bounds;   // Used for COLLIDER_RECTANGLE and COLLIDER_CAPSULE
-    int radius;         // Used for COLLIDER_CIRCLE and COLLIDER_CAPSULE
-} Collider;
+// Head Mounted Display devices
+typedef enum {
+    HMD_DEFAULT_DEVICE = 0,
+    HMD_OCULUS_RIFT_DK2,
+    HMD_OCULUS_RIFT_CV1,
+    HMD_VALVE_HTC_VIVE,
+    HMD_SAMSUNG_GEAR_VR,
+    HMD_GOOGLE_CARDBOARD,
+    HMD_SONY_PLAYSTATION_VR,
+    HMD_RAZER_OSVR,
+    HMD_FOVE_VR,
+} HmdDevice;
 
 #ifdef __cplusplus
 extern "C" {            // Prevents name mangling of functions
@@ -518,23 +560,28 @@ void CloseWindow(void);                                     // Close Window and
 bool WindowShouldClose(void);                               // Detect if KEY_ESCAPE pressed or Close icon pressed
 bool IsWindowMinimized(void);                               // Detect if window has been minimized (or lost focus)
 void ToggleFullscreen(void);                                // Fullscreen toggle (only PLATFORM_DESKTOP)
-#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI)
-void SetCustomCursor(const char *cursorImage);              // Set a custom cursor icon/image
-void SetExitKey(int key);                                   // Set a custom key to exit program (default is ESC)
-#endif
 int GetScreenWidth(void);                                   // Get current screen width
 int GetScreenHeight(void);                                  // Get current screen height
 
+void ShowCursor(void);                                      // Shows cursor
+void HideCursor(void);                                      // Hides cursor
+bool IsCursorHidden(void);                                  // Returns true if cursor is not visible
+void EnableCursor(void);                                    // Enables cursor
+void DisableCursor(void);                                   // Disables cursor
+
 void ClearBackground(Color color);                          // Sets Background Color
 void BeginDrawing(void);                                    // Setup drawing canvas to start drawing
-void BeginDrawingEx(int blendMode, Shader shader, Matrix transform);   // Setup drawing canvas with extended parameters
 void EndDrawing(void);                                      // End canvas drawing and Swap Buffers (Double Buffering)
 
+void Begin2dMode(Camera2D camera);                          // Initialize 2D mode with custom camera
+void End2dMode(void);                                       // Ends 2D mode custom camera usage
 void Begin3dMode(Camera camera);                            // Initializes 3D mode for drawing (Camera setup)
 void End3dMode(void);                                       // Ends 3D mode and returns to default 2D orthographic mode
+void BeginTextureMode(RenderTexture2D target);              // Initializes render texture for drawing
+void EndTextureMode(void);                                  // Ends drawing to render texture
 
 Ray GetMouseRay(Vector2 mousePosition, Camera camera);      // Returns a ray trace from mouse position
-Vector2 WorldToScreen(Vector3 position, Camera camera);     // Returns the screen space position from a 3d world space position
+Vector2 GetWorldToScreen(Vector3 position, Camera camera);  // Returns the screen space position from a 3d world space position
 Matrix GetCameraMatrix(Camera camera);                      // Returns camera transform matrix (view matrix)
 
 void SetTargetFPS(int fps);                                 // Set target FPS (maximum)
@@ -569,6 +616,15 @@ bool IsKeyDown(int key);                                // Detect if a key is be
 bool IsKeyReleased(int key);                            // Detect if a key has been released once
 bool IsKeyUp(int key);                                  // Detect if a key is NOT being pressed
 int GetKeyPressed(void);                                // Get latest key pressed
+void SetExitKey(int key);                               // Set a custom key to exit program (default is ESC)
+
+bool IsGamepadAvailable(int gamepad);                   // Detect if a gamepad is available
+float GetGamepadAxisMovement(int gamepad, int axis);    // Return axis movement value for a gamepad axis
+bool IsGamepadButtonPressed(int gamepad, int button);   // Detect if a gamepad button has been pressed once
+bool IsGamepadButtonDown(int gamepad, int button);      // Detect if a gamepad button is being pressed
+bool IsGamepadButtonReleased(int gamepad, int button);  // Detect if a gamepad button has been released once
+bool IsGamepadButtonUp(int gamepad, int button);        // Detect if a gamepad button is NOT being pressed
+#endif
 
 bool IsMouseButtonPressed(int button);                  // Detect if a mouse button has been pressed once
 bool IsMouseButtonDown(int button);                     // Detect if a mouse button is being pressed
@@ -580,20 +636,6 @@ Vector2 GetMousePosition(void);                         // Returns mouse positio
 void SetMousePosition(Vector2 position);                // Set mouse position XY
 int GetMouseWheelMove(void);                            // Returns mouse wheel movement Y
 
-void ShowCursor(void);                                  // Shows cursor
-void HideCursor(void);                                  // Hides cursor
-void EnableCursor(void);                                // Enables cursor
-void DisableCursor(void);                               // Disables cursor
-bool IsCursorHidden(void);                              // Returns true if cursor is not visible
-
-bool IsGamepadAvailable(int gamepad);                   // Detect if a gamepad is available
-Vector2 GetGamepadMovement(int gamepad);                // Return axis movement vector for a gamepad
-bool IsGamepadButtonPressed(int gamepad, int button);   // Detect if a gamepad button has been pressed once
-bool IsGamepadButtonDown(int gamepad, int button);      // Detect if a gamepad button is being pressed
-bool IsGamepadButtonReleased(int gamepad, int button);  // Detect if a gamepad button has been released once
-bool IsGamepadButtonUp(int gamepad, int button);        // Detect if a gamepad button is NOT being pressed
-#endif
-
 int GetTouchX(void);                                    // Returns touch position X for touch point 0 (relative to screen size)
 int GetTouchY(void);                                    // Returns touch position Y for touch point 0 (relative to screen size)                   
 Vector2 GetTouchPosition(int index);                    // Returns touch position XY for a touch point index (relative to screen size)
@@ -607,13 +649,13 @@ bool IsButtonReleased(int button);                      // Detect if an android
 //------------------------------------------------------------------------------------
 // Gestures and Touch Handling Functions (Module: gestures)
 //------------------------------------------------------------------------------------
-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(void);                           // Check if a gesture have been detected
-int GetGestureType(void);                               // Get latest detected gesture
 void SetGesturesEnabled(unsigned int gestureFlags);     // Enable a set of gestures using flags
-int GetTouchPointsCount(void);                          // Get touch points count
+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())
 
+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
@@ -629,6 +671,7 @@ void UpdateCameraPlayer(Camera *camera, Vector3 *position); // Update camera and
 
 void SetCameraPosition(Vector3 position);                   // Set internal camera position
 void SetCameraTarget(Vector3 target);                       // Set internal camera target
+void SetCameraFovy(float fovy);                             // Set internal camera field-of-view-y
 
 void SetCameraPanControl(int panKey);                       // Set camera pan key to combine with mouse movement (free camera)
 void SetCameraAltControl(int altKey);                       // Set camera alt key to combine with mouse movement (free camera)
@@ -680,8 +723,10 @@ Texture2D LoadTexture(const char *fileName);
 Texture2D LoadTextureEx(void *data, int width, int height, int textureFormat);                     // Load a texture from raw data into GPU memory
 Texture2D LoadTextureFromRES(const char *rresName, int resId);                                     // Load an image as texture from rRES file (raylib Resource)
 Texture2D LoadTextureFromImage(Image image);                                                       // Load a texture from image data
+RenderTexture2D LoadRenderTexture(int width, int height);                                          // Load a texture to be used for rendering
 void UnloadImage(Image image);                                                                     // Unload image from CPU memory (RAM)
 void UnloadTexture(Texture2D texture);                                                             // Unload texture from GPU memory
+void UnloadRenderTexture(RenderTexture2D target);                                                  // Unload render texture from GPU memory
 Color *GetImageData(Image image);                                                                  // Get pixel data from image as a Color struct array
 Image GetTextureData(Texture2D texture);                                                           // Get pixel data from GPU texture and return an Image
 void ImageToPOT(Image *image, Color fillColor);                                                    // Convert image to POT (power-of-two)
@@ -690,14 +735,17 @@ void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp);
 Image ImageCopy(Image image);                                                                      // Create an image duplicate (useful for transformations)
 void ImageCrop(Image *image, Rectangle crop);                                                      // Crop an image to a defined rectangle
 void ImageResize(Image *image, int newWidth, int newHeight);                                       // Resize and image (bilinear filtering)
-void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec);                         // Draw a source image within a destination image
+void ImageResizeNN(Image *image,int newWidth,int newHeight);                                       // Resize and image (Nearest-Neighbor scaling algorithm)
 Image ImageText(const char *text, int fontSize, Color color);                                      // Create an image from text (default font)
 Image ImageTextEx(SpriteFont font, const char *text, int fontSize, int spacing, Color tint);       // Create an image from text (custom sprite font)
+void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec);                         // Draw a source image within a destination image
+void ImageDrawText(Image *dst, Vector2 position, const char *text, int fontSize, Color color);     // Draw text (default font) within an image (destination)
+void ImageDrawTextEx(Image *dst, Vector2 position, SpriteFont font, const char *text, int fontSize, int spacing, Color color); // Draw text (custom sprite font) within an image (destination)
 void ImageFlipVertical(Image *image);                                                              // Flip image vertically
 void ImageFlipHorizontal(Image *image);                                                            // Flip image horizontally
 void ImageColorTint(Image *image, Color color);                                                    // Modify image color: tint
 void ImageColorInvert(Image *image);                                                               // Modify image color: invert
-void ImageColorGrayscale(Image *image);                                                            // Modify bimage color: grayscale
+void ImageColorGrayscale(Image *image);                                                            // Modify image color: grayscale
 void ImageColorContrast(Image *image, float contrast);                                             // Modify image color: contrast (-100 to 100)
 void ImageColorBrightness(Image *image, int brightness);                                           // Modify image color: brightness (-255 to 255)
 void GenTextureMipmaps(Texture2D texture);                                                         // Generate GPU mipmaps for a texture
@@ -730,6 +778,8 @@ const char *SubText(const char *text, int position, int length);
 //------------------------------------------------------------------------------------
 // Basic 3d Shapes Drawing Functions (Module: models)
 //------------------------------------------------------------------------------------
+void Draw3DLine(Vector3 startPos, Vector3 endPos, Color color);                                    // Draw a line in 3D world space
+void Draw3DCircle(Vector3 center, float radius, float rotationAngle, Vector3 rotation, Color color);    // Draw a circle in 3D world space
 void DrawCube(Vector3 position, float width, float height, float lenght, Color color);             // Draw cube
 void DrawCubeV(Vector3 position, Vector3 size, Color color);                                       // Draw cube (Vector version)
 void DrawCubeWires(Vector3 position, float width, float height, float lenght, Color color);        // Draw cube wires
@@ -740,39 +790,43 @@ void DrawSphereWires(Vector3 centerPos, float radius, int rings, int slices, Col
 void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color); // Draw a cylinder/cone
 void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color); // Draw a cylinder/cone wires
 void DrawPlane(Vector3 centerPos, Vector2 size, Color color);                                      // Draw a plane XZ
-void DrawQuad(Vector3 v1, Vector3 v2, Vector3 v3, Vector3 v4, Color color);                        // Draw a quad
 void DrawRay(Ray ray, Color color);                                                                // Draw a ray line
 void DrawGrid(int slices, float spacing);                                                          // Draw a grid (centered at (0, 0, 0))
 void DrawGizmo(Vector3 position);                                                                  // Draw simple gizmo
+void DrawLight(Light light);                                                                       // Draw light in 3D world
 //DrawTorus(), DrawTeapot() are useless...
 
 //------------------------------------------------------------------------------------
 // Model 3d Loading and Drawing Functions (Module: models)
 //------------------------------------------------------------------------------------
-Model LoadModel(const char *fileName);                                                             // Load a 3d model (.OBJ)
-Model LoadModelEx(Mesh data);                                                                      // Load a 3d model (from vertex data)
-//Model LoadModelFromRES(const char *rresName, int resId);                                         // TODO: Load a 3d model from rRES file (raylib Resource)
-Model LoadHeightmap(Image heightmap, Vector3 size);                                                // Load a heightmap image as a 3d model
-Model LoadCubicmap(Image cubicmap);                                                                // Load a map image as a 3d model (cubes based)
-void UnloadModel(Model model);                                                                     // Unload 3d model from memory
-void SetModelTexture(Model *model, Texture2D texture);                                             // Link a texture to a model
+Model LoadModel(const char *fileName);                          // Load a 3d model (.OBJ)
+Model LoadModelEx(Mesh data, bool dynamic);                     // Load a 3d model (from mesh data)
+Model LoadModelFromRES(const char *rresName, int resId);        // Load a 3d model from rRES file (raylib Resource)
+Model LoadHeightmap(Image heightmap, Vector3 size);             // Load a heightmap image as a 3d model
+Model LoadCubicmap(Image cubicmap);                             // Load a map image as a 3d model (cubes based)
+void UnloadModel(Model model);                                  // Unload 3d model from memory
+
+Material LoadMaterial(const char *fileName);                    // Load material data (from file)
+Material LoadDefaultMaterial(void);                             // Load default material (uses default models shader)
+Material LoadStandardMaterial(void);                            // Load standard material (uses material attributes and lighting shader)
+void UnloadMaterial(Material material);                         // Unload material textures from VRAM
 
 void DrawModel(Model model, Vector3 position, float scale, Color tint);                            // Draw a model (with texture if set)
 void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint);      // Draw a model with extended parameters
-void DrawModelWires(Model model, Vector3 position, float scale, Color color);                      // Draw a model wires (with texture if set)
-void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint);      // Draw a model wires (with texture if set) with extended parameters
-void DrawBoundingBox(BoundingBox box);                                                             // Draw bounding box (wires)
+void DrawModelWires(Model model, Vector3 position, float scale, Color tint);                      // Draw a model wires (with texture if set)
+void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters
+void DrawBoundingBox(BoundingBox box, Color color);                                                // Draw bounding box (wires)
 
 void DrawBillboard(Camera camera, Texture2D texture, Vector3 center, float size, Color tint);                         // Draw a billboard texture
 void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, Vector3 center, float size, Color tint); // Draw a billboard texture defined by sourceRec
 
-BoundingBox CalculateBoundingBox(Mesh mesh);                                                       // Calculate mesh bounding box limits
+BoundingBox CalculateBoundingBox(Mesh mesh);                                                                    // Calculate mesh bounding box limits
 bool CheckCollisionSpheres(Vector3 centerA, float radiusA, Vector3 centerB, float radiusB);                     // Detect collision between two spheres
-bool CheckCollisionBoxes(Vector3 minBBox1, Vector3 maxBBox1, Vector3 minBBox2, Vector3 maxBBox2);               // Detect collision between two boxes
-bool CheckCollisionBoxSphere(Vector3 minBBox, Vector3 maxBBox, Vector3 centerSphere, float radiusSphere);       // Detect collision between box and sphere
+bool CheckCollisionBoxes(BoundingBox box1, BoundingBox box2);                                                   // Detect collision between two bounding boxes
+bool CheckCollisionBoxSphere(BoundingBox box, Vector3 centerSphere, float radiusSphere);                        // Detect collision between box and sphere
 bool CheckCollisionRaySphere(Ray ray, Vector3 spherePosition, float sphereRadius);                              // Detect collision between ray and sphere
 bool CheckCollisionRaySphereEx(Ray ray, Vector3 spherePosition, float sphereRadius, Vector3 *collisionPoint);   // Detect collision between ray and sphere with extended parameters and collision point detection
-bool CheckCollisionRayBox(Ray ray, Vector3 minBBox, Vector3 maxBBox);                                           // Detect collision between ray and box
+bool CheckCollisionRayBox(Ray ray, BoundingBox box);                                                            // Detect collision between ray and box
 Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *playerPosition, float radius);   // Detect collision of player radius with cubicmap
                                                                                                                 // NOTE: Return the normal vector of the impacted surface
 //------------------------------------------------------------------------------------
@@ -780,51 +834,46 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p
 // NOTE: This functions are useless when using OpenGL 1.1
 //------------------------------------------------------------------------------------
 Shader LoadShader(char *vsFileName, char *fsFileName);              // Load a custom shader and bind default locations
-unsigned int LoadShaderProgram(char *vShaderStr, char *fShaderStr); // Load custom shaders strings and return program id
 void UnloadShader(Shader shader);                                   // Unload a custom shader from memory
-void SetPostproShader(Shader shader);                               // Set fullscreen postproduction shader
-void SetCustomShader(Shader shader);                                // Set custom shader to be used in batch draw
-void SetDefaultShader(void);                                        // Set default shader to be used in batch draw
-void SetModelShader(Model *model, Shader shader);                   // Link a shader to a model
-bool IsPosproShaderEnabled(void);                                   // Check if postprocessing shader is enabled
-
-int GetShaderLocation(Shader shader, const char *uniformName);                          // Get shader uniform location
-void SetShaderValue(Shader shader, int uniformLoc, float *value, int size);             // Set shader uniform value (float)
-void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size);              // Set shader uniform value (int)
-void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat);                   // Set shader uniform value (matrix 4x4)
-void SetShaderMapDiffuse(Shader *shader, Texture2D texture);                            // Default diffuse shader map texture assignment
-void SetShaderMapNormal(Shader *shader, const char *uniformName, Texture2D texture);    // Normal map texture shader assignment
-void SetShaderMapSpecular(Shader *shader, const char *uniformName, Texture2D texture);  // Specular map texture shader assignment
-void SetShaderMap(Shader *shader, int mapLocation, Texture2D texture, int textureUnit); // TODO: Generic shader map assignment
-
-void SetBlendMode(int mode);                                        // Set blending mode (alpha, additive, multiplied)
 
-//----------------------------------------------------------------------------------
-// Physics System Functions (engine-module: physac)
-//----------------------------------------------------------------------------------
-void InitPhysics(int maxPhysicElements);                                    // Initialize all internal physics values
-void UnloadPhysics();                                                       // Unload physic elements arrays
+Shader GetDefaultShader(void);                                      // Get default shader
+Shader GetStandardShader(void);                                     // Get default shader
+Texture2D GetDefaultTexture(void);                                  // Get default texture
+
+int GetShaderLocation(Shader shader, const char *uniformName);              // Get shader uniform location
+void SetShaderValue(Shader shader, int uniformLoc, float *value, int size); // Set shader uniform value (float)
+void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size);  // Set shader uniform value (int)
+void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat);       // Set shader uniform value (matrix 4x4)
 
-void AddRigidbody(int index, Rigidbody rigidbody);                          // Initialize a new rigidbody with parameters to internal index slot
-void AddCollider(int index, Collider collider);                             // Initialize a new Collider with parameters to internal index slot
+void SetMatrixProjection(Matrix proj);                              // Set a custom projection matrix (replaces internal projection matrix)
+void SetMatrixModelview(Matrix view);                               // Set a custom modelview matrix (replaces internal modelview matrix)
 
-void ApplyPhysics(int index, Vector2 *position);                            // Apply physics to internal rigidbody, physics calculations are applied to position pointer parameter
-void SetRigidbodyEnabled(int index, bool state);                            // Set enabled state to a defined rigidbody
-void SetRigidbodyVelocity(int index, Vector2 velocity);                     // Set velocity of rigidbody (without considering of mass value)
-void SetRigidbodyAcceleration(int index, Vector2 acceleration);             // Set acceleration of rigidbody (without considering of mass value)
-void AddRigidbodyForce(int index, Vector2 force);                           // Set rigidbody force (considering mass value)
-void AddForceAtPosition(Vector2 position, float intensity, float radius);   // Add a force to all enabled rigidbodies at a position
+void BeginShaderMode(Shader shader);                                // Begin custom shader drawing
+void EndShaderMode(void);                                           // End custom shader drawing (use default shader)
+void BeginBlendMode(int mode);                                      // Begin blending mode (alpha, additive, multiplied)
+void EndBlendMode(void);                                            // End blending mode (reset to default: alpha blending)
 
-void SetColliderEnabled(int index, bool state);                             // Set enabled state to a defined collider
+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
 
-Rigidbody GetRigidbody(int index);                                          // Returns the internal rigidbody data defined by index parameter
-Collider GetCollider(int index);                                            // Returns the internal collider data defined by index parameter
+//------------------------------------------------------------------------------------
+// VR experience Functions (Module: rlgl)
+// NOTE: This functions are useless when using OpenGL 1.1
+//------------------------------------------------------------------------------------
+void InitVrDevice(int hmdDevice);           // Init VR device
+void CloseVrDevice(void);                   // Close VR device
+void UpdateVrTracking(void);                // Update VR tracking (position and orientation)
+void BeginVrDrawing(void);                  // Begin VR drawing configuration
+void EndVrDrawing(void);                    // End VR drawing process (and desktop mirror)
+bool IsVrDeviceReady(void);                 // Detect if VR device (or simulator) is ready
+void ToggleVrMode(void);                    // Enable/Disable VR experience (device or simulator)
 
 //------------------------------------------------------------------------------------
 // Audio Loading and Playing Functions (Module: audio)
 //------------------------------------------------------------------------------------
 void InitAudioDevice(void);                                     // Initialize audio device and context
 void CloseAudioDevice(void);                                    // Close the audio device and context (and music stream)
+bool IsAudioDeviceReady(void);                                  // True if call to InitAudioDevice() was successful and CloseAudioDevice() has not been called yet
 
 Sound LoadSound(char *fileName);                                // Load sound to memory
 Sound LoadSoundFromWave(Wave wave);                             // Load sound to memory from wave data
@@ -833,19 +882,21 @@ void UnloadSound(Sound sound);                                  // Unload sound
 void PlaySound(Sound sound);                                    // Play a sound
 void PauseSound(Sound sound);                                   // Pause a sound
 void StopSound(Sound sound);                                    // Stop playing a sound
-bool SoundIsPlaying(Sound sound);                               // Check if a sound is currently playing
+bool IsSoundPlaying(Sound sound);                               // Check if a sound is currently playing
 void SetSoundVolume(Sound sound, float volume);                 // Set volume for a sound (1.0 is max level)
 void SetSoundPitch(Sound sound, float pitch);                   // Set pitch for a sound (1.0 is base level)
 
-void PlayMusicStream(char *fileName);                           // Start music playing (open stream)
-void UpdateMusicStream(void);                                   // Updates buffers for music streaming
-void StopMusicStream(void);                                     // Stop music playing (close stream)
-void PauseMusicStream(void);                                    // Pause music playing
-void ResumeMusicStream(void);                                   // Resume playing paused music
-bool MusicIsPlaying(void);                                      // Check if music is playing
-void SetMusicVolume(float volume);                              // Set volume for music (1.0 is max level)
-float GetMusicTimeLength(void);                                 // Get current music time length (in seconds)
-float GetMusicTimePlayed(void);                                 // Get current music time played (in seconds)
+int PlayMusicStream(int index, char *fileName);                 // Start music playing (open stream)
+void UpdateMusicStream(int index);                              // Updates buffers for music streaming
+void StopMusicStream(int index);                                // Stop music playing (close stream)
+void PauseMusicStream(int index);                               // Pause music playing
+void ResumeMusicStream(int index);                              // Resume playing paused music
+bool IsMusicPlaying(int index);                                 // Check if music is playing
+void SetMusicVolume(int index, float volume);                   // Set volume for music (1.0 is max level)
+void SetMusicPitch(int index, float pitch);                     // Set pitch for a music (1.0 is base level)
+float GetMusicTimeLength(int index);                            // Get current music time length (in seconds)
+float GetMusicTimePlayed(int index);                            // Get current music time played (in seconds)
+int GetMusicStreamCount(void);                                  // Get number of streams loaded
 
 #ifdef __cplusplus
 }

BIN
templates/android_project/jni/libs/libraylib.a


この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません