فهرست منبع

Merge pull request #132 from raysan5/develop

Develop branch integration
Ray 9 سال پیش
والد
کامیت
a2794379a0
91فایلهای تغییر یافته به همراه14865 افزوده شده و 3275 حذف شده
  1. 5 1
      .gitignore
  2. 93 2
      CHANGELOG
  3. 5 7
      HELPME.md
  4. 1 1
      LICENSE.md
  5. 61 24
      README.md
  6. 10 4
      ROADMAP.md
  7. 39 24
      examples/Makefile
  8. 6 6
      examples/audio_music_stream.c
  9. 2 2
      examples/core_2d_camera.c
  10. 2 2
      examples/core_color_select.c
  11. 18 8
      examples/core_oculus_rift.c
  12. BIN
      examples/core_oculus_rift.png
  13. 0 1
      examples/core_world_screen.c
  14. 1 1
      examples/models_cubicmap.c
  15. 1 1
      examples/models_heightmap.c
  16. 2 2
      examples/models_obj_loading.c
  17. 26 0
      examples/oculus_glfw_sample/base.vs
  18. 59 0
      examples/oculus_glfw_sample/distortion.fs
  19. 58 90
      examples/oculus_glfw_sample/oculus_glfw_sample.c
  20. BIN
      examples/oculus_glfw_sample/raylib_OculusRiftCV1_test03.png
  21. 11 28
      examples/oculus_glfw_sample/raymath.h
  22. 470 39
      examples/oculus_glfw_sample/rlgl.c
  23. 16 1
      examples/oculus_glfw_sample/rlgl.h
  24. 44 52
      examples/oculus_glfw_sample/rlgl_standalone.c
  25. 496 0
      examples/oculus_glfw_sample/rlgl_standalone_stereo.c
  26. 174 0
      examples/oculus_glfw_sample/standard_shader.h
  27. 19 14
      examples/physics_basic_rigidbody.c
  28. 20 15
      examples/physics_forces.c
  29. 1 1
      examples/resources/shaders/glsl100/bloom.fs
  30. 54 0
      examples/resources/shaders/glsl100/distortion.fs
  31. 2 2
      examples/resources/shaders/glsl100/grayscale.fs
  32. 4 4
      examples/resources/shaders/glsl100/swirl.fs
  33. 56 0
      examples/resources/shaders/glsl330/distortion.fs
  34. 3 3
      examples/resources/shaders/glsl330/swirl.fs
  35. 1 1
      examples/shaders_custom_uniform.c
  36. 1 1
      examples/shaders_postprocessing.c
  37. 2 2
      examples/shaders_standard_lighting.c
  38. 2 2
      games/raylib_demo/raylib_demo.c
  39. BIN
      release/android/armeabi/libraylib.a
  40. 896 0
      release/android/raylib.h
  41. BIN
      release/html5/libraylib.bc
  42. 896 0
      release/html5/raylib.h
  43. 0 0
      release/linux/helpme!
  44. 0 0
      release/osx/helpme!
  45. BIN
      release/win32/mingw32/libraylib.a
  46. 896 0
      release/win32/raylib.h
  47. 1 1
      shaders/glsl100/bloom.fs
  48. 1 1
      shaders/glsl100/grayscale.fs
  49. 155 0
      shaders/glsl100/standard.fs
  50. 23 0
      shaders/glsl100/standard.vs
  51. 0 0
      shaders/glsl330/standard.fs
  52. 0 0
      shaders/glsl330/standard.vs
  53. 2 11
      src/Makefile
  54. 2 2
      src/android/jni/Android.mk
  55. 265 241
      src/audio.c
  56. 21 14
      src/audio.h
  57. 112 517
      src/core.c
  58. 196 0
      src/external/OculusSDK/LibOVR/Include/Extras/OVR_CAPI_Util.h
  59. 3804 0
      src/external/OculusSDK/LibOVR/Include/Extras/OVR_Math.h
  60. 70 0
      src/external/OculusSDK/LibOVR/Include/Extras/OVR_StereoProjection.h
  61. 2128 0
      src/external/OculusSDK/LibOVR/Include/OVR_CAPI.h
  62. 80 0
      src/external/OculusSDK/LibOVR/Include/OVR_CAPI_Audio.h
  63. 155 0
      src/external/OculusSDK/LibOVR/Include/OVR_CAPI_D3D.h
  64. 99 0
      src/external/OculusSDK/LibOVR/Include/OVR_CAPI_GL.h
  65. 53 0
      src/external/OculusSDK/LibOVR/Include/OVR_CAPI_Keys.h
  66. 147 0
      src/external/OculusSDK/LibOVR/Include/OVR_ErrorCode.h
  67. 60 0
      src/external/OculusSDK/LibOVR/Include/OVR_Version.h
  68. BIN
      src/external/OculusSDK/LibOVR/LibOVRRT32_1.dll
  69. 0 9
      src/external/glad.c
  70. 1 1
      src/external/glad.h
  71. 26 18
      src/external/jar_mod.h
  72. BIN
      src/external/pthread/pthreadGC2.dll
  73. 17 17
      src/gestures.c
  74. 4 4
      src/gestures.h
  75. BIN
      src/libraylib.bc
  76. 39 43
      src/models.c
  77. 0 594
      src/physac.c
  78. 754 22
      src/physac.h
  79. 0 1138
      src/raygui.c
  80. 1222 27
      src/raygui.h
  81. 31 71
      src/raylib.h
  82. 8 10
      src/raymath.h
  83. 607 160
      src/rlgl.c
  84. 27 8
      src/rlgl.h
  85. 106 0
      src/shader_distortion.h
  86. 173 0
      src/shader_standard.h
  87. 6 6
      src/shapes.c
  88. 10 7
      src/text.c
  89. 1 6
      src/textures.c
  90. 1 1
      templates/android_project/jni/Android.mk
  91. 5 5
      templates/android_project/jni/basic_game.c

+ 5 - 1
.gitignore

@@ -63,10 +63,14 @@ xcuserdata/
 DerivedData/
 *.dll
 src/libraylib.a
+src/libraylib.bc
 
 # oculus example
-!examples/oculus_glfw_sample/LibOVRRT32_1.dll
+!examples/oculus_glfw_sample/
+
 
 # external libraries DLLs
 !src/external/glfw3/lib/win32/glfw3.dll
 !src/external/openal_soft/lib/win32/OpenAL32.dll
+!src/external/OculusSDK/LibOVR/LibOVRRT32_1.dll
+!src/external/pthread/pthreadGC2.dll

+ 93 - 2
CHANGELOG

@@ -1,16 +1,107 @@
 changelog
 ---------
 
-Current Release:    raylib 1.4.0 (22 February 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 (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, 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 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:
+
+[core] Review Android button inputs
+[core] Support Android internal data storage
+[core] Renamed WorldToScreen() to GetWorldToScreen()
+[core] Removed function SetCustomCursor()
+[core] Removed functions BeginDrawingEx(), BeginDrawingPro()
+[core] Replaced functions InitDisplay() + InitGraphics() with: InitGraphicsDevice()
+[core] Added support for field-of-view Y (fovy) on 3d Camera
+[core] Added 2D camera mode functions: Begin2dMode() - End2dMode()
+[core] Translate mouse inputs to Android touch/gestures internally
+[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()
+[rlgl] Removed function: rlglInitGraphics(), integrated into rlglInit()
+[rlgl] Updated Mesh and Shader structs
+[rlgl] Simplified internal (default) dynamic buffers
+[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: 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()
+[rlgl] Replaced SetCustomShader() by: BeginShaderMode() - EndShaderMode()
+[rlgl] Replaced SetBlendMode() by: BeginBlendMode() - EndBlendMode()
+[rlgl] Added functions to customize internal matrices: SetMatrixProjection(), SetMatrixModelview()
+[rlgl] Unified internal shaders to only one default shader
+[rlgl] Added support for render to texture (RenderTexture2D): 
+          LoadRenderTexture() - UnloadRenderTexture()
+          BeginTextureMode() - EndTextureMode()
+[rlgl] Removed SetShaderMap*() functions
+[rlgl] Redesigned default buffers usage functions:
+          LoadDefaultBuffers() - UnloadDefaultBuffers()
+          UpdateDefaultBuffers() - DrawDefaultBuffers()
+[shapes] Corrected bug on GetCollisionRec()
+[textures] Added support for Nearest-Neighbor image scaling
+[textures] Added functions to draw text on image: ImageDrawText(), ImageDrawTextEx()
+[text] Reorganized internal functions: Added LoadImageFont()
+[text] Security check for unsupported BMFonts
+[models] Split mesh creation from model loading on heightmap and cubicmap
+[models] Updated BoundingBox collision detections
+[models] Added color parameter to DrawBoundigBox()
+[models] Removed function: DrawQuad()
+[models] Removed function: SetModelTexture()
+[models] Redesigned DrawPlane() to use RL_TRIANGLES
+[models] Redesigned DrawRectangleV() to use RL_TRIANGLES
+[models] Redesign to accomodate new materials system: LoadMaterial()
+[models] Added material functions: LoadDefaultMaterial(), LoadStandardMaterial()
+[models] Added MTL material loading support: LoadMTL()
+[models] Added function: DrawLight()
+[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 (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)
+[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)
 -----------------------------------------------
 NOTE: 
-  This version supposed another big improvement for raylib, inlcuding new modules and new features.
+  This version supposed another big improvement for raylib, including new modules and new features.
   More than 30 new functions have been added to previous raylib version.
   Around 8 new examples and +10 new game samples have been added.
 

+ 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

+ 1 - 1
LICENSE.md

@@ -7,7 +7,7 @@ source code
 raylib is licensed under an unmodified zlib/libpng license, which is an OSI-certified, 
 BSD-like license that allows static linking with closed source software:
 	
-Copyright (c) 2013 Ramon Santamaria (Ray San - [email protected])
+Copyright (c) 2013-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.

+ 61 - 24
README.md

@@ -1,4 +1,4 @@
-<img src="http://www.raylib.com/img/fb_raylib_logo.png" width=256>
+<img src="https://github.com/raysan5/raylib/blob/master/logo/logo256x256.png" width=256>
 
 about
 -----
@@ -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).
 
@@ -101,40 +99,74 @@ Lots of code changes and lot of testing have concluded in this amazing new rayli
 notes on raylib 1.4
 -------------------
 
-On February 2016, after 4 months of raylib 1.3 release, it comes raylib 1.4. For this new version, lots of parts of the library have been reviewed, lots of bugs have been solved and some interesting features have been added.
+On February 2016, after 4 months of raylib 1.3 release, it comes raylib 1.4. For this new version, 
+lots of parts of the library have been reviewed, lots of bugs have been solved and some interesting features have been added.
 
-First big addition is a set of [Image manipulation functions](https://github.com/raysan5/raylib/blob/develop/src/raylib.h#L673) have been added to crop, resize, colorize, flip, dither and even draw image-to-image or text-to-image. Now a basic image processing can be done before converting the image to texture for usage.
+First big addition is a set of [Image manipulation functions](https://github.com/raysan5/raylib/blob/develop/src/raylib.h#L673) have been added to crop, resize, colorize, flip, dither and even draw image-to-image or text-to-image.
+Now a basic image processing can be done before converting the image to texture for usage.
 
-SpriteFonts system has been improved, adding support for AngelCode fonts (.fnt) and TrueType Fonts (using [stb_truetype](https://github.com/nothings/stb/blob/master/stb_truetype.h) helper library). Now raylib can read standard .fnt font data and also generate at loading a SpriteFont from a TTF file.
+SpriteFonts system has been improved, adding support for AngelCode fonts (.fnt) and TrueType Fonts (using [stb_truetype](https://github.com/nothings/stb/blob/master/stb_truetype.h) helper library). 
+Now raylib can read standard .fnt font data and also generate at loading a SpriteFont from a TTF file.
 
-New [physac](https://github.com/raysan5/raylib/blob/develop/src/physac.h) physics module for basic 2D physics support. Still in development but already functional. Module comes with some usage examples for basic jump and level interaction and also force-based physic movements.
+New [physac](https://github.com/raysan5/raylib/blob/develop/src/physac.h) physics module for basic 2D physics support. Still in development but already functional. 
+Module comes with some usage examples for basic jump and level interaction and also force-based physic movements.
 
 [raymath](https://github.com/raysan5/raylib/blob/develop/src/raymath.h) module has been reviewed; some bugs have been solved and the module has been converted to a header-only file for easier portability, optionally, functions can also be used as inline. 
 
-[gestures](https://github.com/raysan5/raylib/blob/develop/src/gestures.c) module has redesigned and simplified, now it can process touch events from any source, including mouse. This way, gestures system can be used on any platform providing an unified way to work with inputs and allowing the user to create multiplatform games with only one source code.
+[gestures](https://github.com/raysan5/raylib/blob/develop/src/gestures.c) module has redesigned and simplified, now it can process touch events from any source, including mouse. 
+This way, gestures system can be used on any platform providing an unified way to work with inputs and allowing the user to create multiplatform games with only one source code.
 
-Raspberry Pi input system has been redesigned to better read raw inputs using generic Linux event handlers (keyboard:`stdin`, mouse:`/dev/input/mouse0`, gamepad:`/dev/input/js0`). Gamepad support has also been added (experimental).
+Raspberry Pi input system has been redesigned to better read raw inputs using generic Linux event handlers (keyboard:`stdin`, mouse:`/dev/input/mouse0`, gamepad:`/dev/input/js0`). 
+Gamepad support has also been added (experimental).
 
-Other important improvements are the functional raycast system for 3D picking, including some ray collision-detection functions, and the addition of two simple functions for persistent data storage. Now raylib user can save and load game data in a file (only some platforms supported). A simple [easings](https://github.com/raysan5/raylib/blob/develop/src/easings.h) module has also been added for values animation.
+Other important improvements are the functional raycast system for 3D picking, including some ray collision-detection functions, 
+and the addition of two simple functions for persistent data storage. Now raylib user can save and load game data in a file (only some platforms supported). 
+A simple [easings](https://github.com/raysan5/raylib/blob/develop/src/easings.h) module has also been added for values animation.
 
-Up to 8 new code examples have been added to show the new raylib features and +10 complete game samples have been provided to learn how to create some classic games like Arkanoid, Asteroids, Missile Commander, Snake or Tetris.
+Up to 8 new code examples have been added to show the new raylib features and +10 complete game samples have been provided to learn 
+how to create some classic games like Arkanoid, Asteroids, Missile Commander, Snake or Tetris.
 
 Lots of code changes and lots of hours of hard work have concluded in this amazing new raylib 1.4.
 
+notes on raylib 1.5
+-------------------
+
+On July 2016, after 5 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.
+
+VR support: **Oculus Rift CV1**. 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, supported light types are **point light**, **directional light** and **spot light**. Just create a light, configure it and raylib manages render internally for every 3d object using standard material.
+
+Complete gamepad support on Raspberry Pi: Gamepad system has been completely redesigned. Now multiple gamepads can be easily used and  configured and gamepad data is read and processed in raw mode in a second thread.
+
+Redesigned physics module: physac module has been converted to header only and usage has been simplified. Performance has also been singnificantly improved, now physic objects now are managed internally in a second thread.
+
+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 @kd7tck amazing work.
+
+This new version is so massie 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 and lighting systems. 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 also some samples to show the usage of [rlgl]() and [audio]() raylib modules as standalone libraries.
+
+Lots of code changes (more than 300 commits) and lots of hours of hard work have concluded in this amazing new raylib 1.5.
+
 features
 --------
  
    *  Written in plain C code (C99)
    *  Uses C# PascalCase/camelCase notation
-   *  Hardware accelerated with OpenGL (1.1, 3.3 or ES2)
+   *  Hardware accelerated with OpenGL (1.1, 2.1, 3.3 or ES2)
    *  Unique OpenGL abstraction layer (usable as standalone module): [rlgl](https://github.com/raysan5/raylib/blob/master/src/rlgl.c) 
    *  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
    *  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 and OGG)
+   *  Audio loading and playing with streaming support and mixing channels (WAV, OGG, XM, MOD)
    *  Custom color palette for fancy visuals on raywhite background
-   *  Multiple platforms support: Windows, Linux, Mac, **Android**, **Raspberry Pi** and **HTML5**
+   *  VR stereo rendering support with configurable HMD device parameters
+   *  Multiple platforms support: Windows, Linux, Mac, **Android**, **Raspberry Pi**, **HTML5** and **Oculus Rift CV1**
 
 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, ...).
@@ -142,7 +174,7 @@ 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.
 
@@ -167,12 +199,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
 -------
@@ -191,21 +223,26 @@ If you feel you can help, then, [helpme!](http://www.raylib.com/helpme.htm)
 acknowledgements
 ---------------
 
-The following people have contributed in some way to make raylib project a reality. Big thanks to them!
+I believe that time is the most valuable resource and the following people have invested part of their time
+contributing (in some way or another) to make raylib project better. Huge thanks!
 
  - [Zopokx](https://github.com/Zopokx) for testing the web.
  - [Elendow](http://www.elendow.com) for testing and helping on web development.
- - Victor Dual for implementating and testing of 3D shapes functions.
- - Marc Palau for implementating and testing of 3D shapes functions and helping on development of camera and getures modules.
+ - Victor Dual for implementing and testing 3D shapes functions.
+ - Marc Palau for implementing and testing 3D shapes functions and contribute on camera and gestures modules.
  - Kevin Gato for improving texture internal formats support and helping on raygui development. 
  - Daniel Nicolas for improving texture internal formats support and helping on raygui development. 
  - Marc Agüera for testing and using raylib on a real product ([Koala Seasons](http://www.koalaseasons.com))
  - Daniel Moreno for testing and using raylib on a real product ([Koala Seasons](http://www.koalaseasons.com))
  - Daniel Gomez for testing and using raylib on a real product ([Koala Seasons](http://www.koalaseasons.com))
- - Sergio Martinez for helping on raygui development and tools development.
- - Victor Fisac for developing physics raylib module (physac) and implementing light shaders and raycast system... and multiple tools and games. 
+ - Sergio Martinez for helping on raygui development and tools development (raygui_styler).
+ - [Victor Fisac](https://github.com/victorfisac) for developing physics raylib module (physac) and implementing materials and lighting systems... among multiple other improvements and multiple tools and games. 
  - Albert Martos for helping on raygui and porting examples and game-templates to Android and HTML5.
  - Ian Eito for helping on raygui and porting examples and game-templates to Android and HTML5.
+ - [procedural](https://github.com/procedural) for testing raylib on Linux, correcting some bugs and adding several mouse functions.
+ - [Chris Hemingway](https://github.com/cHemingway) for improving raylib on OSX build system.
+ - [Emanuele Petriglia](https://github.com/LelixSuper) for working on multiple GNU/Linux improvements and developing [TicTacToe](https://github.com/LelixSuper/TicTacToe) raylib game.
+ - [Joshua Reisenauer](https://github.com/kd7tck) for adding audio modules support (XM, MOD) and reviewing audio system.
  
 	
 [raysan5]: mailto:[email protected] "Ramon Santamaria - Ray San"

+ 10 - 4
ROADMAP.md

@@ -6,16 +6,22 @@ Here it is a wish list of features I would like to add and functions to improve.
 
 Note that around the raylib source code there are multiple TODO points with pending revisions/bugs. Check [GitHub Issues](https://github.com/raysan5/raylib/issues) for further details!
 
-raylib 1.5
+raylib 1.x
 
-    Redesign Shaders/Textures system, use Materials
-    Redesign physics module (physac)
+    [IN PROGRESS] LUA scripting support (wrapper to lua lib)
     Basic GPU stats sytem (memory, draws, time...)
     Procedural image generation functions (spot, gradient, noise...)
     Procedural mesh generation functions (cube, cone, sphere...)
     Touch-based camera controls for Android
     Skybox and Fog support
-    [IN PROGRESS] LUA scripting support (wrapper to lua lib)
+
+raylib 1.5
+
+    [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)
+    [DONE] Chiptunes audio modules support
 
 raylib 1.4
 

+ 39 - 24
examples/Makefile

@@ -2,7 +2,7 @@
 #
 #   raylib makefile for desktop platforms, Raspberry Pi and HTML5 (emscripten)
 #
-#   Copyright (c) 2015 Ramon Santamaria (@raysan5)
+#   Copyright (c) 2013-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.
@@ -78,44 +78,38 @@ endif
 #CFLAGSEXTRA = -Wextra -Wmissing-prototypes -Wstrict-prototypes
 
 # define any directories containing required header files
+INCLUDES = -I. -I../src -I../src/external
+
 ifeq ($(PLATFORM),PLATFORM_RPI)
-    INCLUDES = -I. -I../../src -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads
+    INCLUDES += -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads
 endif
 ifeq ($(PLATFORM),PLATFORM_DESKTOP)
     # add standard directories for GNU/Linux
     ifeq ($(PLATFORM_OS),LINUX)
-        INCLUDES = -I. -I../src -I/usr/local/include/raylib/
-    else ifeq ($(PLATFORM_OS),OSX)
-        INCLUDES = -I. -I../src
-    else
-        INCLUDES = -I. -I../../src -IC:/raylib/raylib/src
+        INCLUDES += -I/usr/local/include/raylib/
+    else ifeq ($(PLATFORM_OS),WINDOWS)
         # external libraries headers
         # GLFW3
-            INCLUDES += -I../../external/glfw3/include
+            INCLUDES += -I../src/external/glfw3/include
         # OpenAL Soft
-            INCLUDES += -I../../external/openal_soft/include
+            INCLUDES += -I../src/external/openal_soft/include
     endif
 endif
 
 # define library paths containing required libs
+LFLAGS = -L. -L../src
+
 ifeq ($(PLATFORM),PLATFORM_RPI)
-    LFLAGS = -L. -L../../src -L/opt/vc/lib
+    LFLAGS += -L/opt/vc/lib
 endif
 ifeq ($(PLATFORM),PLATFORM_DESKTOP)
     # add standard directories for GNU/Linux
-    ifeq ($(PLATFORM_OS),LINUX)
-        LFLAGS = -L. -L../../src
-    else ifeq ($(PLATFORM_OS),OSX)
-        LFLAGS = -L. -L../src
-    else
-        LFLAGS = -L. -L../../src -LC:/raylib/raylib/src
+    ifeq ($(PLATFORM_OS),WINDOWS)
         # external libraries to link with
         # GLFW3
-            LFLAGS += -L../../external/glfw3/lib/$(LIBPATH)
-        ifneq ($(PLATFORM_OS),OSX)
+            LFLAGS += -L../src/external/glfw3/lib/$(LIBPATH)
         # OpenAL Soft
-            LFLAGS += -L../../external/openal_soft/lib/$(LIBPATH)
-        endif
+            LFLAGS += -L../src/external/openal_soft/lib/$(LIBPATH)
     endif
 endif
 
@@ -126,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
@@ -148,7 +143,7 @@ ifeq ($(PLATFORM),PLATFORM_RPI)
 endif
 ifeq ($(PLATFORM),PLATFORM_WEB)
     # just adjust the correct path to libraylib.bc
-    LIBS = ../src/libraylib.bc
+    LIBS = ../release/html5/libraylib.bc
 endif
 
 # define additional parameters and flags for windows
@@ -178,6 +173,9 @@ EXAMPLES = \
     core_3d_picking \
     core_3d_camera_free \
     core_3d_camera_first_person \
+    core_2d_camera \
+    core_world_screen \
+    core_oculus_rift \
     shapes_logo_raylib \
     shapes_basic_shapes \
     shapes_colors_palette \
@@ -208,6 +206,7 @@ EXAMPLES = \
     shaders_shapes_textures \
     shaders_custom_uniform \
     shaders_postprocessing \
+    shaders_standard_lighting \
     audio_sound_loading \
     audio_music_stream \
     fix_dylib \
@@ -287,7 +286,19 @@ core_3d_camera_free: core_3d_camera_free.c
 # compile [core] example - 3d camera first person
 core_3d_camera_first_person: core_3d_camera_first_person.c
 	$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)    
+
+# compile [core] example - 2d camera
+core_2d_camera: core_2d_camera.c
+	$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
     
+# compile [core] example - world screen
+core_world_screen: core_world_screen.c
+	$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
+
+# compile [core] example - oculus rift
+core_oculus_rift: core_oculus_rift.c
+	$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
+
 # compile [shapes] example - raylib logo (with basic shapes)
 shapes_logo_raylib: shapes_logo_raylib.c
 	$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
@@ -411,7 +422,11 @@ shaders_custom_uniform: shaders_custom_uniform.c
 # compile [shaders] example - postprocessing shader
 shaders_postprocessing: shaders_postprocessing.c
 	$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
-    
+
+# compile [shaders] example - standard lighting
+shaders_standard_lighting: shaders_standard_lighting.c
+	$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
+
 # compile [audio] example - sound loading and playing (WAV and OGG)
 audio_sound_loading: audio_sound_loading.c
 	$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)

+ 6 - 6
examples/audio_music_stream.c

@@ -24,7 +24,7 @@ int main()
 
     InitAudioDevice();              // Initialize audio device
 
-    PlayMusicStream("resources/audio/guitar_noodling.ogg");         // Play music stream
+    PlayMusicStream(0, "resources/audio/guitar_noodling.ogg");         // Play music stream
 
     int framesCounter = 0;
     float timePlayed = 0.0f;
@@ -52,18 +52,18 @@ int main()
             {
                 volume = 1.0;
                 framesCounter = 0;
-                PlayMusicStream("resources/audio/another_file.ogg");
+                PlayMusicStream(1, "resources/audio/another_file.ogg");
             }
 
             SetMusicVolume(volume);
         }
 */
-        if (IsWindowMinimized()) PauseMusicStream();
-        else ResumeMusicStream();
+        if (IsWindowMinimized()) PauseMusicStream(0);
+        else ResumeMusicStream(0);
 
-        timePlayed = GetMusicTimePlayed()/GetMusicTimeLength()*100*4; // We scale by 4 to fit 400 pixels
+        timePlayed = GetMusicTimePlayed(0)/GetMusicTimeLength(0)*100*4; // We scale by 4 to fit 400 pixels
         
-        UpdateMusicStream();        // Update music buffer with new stream data
+        UpdateMusicStream(0);        // Update music buffer with new stream data
         //----------------------------------------------------------------------------------
 
         // Draw

+ 2 - 2
examples/core_2d_camera.c

@@ -23,8 +23,8 @@ int main()
     InitWindow(screenWidth, screenHeight, "raylib [core] example - 2d camera");
     
     Rectangle player = { 400, 280, 40, 40 };
-    Rectangle buildings[MAX_BUILDINGS] = { 0, 0, 0, 0 };
-    Color buildColors[MAX_BUILDINGS] = { 80, 80, 80, 255 };
+    Rectangle buildings[MAX_BUILDINGS];
+    Color buildColors[MAX_BUILDINGS];
     
     int spacing = 0;
     

+ 2 - 2
examples/core_color_select.c

@@ -16,7 +16,7 @@ int main()
     // Initialization
     //--------------------------------------------------------------------------------------
     int screenWidth = 800;
-    int screenHeight = 400;
+    int screenHeight = 450;
 
     InitWindow(screenWidth, screenHeight, "raylib [core] example - color selection (collision detection)");
 
@@ -30,7 +30,7 @@ int main()
     for (int i = 0; i < 21; i++)
     {
         colorsRecs[i].x = 20 + 100*(i%7) + 10*(i%7);
-        colorsRecs[i].y = 40 + 100*(i/7) + 10*(i/7);
+        colorsRecs[i].y = 60 + 100*(i/7) + 10*(i/7);
         colorsRecs[i].width = 100;
         colorsRecs[i].height = 100;
     }

+ 18 - 8
examples/core_oculus_rift.c

@@ -2,6 +2,9 @@
 *
 *   raylib [core] example - Oculus Rift CV1
 *
+*   Compile example using:
+*   gcc -o $(NAME_PART).exe $(FILE_NAME) -L. -L..\src\external\OculusSDK\LibOVR -lLibOVRRT32_1 -lraylib -lglfw3 -lopengl32 -lgdi32 -std=c99
+*
 *   This example has been created using raylib 1.5 (www.raylib.com)
 *   raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
 *
@@ -18,19 +21,22 @@ 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");
     
-    InitOculusDevice();
-
-    // Define the camera to look into our 3d world   
+    // NOTE: If device is not available, it fallbacks to default device (simulator)
+    InitVrDevice(HMD_OCULUS_RIFT_CV1);                  // Init VR device (Oculus Rift CV1)
+    
+    // Define the camera to look into our 3d world
     Camera camera;
     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
+    camera.fovy = 60.0f;                                // Camera field-of-view Y
     
     Vector3 cubePosition = { 0.0f, 0.0f, 0.0f };
-
+    
     SetTargetFPS(90);                   // Set our game to run at 90 frames-per-second
     //--------------------------------------------------------------------------------------
 
@@ -39,13 +45,15 @@ int main()
     {
         // Update
         //----------------------------------------------------------------------------------
-        UpdateOculusTracking();
+        UpdateVrTracking();
+        
+        if (IsKeyPressed(KEY_SPACE)) ToggleVrMode();
         //----------------------------------------------------------------------------------
 
         // Draw
         //----------------------------------------------------------------------------------
         BeginDrawing();
-        
+
             ClearBackground(RAYWHITE);
 
             Begin3dMode(camera);
@@ -57,13 +65,15 @@ int main()
 
             End3dMode();
 
+            DrawFPS(10, 10);
+
         EndDrawing();
         //----------------------------------------------------------------------------------
     }
 
     // De-Initialization
     //--------------------------------------------------------------------------------------
-    CloseOculusdevice();    // Close Oculus Rift device
+    CloseVrDevice();        // Close VR device
     
     CloseWindow();          // Close window and OpenGL context
     //--------------------------------------------------------------------------------------

BIN
examples/core_oculus_rift.png


+ 0 - 1
examples/core_world_screen.c

@@ -63,7 +63,6 @@ int main()
             
             DrawText("Enemy: 100 / 100", cubeScreenPosition.x - MeasureText("Enemy: 100 / 100", 20) / 2, cubeScreenPosition.y, 20, BLACK);
             DrawText("Text is always on top of the cube", (screenWidth - MeasureText("Text is always on top of the cube", 20)) / 2, 25, 20, GRAY);
-            
 
         EndDrawing();
         //----------------------------------------------------------------------------------

+ 1 - 1
examples/models_cubicmap.c

@@ -29,7 +29,7 @@ int main()
     
     // NOTE: By default each cube is mapped to one part of texture atlas
     Texture2D texture = LoadTexture("resources/cubicmap_atlas.png");    // Load map texture
-    SetModelTexture(&map, texture);                         // Bind texture to map model
+    map.material.texDiffuse = texture;                      // Set map diffuse texture
     
     Vector3 mapPosition = { -16.0f, 0.0f, -8.0f };          // Set model position
 

+ 1 - 1
examples/models_heightmap.c

@@ -26,7 +26,7 @@ int main()
     Image image = LoadImage("resources/heightmap.png");         // Load heightmap image (RAM)
     Texture2D texture = LoadTextureFromImage(image);            // Convert image to texture (VRAM)
     Model map = LoadHeightmap(image, (Vector3){ 16, 8, 16 });   // Load heightmap model with defined size
-    SetModelTexture(&map, texture);                             // Bind texture to model
+    map.material.texDiffuse = texture;                          // Set map diffuse texture
     Vector3 mapPosition = { -8.0f, 0.0f, -8.0f };               // Set model position (depends on model scaling!)
 
     UnloadImage(image);                 // Unload heightmap image from RAM, already uploaded to VRAM

+ 2 - 2
examples/models_obj_loading.c

@@ -25,7 +25,7 @@ int main()
 
     Model dwarf = LoadModel("resources/model/dwarf.obj");                   // Load OBJ model
     Texture2D texture = LoadTexture("resources/model/dwarf_diffuse.png");   // Load model texture
-    SetModelTexture(&dwarf, texture);                                       // Bind texture to model
+    dwarf.material.texDiffuse = texture;                                    // Set dwarf model diffuse texture
     Vector3 position = { 0.0f, 0.0f, 0.0f };                                // Set model position
 
     SetTargetFPS(60);   // Set our game to run at 60 frames-per-second
@@ -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
 

+ 26 - 0
examples/oculus_glfw_sample/base.vs

@@ -0,0 +1,26 @@
+#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);
+}

+ 59 - 0
examples/oculus_glfw_sample/distortion.fs

@@ -0,0 +1,59 @@
+#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);
+    }
+}

+ 58 - 90
examples/oculus_glfw_sample/oculus_glfw_sample.c

@@ -23,12 +23,11 @@
 #include <string.h>
 #include <math.h>
 
-#define GLAD_IMPLEMENTATION
-#include "glad.h"               // Extensions loading library
+#include "glad.h"
 #include <GLFW/glfw3.h>         // Windows/Context and inputs management
 
 #define RLGL_STANDALONE
-#include "rlgl.h"
+#include "rlgl.h"               // rlgl library: OpenGL 1.1 immediate-mode style coding
 
 #define PLATFORM_OCULUS
 
@@ -79,14 +78,11 @@ typedef struct OculusLayer {
 } OculusLayer;
 #endif
 
-typedef enum { LOG_INFO = 0, LOG_ERROR, LOG_WARNING, LOG_DEBUG, LOG_OTHER } TraceLogType;
-
 //----------------------------------------------------------------------------------
 // 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);
-static void TraceLog(int msgType, const char *text, ...);
 
 // Drawing functions (uses rlgl functionality)
 static void DrawGrid(int slices, float spacing);
@@ -114,32 +110,10 @@ int main(void)
 {
     // Initialization
     //--------------------------------------------------------------------------------------
-    int screenWidth = 1080;
-    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)
     
-#if defined(PLATFORM_OCULUS)
-    ovrResult result = ovr_Initialize(NULL);
-    if (OVR_FAILURE(result)) TraceLog(LOG_ERROR, "OVR: Could not initialize Oculus device");
-
-    result = ovr_Create(&session, &luid);
-    if (OVR_FAILURE(result))
-    {
-        TraceLog(LOG_WARNING, "OVR: Could not create Oculus session");
-        ovr_Shutdown();
-    }
-
-    hmdDesc = ovr_GetHmdDesc(session);
-    
-    TraceLog(LOG_INFO, "OVR: Product Name: %s", hmdDesc.ProductName);
-    TraceLog(LOG_INFO, "OVR: Manufacturer: %s", hmdDesc.Manufacturer);
-    TraceLog(LOG_INFO, "OVR: Product ID: %i", hmdDesc.ProductId);
-    TraceLog(LOG_INFO, "OVR: Product Type: %i", hmdDesc.Type);
-    TraceLog(LOG_INFO, "OVR: Serian Number: %s", hmdDesc.SerialNumber);
-    TraceLog(LOG_INFO, "OVR: Resolution: %ix%i", hmdDesc.Resolution.w, hmdDesc.Resolution.h);
-    
-    screenWidth = hmdDesc.Resolution.w/2;
-    screenHeight = hmdDesc.Resolution.h/2;
-#endif
+    // NOTE: Mirror screen size can be set to any desired resolution!
     
     // GLFW3 Initialization + OpenGL 3.3 Context + Extensions
     //--------------------------------------------------------
@@ -147,10 +121,10 @@ int main(void)
     
     if (!glfwInit())
     {
-        TraceLog(LOG_WARNING, "GLFW3: Can not initialize GLFW");
-        exit(EXIT_FAILURE);
+        TraceLog(WARNING, "GLFW3: Can not initialize GLFW");
+        return 1;
     }
-    else TraceLog(LOG_INFO, "GLFW3: GLFW initialized successfully");
+    else TraceLog(INFO, "GLFW3: GLFW initialized successfully");
     
     glfwWindowHint(GLFW_DEPTH_BITS, 16);
     glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
@@ -163,9 +137,9 @@ int main(void)
     if (!window)
     {
         glfwTerminate();
-        exit(EXIT_FAILURE);
+        return 2;
     }
-    else TraceLog(LOG_INFO, "GLFW3: Window created successfully");
+    else TraceLog(INFO, "GLFW3: Window created successfully");
     
     glfwSetKeyCallback(window, KeyCallback);
     
@@ -173,39 +147,55 @@ int main(void)
     glfwSwapInterval(0);
 
     // Load OpenGL 3.3 extensions
-    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
-    {
-        TraceLog(LOG_WARNING, "GLAD: Cannot load OpenGL extensions");
-        exit(1);
-    }
-    else TraceLog(LOG_INFO, "GLAD: OpenGL extensions loaded successfully");
+    rlglLoadExtensions(glfwGetProcAddress);
+    
+    // Initialize rlgl internal buffers and OpenGL state
+    rlglInit();
+    rlglInitGraphics(0, 0, screenWidth, screenHeight);
+    rlClearColor(245, 245, 245, 255);   // Define clear color
+    rlEnableDepthTest();                // Enable DEPTH_TEST for 3D
     //--------------------------------------------------------
     
 #if defined(PLATFORM_OCULUS)
+    ovrResult result = ovr_Initialize(NULL);
+    if (OVR_FAILURE(result)) TraceLog(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, hmdDesc.Resolution.w/2, hmdDesc.Resolution.h/2);
+    OculusMirror mirror = LoadOculusMirror(session, screenWidth, screenHeight);
     layer.eyeLayer.ColorTexture[0] = buffer.textureChain;     //SetOculusLayerTexture(eyeLayer, buffer.textureChain);
 
     // Recenter OVR tracking origin
     ovr_RecenterTrackingOrigin(session);
 #endif
-
-    // Initialize rlgl internal buffers and OpenGL state
-    rlglInit();
-    rlglInitGraphics(0, 0, screenWidth, screenHeight);
-    rlClearColor(245, 245, 245, 255);   // Define clear color
-    rlEnableDepthTest();                // Enable DEPTH_TEST for 3D
-    
-    Vector2 size = { 200, 200 };
-    Vector3 cubePosition = { 0.0f, 0.0f, 0.0f };
     
     Camera camera;
     camera.position = (Vector3){ 5.0f, 5.0f, 5.0f };    // Camera position
     camera.target = (Vector3){ 0.0f, 0.0f, 0.0f };      // Camera looking at point
     camera.up = (Vector3){ 0.0f, 1.0f, 0.0f };          // Camera up vector (rotation towards target)
     camera.fovy = 45.0f;                                // Camera field-of-view Y
+    
+    Vector3 cubePosition = { 0.0f, 0.0f, 0.0f };
     //--------------------------------------------------------------------------------------    
 
     // Main game loop    
@@ -257,8 +247,8 @@ int main(void)
             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
+            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);
@@ -297,7 +287,7 @@ int main(void)
         // Get session status information
         ovrSessionStatus sessionStatus;
         ovr_GetSessionStatus(session, &sessionStatus);
-        if (sessionStatus.ShouldQuit) TraceLog(LOG_WARNING, "OVR: Session should quit...");
+        if (sessionStatus.ShouldQuit) TraceLog(WARNING, "OVR: Session should quit...");
         if (sessionStatus.ShouldRecenter) ovr_RecenterTrackingOrigin(session);
 #endif
 
@@ -311,17 +301,15 @@ int main(void)
 #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();
-    
-#if defined(PLATFORM_OCULUS)
-    ovr_Destroy(session);   // Must be called after glfwTerminate()
-    ovr_Shutdown();
-#endif
     //--------------------------------------------------------------------------------------
     
     return 0;
@@ -334,7 +322,7 @@ int main(void)
 // GLFW3: Error callback
 static void ErrorCallback(int error, const char* description)
 {
-    TraceLog(LOG_ERROR, description);
+    TraceLog(ERROR, description);
 }
 
 // GLFW3: Keyboard callback
@@ -346,29 +334,6 @@ static void KeyCallback(GLFWwindow* window, int key, int scancode, int action, i
     }
 }
 
-// Output a trace log message
-static void TraceLog(int msgType, const char *text, ...)
-{
-    va_list args;
-    va_start(args, text);
-
-    switch(msgType)
-    {
-        case LOG_INFO: fprintf(stdout, "INFO: "); break;
-        case LOG_ERROR: fprintf(stdout, "ERROR: "); break;
-        case LOG_WARNING: fprintf(stdout, "WARNING: "); break;
-        case LOG_DEBUG: fprintf(stdout, "DEBUG: "); break;
-        default: break;
-    }
-
-    vfprintf(stdout, text, args);
-    fprintf(stdout, "\n");
-
-    va_end(args);
-
-    //if (msgType == LOG_ERROR) exit(1);
-}
-
 // Draw rectangle using rlgl OpenGL 1.1 style coding (translated to OpenGL 3.3 internally)
 static void DrawRectangleV(Vector2 position, Vector2 size, Color color)
 {
@@ -610,12 +575,12 @@ static OculusBuffer LoadOculusBuffer(ovrSession session, int width, int height)
 
     ovrResult result = ovr_CreateTextureSwapChainGL(session, &desc, &buffer.textureChain);
     
-    if (!OVR_SUCCESS(result)) TraceLog(LOG_WARNING, "OVR: Failed to create swap textures buffer");
+    if (!OVR_SUCCESS(result)) TraceLog(WARNING, "OVR: Failed to create swap textures buffer");
 
     int textureCount = 0;
     ovr_GetTextureSwapChainLength(session, buffer.textureChain, &textureCount);
     
-    if (!OVR_SUCCESS(result) || !textureCount) TraceLog(LOG_WARNING, "OVR: Unable to count swap chain textures");
+    if (!OVR_SUCCESS(result) || !textureCount) TraceLog(WARNING, "OVR: Unable to count swap chain textures");
 
     for (int i = 0; i < textureCount; ++i)
     {
@@ -682,10 +647,13 @@ static void SetOculusBuffer(ovrSession session, OculusBuffer buffer)
     //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);
+    //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);   // Same as rlClearScreenBuffers()
     
-    // Required if OculusBuffer format is OVR_FORMAT_R8G8B8A8_UNORM_SRGB
-    glEnable(GL_FRAMEBUFFER_SRGB);
+    // 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
@@ -708,7 +676,7 @@ static OculusMirror LoadOculusMirror(ovrSession session, int width, int height)
     mirrorDesc.Width = mirror.width;
     mirrorDesc.Height = mirror.height;
     
-    if (!OVR_SUCCESS(ovr_CreateMirrorTextureGL(session, &mirrorDesc, &mirror.texture))) TraceLog(LOG_WARNING, "Could not create mirror texture");
+    if (!OVR_SUCCESS(ovr_CreateMirrorTextureGL(session, &mirrorDesc, &mirror.texture))) TraceLog(WARNING, "Could not create mirror texture");
 
     glGenFramebuffers(1, &mirror.fboId);
 

BIN
examples/oculus_glfw_sample/raylib_OculusRiftCV1_test03.png


+ 11 - 28
examples/oculus_glfw_sample/raymath.h

@@ -47,10 +47,16 @@
     #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 extern inline
+    #define RMDEF RMEXTERN inline   // Functions are embeded inline (compiler generated code)
 #else
-    #define RMDEF extern
+    #define RMDEF RMEXTERN
 #endif
 
 //----------------------------------------------------------------------------------
@@ -105,10 +111,6 @@ typedef struct Quaternion {
 
 #ifndef RAYMATH_EXTERN_INLINE
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 //------------------------------------------------------------------------------------
 // Functions Declaration to work with Vector3
 //------------------------------------------------------------------------------------
@@ -151,7 +153,6 @@ RMDEF Matrix MatrixFrustum(double left, double right, double bottom, double top,
 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)
-RMDEF void PrintMatrix(Matrix m);                             // Print matrix utility
 
 //------------------------------------------------------------------------------------
 // Functions Declaration to work with Quaternions
@@ -167,10 +168,6 @@ RMDEF Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle);  // Returns
 RMDEF void QuaternionToAxisAngle(Quaternion q, Vector3 *outAxis, float *outAngle); // Returns the rotation angle and axis for a given quaternion
 RMDEF void QuaternionTransform(Quaternion *q, Matrix mat);            // Transform a quaternion given a transformation matrix
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif  // notdef RAYMATH_EXTERN_INLINE
 
 #endif  // RAYMATH_H
@@ -178,9 +175,7 @@ RMDEF void QuaternionTransform(Quaternion *q, Matrix mat);            // Transfo
 
 #if defined(RAYMATH_IMPLEMENTATION) || defined(RAYMATH_EXTERN_INLINE)
 
-#include <stdio.h>      // Used only on PrintMatrix()
-#include <math.h>       // Standard math libary: sin(), cos(), tan()...
-#include <stdlib.h>     // Used for abs()
+#include <math.h>       // Required for: sinf(), cosf(), tan(), fabs()
 
 //----------------------------------------------------------------------------------
 // Module Functions Definition - Vector3 math
@@ -342,15 +337,14 @@ RMDEF Vector3 VectorReflect(Vector3 vector, Vector3 normal)
     return result;
 }
 
-// Transforms a Vector3 with a given Matrix
+// 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;
 
-    //MatrixTranspose(&mat);
-
     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;
@@ -871,17 +865,6 @@ RMDEF Matrix MatrixLookAt(Vector3 eye, Vector3 target, Vector3 up)
     return result;
 }
 
-// Print matrix utility (for debug)
-RMDEF void PrintMatrix(Matrix m)
-{
-    printf("----------------------\n");
-    printf("%2.2f %2.2f %2.2f %2.2f\n", m.m0, m.m4, m.m8, m.m12);
-    printf("%2.2f %2.2f %2.2f %2.2f\n", m.m1, m.m5, m.m9, m.m13);
-    printf("%2.2f %2.2f %2.2f %2.2f\n", m.m2, m.m6, m.m10, m.m14);
-    printf("%2.2f %2.2f %2.2f %2.2f\n", m.m3, m.m7, m.m11, m.m15);
-    printf("----------------------\n");
-}
-
 //----------------------------------------------------------------------------------
 // Module Functions Definition - Quaternion math
 //----------------------------------------------------------------------------------

+ 470 - 39
examples/oculus_glfw_sample/rlgl.c

@@ -48,7 +48,13 @@
     #ifdef __APPLE__ 
         #include <OpenGL/gl3.h>     // OpenGL 3 library for OSX
     #else
-        #include "glad.h"           // GLAD library, includes OpenGL headers
+    #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
 
@@ -62,6 +68,14 @@
     #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
 //----------------------------------------------------------------------------------
@@ -149,13 +163,43 @@ typedef struct {
 // Draw call type
 // NOTE: Used to track required draw-calls, organized by texture
 typedef struct {
-    GLuint textureId;
     int vertexCount;
-    // TODO: Store draw state -> blending mode, shader
+    GLuint vaoId;
+    GLuint textureId;
+    GLuint shaderId;
+
+    Matrix projection;
+    Matrix modelview;
+
+    // TODO: Store additional draw state data
+    //int blendMode;
+    //Guint fboId;
 } DrawCall;
 
-#if defined(RLGL_STANDALONE)
-typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType;
+#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
 
 //----------------------------------------------------------------------------------
@@ -189,26 +233,38 @@ static bool useTempBuffer = false;
 
 // Shader Programs
 static Shader defaultShader;
-static Shader standardShader;
-static Shader currentShader;            // By default, 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)
+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
+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
+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
+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)
@@ -221,15 +277,14 @@ static PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArrays;
 static int blendMode = 0;
 
 // White texture useful for plain color polys (required by shader)
-// NOTE: It's required in shapes and models modules!
-unsigned int whiteTexture;
+static unsigned int whiteTexture;
 
 //----------------------------------------------------------------------------------
 // Module specific Functions Declaration
 //----------------------------------------------------------------------------------
 #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
 static void LoadCompressedTexture(unsigned char *data, int width, int height, int mipmapCount, int compressedFormat);
-static unsigned int LoadShaderProgram(char *vShaderStr, char *fShaderStr);  // Load custom shader strings and return program id
+static unsigned int LoadShaderProgram(const char *vShaderStr, const char *fShaderStr);  // Load custom shader strings and return program id
 
 static Shader LoadDefaultShader(void);      // Load default shader (just vertex positioning and texture coloring)
 static Shader LoadStandardShader(void);     // Load standard shader (support materials and lighting)
@@ -247,13 +302,22 @@ static void SetShaderLights(Shader shader); // Sets shader uniform values for li
 static char *ReadTextFile(const char *fileName);
 #endif
 
+#if defined(RLGL_OCULUS_SUPPORT)            // Oculus Rift functions
+static OculusBuffer LoadOculusBuffer(ovrSession session, int width, int height);    // Load Oculus required buffers
+static void UnloadOculusBuffer(ovrSession session, OculusBuffer buffer);            // Unload texture required buffers
+static OculusMirror LoadOculusMirror(ovrSession session, int width, int height);    // Load Oculus mirror buffers
+static void UnloadOculusMirror(ovrSession session, OculusMirror mirror);            // Unload Oculus mirror buffers
+static void BlitOculusMirror(ovrSession session, OculusMirror mirror);              // Copy Oculus screen buffer to mirror texture
+static OculusLayer InitOculusLayer(ovrSession session);                             // Init Oculus layer (similar to photoshop)
+static Matrix FromOvrMatrix(ovrMatrix4f ovrM);  // Convert from Oculus ovrMatrix4f struct to raymath Matrix struct
+#endif
+
 #if defined(GRAPHICS_API_OPENGL_11)
 static int GenerateMipmaps(unsigned char *data, int baseWidth, int baseHeight);
 static Color *GenNextMipmap(Color *srcData, int srcWidth, int srcHeight);
 #endif
 
 #if defined(RLGL_STANDALONE)
-static void TraceLog(int msgType, const char *text, ...);
 float *MatrixToFloat(Matrix mat);           // Converts Matrix to float array
 #endif
 
@@ -355,7 +419,6 @@ void rlRotatef(float angleDeg, float x, float y, float z)
     Vector3 axis = (Vector3){ x, y, z };
     VectorNormalize(&axis);
     matRotation = MatrixRotate(axis, angleDeg*DEG2RAD);
-
     MatrixTranspose(&matRotation);
 
     *currentMatrix = MatrixMultiply(*currentMatrix, matRotation);
@@ -1032,7 +1095,6 @@ void rlglInit(void)
 
     // Init default Shader (customized for GL 3.3 and ES2)
     defaultShader = LoadDefaultShader();
-    standardShader = LoadStandardShader();
     currentShader = defaultShader;
 
     LoadDefaultBuffers();        // Initialize default vertex arrays buffers (lines, triangles, quads)
@@ -1142,6 +1204,23 @@ void rlglInitGraphics(int offsetX, int offsetY, int width, int height)
     TraceLog(INFO, "OpenGL graphic device initialized successfully");
 }
 
+// Load OpenGL extensions
+// NOTE: External loader function could be passed as a pointer
+void rlglLoadExtensions(void *loader)
+{
+#if defined(GRAPHICS_API_OPENGL_33)
+    // NOTE: glad is generated and contains only required OpenGL 3.3 Core extensions
+    if (!gladLoadGLLoader((GLADloadproc)loader)) TraceLog(WARNING, "GLAD: Cannot load OpenGL extensions");
+    else TraceLog(INFO, "GLAD: OpenGL extensions loaded successfully");
+
+    if (GLAD_GL_VERSION_3_3) TraceLog(INFO, "OpenGL 3.3 Core profile supported");
+    else TraceLog(ERROR, "OpenGL 3.3 Core profile not supported");
+
+    // With GLAD, we can check if an extension is supported using the GLAD_GL_xxx booleans
+    //if (GLAD_GL_ARB_vertex_array_object) // Use GL_ARB_vertex_array_object
+#endif
+}
+
 // Get world coordinates from screen coordinates
 Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view)
 {
@@ -1173,11 +1252,13 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int textureForma
     GLuint id = 0;
     
     // Check texture format support by OpenGL 1.1 (compressed textures not supported)
-    if ((rlGetVersion() == OPENGL_11) && (textureFormat >= 8))
+#if defined(GRAPHICS_API_OPENGL_11) 
+    if (textureFormat >= 8)
     {
         TraceLog(WARNING, "OpenGL 1.1 does not support GPU compressed texture formats");
         return id;
     }
+#endif
     
     if ((!texCompDXTSupported) && ((textureFormat == COMPRESSED_DXT1_RGB) || (textureFormat == COMPRESSED_DXT1_RGBA) ||
         (textureFormat == COMPRESSED_DXT3_RGBA) || (textureFormat == COMPRESSED_DXT5_RGBA)))
@@ -1791,8 +1872,13 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform)
     // NOTE: standard shader specific locations are got at render time to keep Shader struct as simple as possible (with just default shader locations)
     if (material.shader.id == standardShader.id)
     {
+        // Transpose and inverse model transformations matrix for fragment normal calculations
+        Matrix transInvTransform = transform;
+        MatrixTranspose(&transInvTransform);
+        MatrixInvert(&transInvTransform);
+        
         // Send model transformations matrix to shader
-        glUniformMatrix4fv(glGetUniformLocation(material.shader.id, "modelMatrix"), 1, false, MatrixToFloat(transform));
+        glUniformMatrix4fv(glGetUniformLocation(material.shader.id, "modelMatrix"), 1, false, MatrixToFloat(transInvTransform));
         
         // Send view transformation matrix to shader. View matrix 8, 9 and 10 are view direction vector axis values (target - position)
         glUniform3f(glGetUniformLocation(material.shader.id, "viewDir"), matView.m8, matView.m9, matView.m10);
@@ -2091,6 +2177,24 @@ void *rlglReadTexturePixels(Texture2D texture)
     return pixels;
 }
 
+/*
+// TODO: Record draw calls to be processed in batch
+// NOTE: Global state must be kept
+void rlglRecordDraw(void)
+{
+    // TODO: Before adding a new draw, check if anything changed from last stored draw
+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+    draws[drawsCounter].vaoId = currentState.vaoId;             // lines.id, trangles.id, quads.id?
+    draws[drawsCounter].textureId = currentState.textureId;     // whiteTexture?
+    draws[drawsCounter].shaderId = currentState.shaderId;       // defaultShader.id
+    draws[drawsCounter].projection = projection;
+    draws[drawsCounter].modelview = modelview;
+    draws[drawsCounter].vertexCount = currentState.vertexCount;
+    
+    drawsCounter++;
+#endif
+}
+*/
 
 //----------------------------------------------------------------------------------
 // Module Functions Definition - Shaders Functions
@@ -2185,14 +2289,22 @@ Shader GetDefaultShader(void)
 }
 
 // Get default shader
+// NOTE: Inits global variable standardShader
 Shader GetStandardShader(void)
 {
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    return standardShader;
-#else
     Shader shader = { 0 };
-    return shader;
+    
+#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
@@ -2254,13 +2366,17 @@ void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat)
 // 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)
@@ -2345,6 +2461,130 @@ void DestroyLight(Light light)
 #endif
 }
 
+#if defined(RLGL_OCULUS_SUPPORT)
+// Init Oculus Rift device
+// NOTE: Device initialization should be done before window creation?
+void InitOculusDevice(void)
+{
+    // Initialize Oculus device
+    ovrResult result = ovr_Initialize(NULL);
+    if (OVR_FAILURE(result)) TraceLog(WARNING, "OVR: Could not initialize Oculus device");
+
+    result = ovr_Create(&session, &luid);
+    if (OVR_FAILURE(result))
+    {
+        TraceLog(WARNING, "OVR: Could not create Oculus session");
+        ovr_Shutdown();
+    }
+
+    hmdDesc = ovr_GetHmdDesc(session);
+    
+    TraceLog(INFO, "OVR: Product Name: %s", hmdDesc.ProductName);
+    TraceLog(INFO, "OVR: Manufacturer: %s", hmdDesc.Manufacturer);
+    TraceLog(INFO, "OVR: Product ID: %i", hmdDesc.ProductId);
+    TraceLog(INFO, "OVR: Product Type: %i", hmdDesc.Type);
+    //TraceLog(INFO, "OVR: Serial Number: %s", hmdDesc.SerialNumber);
+    TraceLog(INFO, "OVR: Resolution: %ix%i", hmdDesc.Resolution.w, hmdDesc.Resolution.h);
+    
+    // NOTE: Oculus mirror is set to defined screenWidth and screenHeight...
+    // ...ideally, it should be (hmdDesc.Resolution.w/2, hmdDesc.Resolution.h/2)
+    
+    // Initialize Oculus Buffers
+    layer = InitOculusLayer(session);   
+    buffer = LoadOculusBuffer(session, layer.width, layer.height);
+    mirror = LoadOculusMirror(session, hmdDesc.Resolution.w/2, hmdDesc.Resolution.h/2);     // NOTE: hardcoded...
+    layer.eyeLayer.ColorTexture[0] = buffer.textureChain;     //SetOculusLayerTexture(eyeLayer, buffer.textureChain);
+    
+    // Recenter OVR tracking origin
+    ovr_RecenterTrackingOrigin(session);
+}
+
+// Close Oculus Rift device
+void CloseOculusDevice(void)
+{
+    UnloadOculusMirror(session, mirror);    // Unload Oculus mirror buffer
+    UnloadOculusBuffer(session, buffer);    // Unload Oculus texture buffers
+
+    ovr_Destroy(session);   // Free Oculus session data
+    ovr_Shutdown();         // Close Oculus device connection
+}
+
+// Update Oculus Rift tracking (position and orientation)
+void UpdateOculusTracking(void)
+{
+    frameIndex++;
+
+    ovrPosef eyePoses[2];
+    ovr_GetEyePoses(session, frameIndex, ovrTrue, layer.viewScaleDesc.HmdToEyeOffset, eyePoses, &layer.eyeLayer.SensorSampleTime);
+    
+    layer.eyeLayer.RenderPose[0] = eyePoses[0];
+    layer.eyeLayer.RenderPose[1] = eyePoses[1];
+}
+
+void SetOculusMatrix(int eye)
+{
+    rlViewport(layer.eyeLayer.Viewport[eye].Pos.x, layer.eyeLayer.Viewport[eye].Pos.y, layer.eyeLayer.Viewport[eye].Size.w, layer.eyeLayer.Viewport[eye].Size.h);
+
+    Quaternion eyeRPose = (Quaternion){ layer.eyeLayer.RenderPose[eye].Orientation.x, 
+                                        layer.eyeLayer.RenderPose[eye].Orientation.y, 
+                                        layer.eyeLayer.RenderPose[eye].Orientation.z, 
+                                        layer.eyeLayer.RenderPose[eye].Orientation.w };
+    QuaternionInvert(&eyeRPose);
+    Matrix eyeOrientation = QuaternionToMatrix(eyeRPose);
+    Matrix eyeTranslation = MatrixTranslate(-layer.eyeLayer.RenderPose[eye].Position.x, 
+                                            -layer.eyeLayer.RenderPose[eye].Position.y, 
+                                            -layer.eyeLayer.RenderPose[eye].Position.z);
+
+    Matrix eyeView = MatrixMultiply(eyeTranslation, eyeOrientation);
+    Matrix modelEyeView = MatrixMultiply(modelview, eyeView);  // Using internal camera modelview matrix
+
+    SetMatrixModelview(modelEyeView);
+    SetMatrixProjection(layer.eyeProjections[eye]);
+}
+
+void BeginOculusDrawing(void)
+{
+    GLuint currentTexId;
+    int currentIndex;
+    
+    ovr_GetTextureSwapChainCurrentIndex(session, buffer.textureChain, &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
 //----------------------------------------------------------------------------------
@@ -2387,7 +2627,7 @@ static void LoadCompressedTexture(unsigned char *data, int width, int height, in
 }
 
 // Load custom shader strings and return program id
-static unsigned int LoadShaderProgram(char *vShaderStr, char *fShaderStr)
+static unsigned int LoadShaderProgram(const char *vShaderStr, const char *fShaderStr)
 {
     unsigned int program = 0;
 
@@ -2564,18 +2804,28 @@ static Shader LoadDefaultShader(void)
 
 // 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
+//     - 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)
 {
-    // Load standard shader (TODO: rewrite as char pointers)
-    Shader shader = { 0 }; //LoadShader("resources/shaders/standard.vs", "resources/shaders/standard.fs");
-
-    if (shader.id != 0) TraceLog(INFO, "[SHDR ID %i] Standard shader loaded successfully", shader.id);
-    else TraceLog(WARNING, "[SHDR ID %i] Standard shader could not be loaded", shader.id);
+    Shader shader;
+    
+    // Load standard shader (embeded in standard_shader.h)
+    shader.id = LoadShaderProgram(vStandardShaderStr, fStandardShaderStr);
 
-    if (shader.id != 0) LoadDefaultShaderLocations(&shader);
+    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;
 }
@@ -3315,10 +3565,191 @@ static Color *GenNextMipmap(Color *srcData, int srcWidth, int srcHeight)
 }
 #endif
 
+#if defined(RLGL_OCULUS_SUPPORT)
+// Load Oculus required buffers: texture-swap-chain, fbo, texture-depth
+static OculusBuffer LoadOculusBuffer(ovrSession session, int width, int height)
+{
+    OculusBuffer buffer;
+    buffer.width = width;
+    buffer.height = height;
+    
+    // Create OVR texture chain
+    ovrTextureSwapChainDesc desc = {};
+    desc.Type = ovrTexture_2D;
+    desc.ArraySize = 1;
+    desc.Width = width;
+    desc.Height = height;
+    desc.MipLevels = 1;
+    desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;   // Requires glEnable(GL_FRAMEBUFFER_SRGB);
+    desc.SampleCount = 1;
+    desc.StaticImage = ovrFalse;
+
+    ovrResult result = ovr_CreateTextureSwapChainGL(session, &desc, &buffer.textureChain);
+    
+    if (!OVR_SUCCESS(result)) TraceLog(WARNING, "OVR: Failed to create swap textures buffer");
+
+    int textureCount = 0;
+    ovr_GetTextureSwapChainLength(session, buffer.textureChain, &textureCount);
+    
+    if (!OVR_SUCCESS(result) || !textureCount) TraceLog(WARNING, "OVR: Unable to count swap chain textures");
+
+    for (int i = 0; i < textureCount; ++i)
+    {
+        GLuint chainTexId;
+        ovr_GetTextureSwapChainBufferGL(session, buffer.textureChain, i, &chainTexId);
+        glBindTexture(GL_TEXTURE_2D, chainTexId);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    }
+    
+    glBindTexture(GL_TEXTURE_2D, 0);
+    
+    /*
+    // Setup framebuffer object (using depth texture)
+    glGenFramebuffers(1, &buffer.fboId);
+    glGenTextures(1, &buffer.depthId);
+    glBindTexture(GL_TEXTURE_2D, buffer.depthId);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, buffer.width, buffer.height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
+    */
+    
+    // Setup framebuffer object (using depth renderbuffer)
+    glGenFramebuffers(1, &buffer.fboId);
+    glGenRenderbuffers(1, &buffer.depthId);
+    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, buffer.fboId);
+    glBindRenderbuffer(GL_RENDERBUFFER, buffer.depthId);
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, buffer.width, buffer.height);
+    glBindRenderbuffer(GL_RENDERBUFFER, 0);
+    glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, buffer.depthId);
+    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
+
+    return buffer;
+}
+
+// Unload texture required buffers
+static void UnloadOculusBuffer(ovrSession session, OculusBuffer buffer)
+{
+    if (buffer.textureChain)
+    {
+        ovr_DestroyTextureSwapChain(session, buffer.textureChain);
+        buffer.textureChain = NULL;
+    }
+
+    if (buffer.depthId != 0) glDeleteTextures(1, &buffer.depthId);
+    if (buffer.fboId != 0) glDeleteFramebuffers(1, &buffer.fboId);
+}
+
+// Load Oculus mirror buffers
+static OculusMirror LoadOculusMirror(ovrSession session, int width, int height)
+{
+    OculusMirror mirror;
+    mirror.width = width;
+    mirror.height = height;
+    
+    ovrMirrorTextureDesc mirrorDesc;
+    memset(&mirrorDesc, 0, sizeof(mirrorDesc));
+    mirrorDesc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
+    mirrorDesc.Width = mirror.width;
+    mirrorDesc.Height = mirror.height;
+    
+    if (!OVR_SUCCESS(ovr_CreateMirrorTextureGL(session, &mirrorDesc, &mirror.texture))) TraceLog(WARNING, "Could not create mirror texture");
+
+    glGenFramebuffers(1, &mirror.fboId);
+
+    return mirror;
+}
+
+// Unload Oculus mirror buffers
+static void UnloadOculusMirror(ovrSession session, OculusMirror mirror)
+{
+    if (mirror.fboId != 0) glDeleteFramebuffers(1, &mirror.fboId);
+    if (mirror.texture) ovr_DestroyMirrorTexture(session, mirror.texture);
+}
+
+// Copy Oculus screen buffer to mirror texture
+static void BlitOculusMirror(ovrSession session, OculusMirror mirror)
+{
+    GLuint mirrorTextureId;
+    
+    ovr_GetMirrorTextureBufferGL(session, mirror.texture, &mirrorTextureId);
+    
+    glBindFramebuffer(GL_READ_FRAMEBUFFER, mirror.fboId);
+    glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mirrorTextureId, 0);
+    glBlitFramebuffer(0, 0, mirror.width, mirror.height, 0, mirror.height, mirror.width, 0, GL_COLOR_BUFFER_BIT, GL_NEAREST);
+    glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
+}
+
+// Init Oculus layer (similar to photoshop)
+static OculusLayer InitOculusLayer(ovrSession session)
+{
+    OculusLayer layer = { 0 };
+    
+    layer.viewScaleDesc.HmdSpaceToWorldScaleInMeters = 1.0f;
+
+    memset(&layer.eyeLayer, 0, sizeof(ovrLayerEyeFov));
+    layer.eyeLayer.Header.Type = ovrLayerType_EyeFov;
+    layer.eyeLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft;
+
+    ovrEyeRenderDesc eyeRenderDescs[2];
+    
+    for (int eye = 0; eye < 2; eye++)
+    {
+        eyeRenderDescs[eye] = ovr_GetRenderDesc(session, eye, hmdDesc.DefaultEyeFov[eye]);
+        ovrMatrix4f ovrPerspectiveProjection = ovrMatrix4f_Projection(eyeRenderDescs[eye].Fov, 0.01f, 10000.0f, ovrProjection_None); //ovrProjection_ClipRangeOpenGL);
+        layer.eyeProjections[eye] = FromOvrMatrix(ovrPerspectiveProjection);      // NOTE: struct ovrMatrix4f { float M[4][4] } --> struct Matrix
+
+        layer.viewScaleDesc.HmdToEyeOffset[eye] = eyeRenderDescs[eye].HmdToEyeOffset;
+        layer.eyeLayer.Fov[eye] = eyeRenderDescs[eye].Fov;
+        
+        ovrSizei eyeSize = ovr_GetFovTextureSize(session, eye, layer.eyeLayer.Fov[eye], 1.0f);
+        layer.eyeLayer.Viewport[eye].Size = eyeSize;
+        layer.eyeLayer.Viewport[eye].Pos.x = layer.width;
+        layer.eyeLayer.Viewport[eye].Pos.y = 0;
+
+        layer.height = eyeSize.h;     //std::max(renderTargetSize.y, (uint32_t)eyeSize.h);
+        layer.width += eyeSize.w;
+    }
+    
+    return layer;
+}
+
+// Convert from Oculus ovrMatrix4f struct to raymath Matrix struct
+static Matrix FromOvrMatrix(ovrMatrix4f ovrmat)
+{
+    Matrix rmat;
+    
+    rmat.m0 = ovrmat.M[0][0];
+    rmat.m1 = ovrmat.M[1][0];
+    rmat.m2 = ovrmat.M[2][0];
+    rmat.m3 = ovrmat.M[3][0];
+    rmat.m4 = ovrmat.M[0][1];
+    rmat.m5 = ovrmat.M[1][1];
+    rmat.m6 = ovrmat.M[2][1];
+    rmat.m7 = ovrmat.M[3][1];
+    rmat.m8 = ovrmat.M[0][2];
+    rmat.m9 = ovrmat.M[1][2];
+    rmat.m10 = ovrmat.M[2][2];
+    rmat.m11 = ovrmat.M[3][2];
+    rmat.m12 = ovrmat.M[0][3];
+    rmat.m13 = ovrmat.M[1][3];
+    rmat.m14 = ovrmat.M[2][3];
+    rmat.m15 = ovrmat.M[3][3];
+    
+    MatrixTranspose(&rmat);
+    
+    return rmat;
+}
+#endif
+
 #if defined(RLGL_STANDALONE)
 // Output a trace log message
 // NOTE: Expected msgType: (0)Info, (1)Error, (2)Warning
-static void TraceLog(int msgType, const char *text, ...)
+void TraceLog(int msgType, const char *text, ...)
 {
     va_list args;
     va_start(args, text);

+ 16 - 1
examples/oculus_glfw_sample/rlgl.h

@@ -48,7 +48,7 @@
 
 // Choose opengl version here or just define it at compile time: -DGRAPHICS_API_OPENGL_33
 //#define GRAPHICS_API_OPENGL_11     // Only available on PLATFORM_DESKTOP
-//#define GRAPHICS_API_OPENGL_33     // Only available on PLATFORM_DESKTOP
+//#define GRAPHICS_API_OPENGL_33     // Only available on PLATFORM_DESKTOP or Oculus Rift CV1
 //#define GRAPHICS_API_OPENGL_ES2    // Only available on PLATFORM_ANDROID or PLATFORM_RPI or PLATFORM_WEB
 
 // Security check in case no GRAPHICS_API_OPENGL_* defined
@@ -230,6 +230,9 @@ typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion;
 
     // 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
@@ -293,6 +296,7 @@ void rlglInit(void);                            // Initialize rlgl (shaders, VAO
 void rlglClose(void);                           // De-init rlgl
 void rlglDraw(void);                            // Draw VAO/VBO
 void rlglInitGraphics(int offsetX, int offsetY, int width, int height);  // Initialize Graphics (OpenGL stuff)
+void rlglLoadExtensions(void *loader);          // Load OpenGL extensions
 
 unsigned int rlglLoadTexture(void *data, int width, int height, int textureFormat, int mipmapCount);    // Load texture in GPU
 RenderTexture2D rlglLoadRenderTexture(int width, int height);   // Load a texture to be used for rendering (fbo with color and depth attachments)
@@ -339,6 +343,17 @@ void EndBlendMode(void);                                            // End blend
 
 Light CreateLight(int type, Vector3 position, Color diffuse);       // Create a new light, initialize it and add to pool
 void DestroyLight(Light light);                                     // Destroy a light and take it out of the list
+
+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

+ 44 - 52
examples/oculus_glfw_sample/raylib_rlgl_standalone.c → examples/oculus_glfw_sample/rlgl_standalone.c

@@ -18,30 +18,23 @@
 *
 ********************************************************************************************/
 
-#define GLAD_IMPLEMENTATION
 #include "glad.h"               // Extensions loading library
 #include <GLFW/glfw3.h>         // Windows/Context and inputs management
 
 #define RLGL_STANDALONE
-#include "rlgl.h"
+#include "rlgl.h"               // rlgl library: OpenGL 1.1 immediate-mode style coding
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdarg.h>
 
 #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
-//----------------------------------------------------------------------------------
-typedef enum { LOG_INFO = 0, LOG_ERROR, LOG_WARNING, LOG_DEBUG, LOG_OTHER } TraceLogType;
 
 //----------------------------------------------------------------------------------
 // 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);
-static void TraceLog(int msgType, const char *text, ...);
 
 // Drawing functions (uses rlgl functionality)
 static void DrawGrid(int slices, float spacing);
@@ -66,10 +59,10 @@ int main(void)
     
     if (!glfwInit())
     {
-        TraceLog(LOG_WARNING, "GLFW3: Can not initialize GLFW");
-        exit(EXIT_FAILURE);
+        TraceLog(WARNING, "GLFW3: Can not initialize GLFW");
+        return 1;
     }
-    else TraceLog(LOG_INFO, "GLFW3: GLFW initialized successfully");
+    else TraceLog(INFO, "GLFW3: GLFW initialized successfully");
     
     glfwWindowHint(GLFW_SAMPLES, 4);
     glfwWindowHint(GLFW_DEPTH_BITS, 16);
@@ -83,9 +76,9 @@ int main(void)
     if (!window)
     {
         glfwTerminate();
-        exit(EXIT_FAILURE);
+        return 2;
     }
-    else TraceLog(LOG_INFO, "GLFW3: Window created successfully");
+    else TraceLog(INFO, "GLFW3: Window created successfully");
     
     glfwSetKeyCallback(window, KeyCallback);
     
@@ -95,20 +88,27 @@ int main(void)
     // Load OpenGL 3.3 extensions
     if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
     {
-        TraceLog(LOG_WARNING, "GLAD: Cannot load OpenGL extensions");
-        exit(1);
+        TraceLog(WARNING, "GLAD: Cannot load OpenGL extensions");
+        return 3;
     }
-    else TraceLog(LOG_INFO, "GLAD: OpenGL extensions loaded successfully");
+    else TraceLog(INFO, "GLAD: OpenGL extensions loaded successfully");
     //--------------------------------------------------------
     
     // 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
     
-    Vector2 size = { 200, 200 };
-    Vector3 cubePosition = { 0.0f, 0.0f, 0.0f };
+    // Initialize viewport and internal projection/modelview matrices
+    rlViewport(0, 0, screenWidth, screenHeight);
+    rlMatrixMode(RL_PROJECTION);                        // Switch to PROJECTION matrix
+    rlLoadIdentity();                                   // Reset current matrix (PROJECTION)
+    rlOrtho(0, screenWidth, screenHeight, 0, 0.0f, 1.0f); // Orthographic projection with top-left corner at (0,0)
+    rlMatrixMode(RL_MODELVIEW);                         // Switch back to MODELVIEW matrix
+    rlLoadIdentity();                                   // Reset current matrix (MODELVIEW)
+
+    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
@@ -128,29 +128,45 @@ int main(void)
         // Draw
         //----------------------------------------------------------------------------------
         rlClearScreenBuffers();             // Clear current framebuffer
+        
             // 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);
             Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up);
-            Matrix mvp = MatrixMultiply(matView, matProj);
+
+            SetMatrixModelview(matView);    // Replace internal modelview matrix by a custom one
+            SetMatrixProjection(matProj);   // Replace internal projection matrix by a custom one
 
             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(mvp);
+            rlglDraw();
             
+            // 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();
-            mvp = MatrixMultiply(matView, matProj);
             
-            // TODO: 2D drawing on Oculus Rift: requires an ovrLayerQuad layer
-            DrawRectangleV((Vector2){ 10.0f, 10.0f }, (Vector2){ 300.0f, 20.0f }, DARKGRAY);
+            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, screenHeight, 0.0, 0.0, 1.0); // Recalculate internal projection matrix
+            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);
 
             // NOTE: Internal buffers drawing (2D data)
-            rlglDraw(mvp);
+            rlglDraw();
             
         glfwSwapBuffers(window);
         glfwPollEvents();
@@ -163,7 +179,6 @@ int main(void)
     
     glfwDestroyWindow(window);
     glfwTerminate();
-    
     //--------------------------------------------------------------------------------------
     
     return 0;
@@ -176,7 +191,7 @@ int main(void)
 // GLFW3: Error callback
 static void ErrorCallback(int error, const char* description)
 {
-    TraceLog(LOG_ERROR, description);
+    TraceLog(ERROR, description);
 }
 
 // GLFW3: Keyboard callback
@@ -188,29 +203,6 @@ static void KeyCallback(GLFWwindow* window, int key, int scancode, int action, i
     }
 }
 
-// Output a trace log message
-static void TraceLog(int msgType, const char *text, ...)
-{
-    va_list args;
-    va_start(args, text);
-
-    switch(msgType)
-    {
-        case LOG_INFO: fprintf(stdout, "INFO: "); break;
-        case LOG_ERROR: fprintf(stdout, "ERROR: "); break;
-        case LOG_WARNING: fprintf(stdout, "WARNING: "); break;
-        case LOG_DEBUG: fprintf(stdout, "DEBUG: "); break;
-        default: break;
-    }
-
-    vfprintf(stdout, text, args);
-    fprintf(stdout, "\n");
-
-    va_end(args);
-
-    //if (msgType == LOG_ERROR) exit(1);
-}
-
 // Draw rectangle using rlgl OpenGL 1.1 style coding (translated to OpenGL 3.3 internally)
 static void DrawRectangleV(Vector2 position, Vector2 size, Color color)
 {

+ 496 - 0
examples/oculus_glfw_sample/rlgl_standalone_stereo.c

@@ -0,0 +1,496 @@
+/*******************************************************************************************
+*
+*   raylib [rlgl] example - Using rlgl module as standalone module
+*
+*   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
+*
+*   Compile example using:
+*   gcc -o $(NAME_PART).exe $(FILE_NAME) 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)
+*
+*   Copyright (c) 2015 Ramon Santamaria (@raysan5)
+*
+********************************************************************************************/
+
+#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
+
+#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
+//----------------------------------------------------------------------------------
+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);
+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
+//----------------------------------------------------------------------------------
+int main(void)
+{
+    // Initialization
+    //--------------------------------------------------------------------------------------
+    const int screenWidth = 1080;
+    const int screenHeight = 600;
+    
+    // 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_SAMPLES, 4);
+    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, "rlgl standalone", NULL, NULL);
+    
+    if (!window)
+    {
+        glfwTerminate();
+        return 2;
+    }
+    else TraceLog(INFO, "GLFW3: Window created successfully");
+    
+    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();
+    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");
+    
+    // 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 };
+    
+    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
+    //--------------------------------------------------------------------------------------    
+
+    // Main game loop    
+    while (!glfwWindowShouldClose(window)) 
+    {
+        // Update
+        //----------------------------------------------------------------------------------
+        // ...
+        //----------------------------------------------------------------------------------
+
+        // 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
+
+            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();
+            
+            // 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();
+            
+        glfwSwapBuffers(window);
+        glfwPollEvents();
+        //----------------------------------------------------------------------------------
+    }
+
+    // De-Initialization
+    //--------------------------------------------------------------------------------------
+    UnloadShader(distortion);
+    
+    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();
+}
+
+// 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();
+    }
+}

+ 174 - 0
examples/oculus_glfw_sample/standard_shader.h

@@ -0,0 +1,174 @@
+
+// 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";

+ 19 - 14
examples/physics_basic_rigidbody.c

@@ -5,12 +5,19 @@
 *   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)
 *
+*
+*   Compile example using:
+*   cmd /c IF NOT EXIST pthreadGC2.dll copy C:\raylib\raylib\src\external\pthread\pthreadGC2.dll $(CURRENT_DIRECTORY) /Y
+*
 *   Copyright (c) 2016 Victor Fisac and Ramon Santamaria (@raysan5)
 *
 ********************************************************************************************/
 
 #include "raylib.h"
 
+#define PHYSAC_IMPLEMENTATION
+#include "physac.h"
+
 #define MOVE_VELOCITY    5
 #define JUMP_VELOCITY    30
 
@@ -24,44 +31,41 @@ int main()
     InitWindow(screenWidth, screenHeight, "raylib [physac] example - basic rigidbody");
     InitPhysics((Vector2){ 0.0f, -9.81f/2 });      // Initialize physics module
     
-    SetTargetFPS(60);
-    
     // Debug variables
     bool isDebug = false;
     
     // Create rectangle physic object
-    PhysicObject rectangle = CreatePhysicObject((Vector2){ screenWidth*0.25f, screenHeight/2 }, 0.0f, (Vector2){ 75, 50 });
+    PhysicBody rectangle = CreatePhysicBody((Vector2){ screenWidth*0.25f, screenHeight/2 }, 0.0f, (Vector2){ 75, 50 });
     rectangle->rigidbody.enabled = true;       // Enable physic object rigidbody behaviour
     rectangle->rigidbody.applyGravity = true;
     rectangle->rigidbody.friction = 0.1f;
     rectangle->rigidbody.bounciness = 6.0f;
     
     // Create square physic object
-    PhysicObject square = CreatePhysicObject((Vector2){ screenWidth*0.75f, screenHeight/2 }, 0.0f, (Vector2){ 50, 50 });
+    PhysicBody square = CreatePhysicBody((Vector2){ screenWidth*0.75f, screenHeight/2 }, 0.0f, (Vector2){ 50, 50 });
     square->rigidbody.enabled = true;      // Enable physic object rigidbody behaviour
     square->rigidbody.applyGravity = true;
     square->rigidbody.friction = 0.1f;
     
     // Create walls physic objects
-    PhysicObject floor = CreatePhysicObject((Vector2){ screenWidth/2, screenHeight*0.95f }, 0.0f, (Vector2){ screenWidth*0.9f, 100 });
-    PhysicObject leftWall = CreatePhysicObject((Vector2){ 0.0f, screenHeight/2 }, 0.0f, (Vector2){ screenWidth*0.1f, screenHeight });
-    PhysicObject rightWall = CreatePhysicObject((Vector2){ screenWidth, screenHeight/2 }, 0.0f, (Vector2){ screenWidth*0.1f, screenHeight });
-    PhysicObject roof = CreatePhysicObject((Vector2){ screenWidth/2, screenHeight*0.05f }, 0.0f, (Vector2){ screenWidth*0.9f, 100 });
+    PhysicBody floor = CreatePhysicBody((Vector2){ screenWidth/2, screenHeight*0.95f }, 0.0f, (Vector2){ screenWidth*0.9f, 100 });
+    PhysicBody leftWall = CreatePhysicBody((Vector2){ 0.0f, screenHeight/2 }, 0.0f, (Vector2){ screenWidth*0.1f, screenHeight });
+    PhysicBody rightWall = CreatePhysicBody((Vector2){ screenWidth, screenHeight/2 }, 0.0f, (Vector2){ screenWidth*0.1f, screenHeight });
+    PhysicBody roof = CreatePhysicBody((Vector2){ screenWidth/2, screenHeight*0.05f }, 0.0f, (Vector2){ screenWidth*0.9f, 100 });
     
     // Create pplatform physic object
-    PhysicObject platform = CreatePhysicObject((Vector2){ screenWidth/2, screenHeight*0.7f }, 0.0f, (Vector2){ screenWidth*0.25f, 20 });
+    PhysicBody platform = CreatePhysicBody((Vector2){ screenWidth/2, screenHeight*0.7f }, 0.0f, (Vector2){ screenWidth*0.25f, 20 });
     
+    SetTargetFPS(60);
     //--------------------------------------------------------------------------------------
 
     // Main game loop
     while (!WindowShouldClose())    // Detect window close button or ESC key
     {
         // Update
-        //----------------------------------------------------------------------------------
-        UpdatePhysics();    // Update all created physic objects
-        
+        //----------------------------------------------------------------------------------        
         // Check rectangle movement inputs
-        if (IsKeyDown('W') && rectangle->rigidbody.isGrounded) rectangle->rigidbody.velocity.y = JUMP_VELOCITY;
+        if (IsKeyPressed('W')) rectangle->rigidbody.velocity.y = JUMP_VELOCITY;
         if (IsKeyDown('A')) rectangle->rigidbody.velocity.x = -MOVE_VELOCITY;
         else if (IsKeyDown('D')) rectangle->rigidbody.velocity.x = MOVE_VELOCITY;
         
@@ -108,6 +112,8 @@ int main()
             // Draw help message
             DrawText("Use WASD to move rectangle and ARROWS to move square", screenWidth/2 - MeasureText("Use WASD to move rectangle and ARROWS to move square", 20)/2, screenHeight*0.075f, 20, LIGHTGRAY);
 
+            DrawFPS(10, 10);
+            
         EndDrawing();
         //----------------------------------------------------------------------------------
     }
@@ -115,7 +121,6 @@ int main()
     // De-Initialization
     //--------------------------------------------------------------------------------------
     ClosePhysics();       // Unitialize physics (including all loaded objects)
-    
     CloseWindow();        // Close window and OpenGL context
     //--------------------------------------------------------------------------------------
 

+ 20 - 15
examples/physics_forces.c

@@ -5,20 +5,25 @@
 *   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)
 *
+*   NOTE: This example requires raylib module [rlgl]
+*
+*   Compile example using:
+*   cmd /c IF NOT EXIST pthreadGC2.dll copy C:\raylib\raylib\src\external\pthread\pthreadGC2.dll $(CURRENT_DIRECTORY) /Y
+*
 *   Copyright (c) 2016 Victor Fisac and Ramon Santamaria (@raysan5)
 *
 ********************************************************************************************/
 
 #include "raylib.h"
-#include "math.h"
+
+#define PHYSAC_IMPLEMENTATION
+#include "physac.h"
 
 #define FORCE_AMOUNT        5.0f
 #define FORCE_RADIUS        150
 #define LINE_LENGTH         75
 #define TRIANGLE_LENGTH     12
 
-void DrawRigidbodyCircle(PhysicObject obj, Color color);
-
 int main()
 {
     // Initialization
@@ -29,27 +34,25 @@ int main()
     InitWindow(screenWidth, screenHeight, "raylib [physac] example - forces");
     InitPhysics((Vector2){ 0.0f, -9.81f/2 });      // Initialize physics module
     
-    SetTargetFPS(60);
-    
     // Global variables
     Vector2 mousePosition;
     bool isDebug = false;
     
     // Create rectangle physic objects
-    PhysicObject rectangles[3];
+    PhysicBody rectangles[3];
     for (int i = 0; i < 3; i++)
     {
-        rectangles[i] = CreatePhysicObject((Vector2){ screenWidth/4*(i+1), (((i % 2) == 0) ? (screenHeight/3) : (screenHeight/1.5f)) }, 0.0f, (Vector2){ 50, 50 });
+        rectangles[i] = CreatePhysicBody((Vector2){ screenWidth/4*(i+1), (((i % 2) == 0) ? (screenHeight/3) : (screenHeight/1.5f)) }, 0.0f, (Vector2){ 50, 50 });
         rectangles[i]->rigidbody.enabled = true;       // Enable physic object rigidbody behaviour
         rectangles[i]->rigidbody.friction = 0.1f;
     }
     
     // Create circles physic objects
     // NOTE: when creating circle physic objects, transform.scale must be { 0, 0 } and object radius must be defined in collider.radius and use this value to draw the circle.
-    PhysicObject circles[3];
+    PhysicBody circles[3];
     for (int i = 0; i < 3; i++)
     {
-        circles[i] = CreatePhysicObject((Vector2){ screenWidth/4*(i+1), (((i % 2) == 0) ? (screenHeight/1.5f) : (screenHeight/4)) }, 0.0f, (Vector2){ 0, 0 });
+        circles[i] = CreatePhysicBody((Vector2){ screenWidth/4*(i+1), (((i % 2) == 0) ? (screenHeight/1.5f) : (screenHeight/4)) }, 0.0f, (Vector2){ 0, 0 });
         circles[i]->rigidbody.enabled = true;       // Enable physic object rigidbody behaviour
         circles[i]->rigidbody.friction = 0.1f;
         circles[i]->collider.type = COLLIDER_CIRCLE;
@@ -57,11 +60,12 @@ int main()
     }
     
     // Create walls physic objects
-    PhysicObject leftWall = CreatePhysicObject((Vector2){ -25, screenHeight/2 }, 0.0f, (Vector2){ 50, screenHeight });
-    PhysicObject rightWall = CreatePhysicObject((Vector2){ screenWidth + 25, screenHeight/2 }, 0.0f, (Vector2){ 50, screenHeight });
-    PhysicObject topWall = CreatePhysicObject((Vector2){ screenWidth/2, -25 }, 0.0f, (Vector2){ screenWidth, 50 });
-    PhysicObject bottomWall = CreatePhysicObject((Vector2){ screenWidth/2, screenHeight + 25 }, 0.0f, (Vector2){ screenWidth, 50 });
+    PhysicBody leftWall = CreatePhysicBody((Vector2){ -25, screenHeight/2 }, 0.0f, (Vector2){ 50, screenHeight });
+    PhysicBody rightWall = CreatePhysicBody((Vector2){ screenWidth + 25, screenHeight/2 }, 0.0f, (Vector2){ 50, screenHeight });
+    PhysicBody topWall = CreatePhysicBody((Vector2){ screenWidth/2, -25 }, 0.0f, (Vector2){ screenWidth, 50 });
+    PhysicBody bottomWall = CreatePhysicBody((Vector2){ screenWidth/2, screenHeight + 25 }, 0.0f, (Vector2){ screenWidth, 50 });
     
+    SetTargetFPS(60);
     //--------------------------------------------------------------------------------------
 
     // Main game loop
@@ -69,7 +73,6 @@ int main()
     {
         // Update
         //----------------------------------------------------------------------------------
-        UpdatePhysics();    // Update all created physic objects
         
         // Update mouse position value
         mousePosition = GetMousePosition();
@@ -166,7 +169,9 @@ int main()
             
             // Draw help messages
             DrawText("Use LEFT MOUSE BUTTON to apply a force", screenWidth/2 - MeasureText("Use LEFT MOUSE BUTTON to apply a force", 20)/2, screenHeight*0.075f, 20, LIGHTGRAY);
-            DrawText("Use R to reset objects position", screenWidth/2 - MeasureText("Use R to reset objects position", 20)/2, screenHeight*0.875f, 20, GRAY);    
+            DrawText("Use R to reset objects position", screenWidth/2 - MeasureText("Use R to reset objects position", 20)/2, screenHeight*0.875f, 20, GRAY);
+            
+            DrawFPS(10, 10);
 
         EndDrawing();
         //----------------------------------------------------------------------------------

+ 1 - 1
examples/resources/shaders/glsl100/bloom.fs

@@ -26,7 +26,7 @@ void main()
     }
     
     // Texel color fetching from texture sampler
-    vec4 texelColor = texture(texture0, fragTexCoord);
+    vec4 texelColor = texture2D(texture0, fragTexCoord);
     
     // Calculate final fragment color
     if (texelColor.r < 0.3) tc = sum*sum*0.012 + texelColor;

+ 54 - 0
examples/resources/shaders/glsl100/distortion.fs

@@ -0,0 +1,54 @@
+#version 100
+
+precision mediump float;
+
+// Input vertex attributes (from vertex shader)
+varying vec2 fragTexCoord;
+
+// Input uniform values
+uniform sampler2D texture0;
+
+// 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);
+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);
+
+void main()
+{
+    // The following two variables need to be set per eye
+    vec2 LensCenter = fragTexCoord.x < 0.5 ? LeftLensCenter : RightLensCenter;
+    vec2 ScreenCenter = fragTexCoord.x < 0.5 ? LeftScreenCenter : RightScreenCenter;
+    
+    // Scales input texture coordinates for distortion: vec2 HmdWarp(vec2 fragTexCoord, vec2 LensCenter)
+    vec2 theta = (fragTexCoord - LensCenter)*ScaleIn;   // Scales to [-1, 1]
+    float rSq = theta.x*theta.x + theta.y*theta.y;
+    vec2 theta1 = theta*(HmdWarpParam.x + HmdWarpParam.y*rSq + HmdWarpParam.z*rSq*rSq + HmdWarpParam.w*rSq*rSq*rSq);
+    //vec2 tc = LensCenter + Scale*theta1;
+    
+    // Detect whether blue texture coordinates are out of range since these will scaled out the furthest
+    vec2 thetaBlue = theta1*(ChromaAbParam.z + ChromaAbParam.w*rSq);
+    vec2 tcBlue = LensCenter + Scale*thetaBlue;
+
+    if (any(bvec2(clamp(tcBlue, ScreenCenter - vec2(0.25, 0.5), ScreenCenter + vec2(0.25, 0.5)) - tcBlue))) gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+    else
+    {
+        // Do blue texture lookup
+        float blue = texture2D(texture0, tcBlue).b;
+
+        // Do green lookup (no scaling)
+        vec2 tcGreen = LensCenter + Scale*theta1;
+        float green = texture2D(texture0, tcGreen).g;
+
+        // Do red scale and lookup
+        vec2 thetaRed = theta1*(ChromaAbParam.x + ChromaAbParam.y*rSq);
+        vec2 tcRed = LensCenter + Scale*thetaRed;
+        float red = texture2D(texture0, tcRed).r;
+
+        gl_FragColor = vec4(red, green, blue, 1.0);
+    }
+}

+ 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 = texture(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);;
 }

+ 56 - 0
examples/resources/shaders/glsl330/distortion.fs

@@ -0,0 +1,56 @@
+#version 330
+
+// Input vertex attributes (from vertex shader)
+in vec2 fragTexCoord;
+
+// Input uniform values
+uniform sampler2D texture0;
+
+// Output fragment color
+out vec4 finalColor;
+
+// 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);
+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);
+
+void main()
+{
+    // The following two variables need to be set per eye
+    vec2 LensCenter = fragTexCoord.x < 0.5 ? LeftLensCenter : RightLensCenter;
+    vec2 ScreenCenter = fragTexCoord.x < 0.5 ? LeftScreenCenter : RightScreenCenter;
+    
+    // Scales input texture coordinates for distortion: vec2 HmdWarp(vec2 fragTexCoord, vec2 LensCenter)
+    vec2 theta = (fragTexCoord - LensCenter)*ScaleIn;   // Scales to [-1, 1]
+    float rSq = theta.x*theta.x + theta.y*theta.y;
+    vec2 theta1 = theta*(HmdWarpParam.x + HmdWarpParam.y*rSq + HmdWarpParam.z*rSq*rSq + HmdWarpParam.w*rSq*rSq*rSq);
+    //vec2 tc = LensCenter + Scale*theta1;
+    
+    // Detect whether blue texture coordinates are out of range since these will scaled out the furthest
+    vec2 thetaBlue = theta1*(ChromaAbParam.z + ChromaAbParam.w*rSq);
+    vec2 tcBlue = LensCenter + Scale*thetaBlue;
+
+    if (any(bvec2(clamp(tcBlue, ScreenCenter - vec2(0.25, 0.5), ScreenCenter + vec2(0.25, 0.5)) - tcBlue))) finalColor = vec4(0.0, 0.0, 0.0, 1.0);
+    else
+    {
+        // Do blue texture lookup
+        float blue = texture(texture0, tcBlue).b;
+
+        // Do green lookup (no scaling)
+        vec2 tcGreen = LensCenter + Scale*theta1;
+        float green = texture(texture0, tcGreen).g;
+
+        // Do red scale and lookup
+        vec2 thetaRed = theta1*(ChromaAbParam.x + ChromaAbParam.y*rSq);
+        vec2 tcRed = LensCenter + Scale*thetaRed;
+        float red = texture(texture0, tcRed).r;
+
+        finalColor = vec4(red, green, blue, 1.0);
+    }
+}
+

+ 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);;
 }

+ 1 - 1
examples/shaders_custom_uniform.c

@@ -34,7 +34,7 @@ int main()
 
     Model dwarf = LoadModel("resources/model/dwarf.obj");                   // Load OBJ model
     Texture2D texture = LoadTexture("resources/model/dwarf_diffuse.png");   // Load model texture (diffuse map)
-    SetModelTexture(&dwarf, texture);                                       // Bind texture to model
+    dwarf.material.texDiffuse = texture;                                    // Set dwarf model diffuse texture
 
     Vector3 position = { 0.0f, 0.0f, 0.0f };                                // Set model position
     

+ 1 - 1
examples/shaders_postprocessing.c

@@ -34,7 +34,7 @@ int main()
     
     Model dwarf = LoadModel("resources/model/dwarf.obj");                   // Load OBJ model
     Texture2D texture = LoadTexture("resources/model/dwarf_diffuse.png");   // Load model texture (diffuse map)
-    SetModelTexture(&dwarf, texture);                                       // Bind texture to model
+    dwarf.material.texDiffuse = texture;                                    // Set dwarf model diffuse texture
 
     Vector3 position = { 0.0f, 0.0f, 0.0f };                                // Set model position
     

+ 2 - 2
examples/shaders_standard_lighting.c

@@ -22,8 +22,8 @@ int main()
 {
     // Initialization
     //--------------------------------------------------------------------------------------
-    int screenWidth = 1280;
-    int screenHeight = 720;
+    int screenWidth = 800;
+    int screenHeight = 450;
     
     SetConfigFlags(FLAG_MSAA_4X_HINT);      // Enable Multi Sampling Anti Aliasing 4x (if available)
 

+ 2 - 2
games/raylib_demo/raylib_demo.c

@@ -202,8 +202,8 @@ int main()
     camera = (Camera){{ 0.0, 12.0, 15.0 }, { 0.0, 3.0, 0.0 }, { 0.0, 1.0, 0.0 }};
 
     catTexture = LoadTexture("resources/catsham.png");   // Load model texture
-    cat = LoadModel("resources/cat.obj");                 // Load OBJ model
-    SetModelTexture(&cat, catTexture);
+    cat = LoadModel("resources/cat.obj");                // Load OBJ model
+    cat.material.texDiffuse = texture;                   // Set cat model diffuse texture
     
     fxWav = LoadSound("resources/audio/weird.wav");         // Load WAV audio file
     fxOgg = LoadSound("resources/audio/tanatana.ogg");      // Load OGG audio file

BIN
release/android/armeabi/libraylib.a


+ 896 - 0
release/android/raylib.h

@@ -0,0 +1,896 @@
+/**********************************************************************************************
+*
+*   raylib 1.5.0 (www.raylib.com)
+*
+*   A simple and easy-to-use library to learn videogames programming
+*
+*   Features:
+*     Library written in plain C code (C99)
+*     Uses C# PascalCase/camelCase notation
+*     Hardware accelerated with OpenGL (1.1, 3.3 or ES2)
+*     Unique OpenGL abstraction layer [rlgl]
+*     Powerful fonts module with SpriteFonts support (including AngelCode fonts and TTF)
+*     Multiple textures support, including compressed formats and mipmaps generation
+*     Basic 3d support for Shapes, Models, Heightmaps and Billboards
+*     Powerful math module for Vector and Matrix operations [raymath]
+*     Audio loading and playing with streaming support (WAV and OGG)
+*     Multiplatform support, including Android devices, Raspberry Pi and HTML5
+*
+*   Used external libs:
+*     GLFW3 (www.glfw.org) for window/context management and input
+*     GLAD for OpenGL extensions loading (3.3 Core profile, only PLATFORM_DESKTOP)
+*     stb_image (Sean Barret) for images loading (JPEG, PNG, BMP, TGA, PSD, GIF, HDR, PIC)
+*     stb_image_write (Sean Barret) for image writting (PNG)
+*     stb_vorbis (Sean Barret) for ogg audio loading
+*     stb_truetype (Sean Barret) for ttf fonts loading
+*     OpenAL Soft for audio device/context management
+*     tinfl for data decompression (DEFLATE algorithm)
+*
+*   Some design decisions:
+*     32bit Colors - All defined color are always RGBA (struct Color is 4 byte)
+*     One custom default font is loaded automatically when InitWindow()
+*     If using OpenGL 3.3 or ES2, several vertex buffers (VAO/VBO) are created to manage lines-triangles-quads
+*     If using OpenGL 3.3 or ES2, two default shaders are loaded automatically (internally defined)
+*
+*   -- LICENSE --
+*
+*   raylib is licensed under an unmodified zlib/libpng license, which is an OSI-certified,
+*   BSD-like license that allows static linking with closed source software:
+*
+*   Copyright (c) 2013 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 RAYLIB_H
+#define RAYLIB_H
+
+// Choose your platform here or just define it at compile time: -DPLATFORM_DESKTOP
+//#define PLATFORM_DESKTOP      // Windows, Linux or OSX
+//#define PLATFORM_ANDROID      // Android device
+//#define PLATFORM_RPI          // Raspberry Pi
+//#define PLATFORM_WEB          // HTML5 (emscripten, asm.js)
+//#define PLATFORM_OCULUS       // Oculus Rift CV1
+
+// Security check in case no PLATFORM_* defined
+#if !defined(PLATFORM_DESKTOP) && !defined(PLATFORM_ANDROID) && !defined(PLATFORM_RPI) && !defined(PLATFORM_WEB)
+    #define PLATFORM_DESKTOP
+#endif
+
+#if defined(PLATFORM_ANDROID)
+    typedef struct android_app; // Define android_app struct (android_native_app_glue.h)
+#endif
+
+//----------------------------------------------------------------------------------
+// Some basic Defines
+//----------------------------------------------------------------------------------
+#ifndef PI
+    #define PI 3.14159265358979323846
+#endif
+
+#define DEG2RAD (PI/180.0f)
+#define RAD2DEG (180.0f/PI)
+
+// raylib Config Flags
+#define FLAG_FULLSCREEN_MODE    1
+#define FLAG_SHOW_LOGO          2
+#define FLAG_SHOW_MOUSE_CURSOR  4
+#define FLAG_CENTERED_MODE      8
+#define FLAG_MSAA_4X_HINT      16
+#define FLAG_VSYNC_HINT        32
+
+// Keyboard Function Keys
+#define KEY_SPACE            32
+#define KEY_ESCAPE          256
+#define KEY_ENTER           257
+#define KEY_BACKSPACE       259
+#define KEY_RIGHT           262
+#define KEY_LEFT            263
+#define KEY_DOWN            264
+#define KEY_UP              265
+#define KEY_F1              290
+#define KEY_F2              291
+#define KEY_F3              292
+#define KEY_F4              293
+#define KEY_F5              294
+#define KEY_F6              295
+#define KEY_F7              296
+#define KEY_F8              297
+#define KEY_F9              298
+#define KEY_F10             299
+#define KEY_F11             300
+#define KEY_F12             301
+#define KEY_LEFT_SHIFT      340
+#define KEY_LEFT_CONTROL    341
+#define KEY_LEFT_ALT        342
+#define KEY_RIGHT_SHIFT     344
+#define KEY_RIGHT_CONTROL   345
+#define KEY_RIGHT_ALT       346
+
+// Keyboard Alpha Numeric Keys
+#define KEY_ZERO             48
+#define KEY_ONE              49
+#define KEY_TWO              50
+#define KEY_THREE            51
+#define KEY_FOUR             52
+#define KEY_FIVE             53
+#define KEY_SIX              54
+#define KEY_SEVEN            55
+#define KEY_EIGHT            56
+#define KEY_NINE             57
+#define KEY_A                65
+#define KEY_B                66
+#define KEY_C                67
+#define KEY_D                68
+#define KEY_E                69
+#define KEY_F                70
+#define KEY_G                71
+#define KEY_H                72
+#define KEY_I                73
+#define KEY_J                74
+#define KEY_K                75
+#define KEY_L                76
+#define KEY_M                77
+#define KEY_N                78
+#define KEY_O                79
+#define KEY_P                80
+#define KEY_Q                81
+#define KEY_R                82
+#define KEY_S                83
+#define KEY_T                84
+#define KEY_U                85
+#define KEY_V                86
+#define KEY_W                87
+#define KEY_X                88
+#define KEY_Y                89
+#define KEY_Z                90
+
+// Mouse Buttons
+#define MOUSE_LEFT_BUTTON     0
+#if defined(PLATFORM_WEB)
+    #define MOUSE_RIGHT_BUTTON    2
+    #define MOUSE_MIDDLE_BUTTON   1
+#else
+    #define MOUSE_RIGHT_BUTTON    1
+    #define MOUSE_MIDDLE_BUTTON   2
+#endif
+
+// Touch points registered
+#define MAX_TOUCH_POINTS     2
+
+// Gamepad Number
+#define GAMEPAD_PLAYER1       0
+#define GAMEPAD_PLAYER2       1
+#define GAMEPAD_PLAYER3       2     // Not supported
+#define GAMEPAD_PLAYER4       3     // Not supported
+
+// Gamepad Buttons
+// NOTE: Adjusted for a PS3 USB Controller
+#define GAMEPAD_BUTTON_A        2
+#define GAMEPAD_BUTTON_B        1
+#define GAMEPAD_BUTTON_X        3
+#define GAMEPAD_BUTTON_Y        4
+#define GAMEPAD_BUTTON_R1       7
+#define GAMEPAD_BUTTON_R2       5
+#define GAMEPAD_BUTTON_L1       6
+#define GAMEPAD_BUTTON_L2       8
+#define GAMEPAD_BUTTON_SELECT   9
+#define GAMEPAD_BUTTON_START   10
+
+// 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
+#define ANDROID_MENU            82
+#define ANDROID_VOLUME_UP       24
+#define ANDROID_VOLUME_DOWN     25
+
+// Some Basic Colors
+// NOTE: Custom raylib color palette for amazing visuals on WHITE background
+#define LIGHTGRAY  (Color){ 200, 200, 200, 255 }   // Light Gray
+#define GRAY       (Color){ 130, 130, 130, 255 }   // Gray
+#define DARKGRAY   (Color){ 80, 80, 80, 255 }      // Dark Gray
+#define YELLOW     (Color){ 253, 249, 0, 255 }     // Yellow
+#define GOLD       (Color){ 255, 203, 0, 255 }     // Gold
+#define ORANGE     (Color){ 255, 161, 0, 255 }     // Orange
+#define PINK       (Color){ 255, 109, 194, 255 }   // Pink
+#define RED        (Color){ 230, 41, 55, 255 }     // Red
+#define MAROON     (Color){ 190, 33, 55, 255 }     // Maroon
+#define GREEN      (Color){ 0, 228, 48, 255 }      // Green
+#define LIME       (Color){ 0, 158, 47, 255 }      // Lime
+#define DARKGREEN  (Color){ 0, 117, 44, 255 }      // Dark Green
+#define SKYBLUE    (Color){ 102, 191, 255, 255 }   // Sky Blue
+#define BLUE       (Color){ 0, 121, 241, 255 }     // Blue
+#define DARKBLUE   (Color){ 0, 82, 172, 255 }      // Dark Blue
+#define PURPLE     (Color){ 200, 122, 255, 255 }   // Purple
+#define VIOLET     (Color){ 135, 60, 190, 255 }    // Violet
+#define DARKPURPLE (Color){ 112, 31, 126, 255 }    // Dark Purple
+#define BEIGE      (Color){ 211, 176, 131, 255 }   // Beige
+#define BROWN      (Color){ 127, 106, 79, 255 }    // Brown
+#define DARKBROWN  (Color){ 76, 63, 47, 255 }      // Dark Brown
+
+#define WHITE      (Color){ 255, 255, 255, 255 }   // White
+#define BLACK      (Color){ 0, 0, 0, 255 }         // Black
+#define BLANK      (Color){ 0, 0, 0, 0 }           // Blank (Transparent)
+#define MAGENTA    (Color){ 255, 0, 255, 255 }     // Magenta
+#define RAYWHITE   (Color){ 245, 245, 245, 255 }   // My own White (raylib logo)
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+#ifndef __cplusplus
+// Boolean type
+    #if !defined(_STDBOOL_H)
+        typedef enum { false, true } bool;
+        #define _STDBOOL_H
+    #endif
+#endif
+
+// byte type
+typedef unsigned char byte;
+
+// 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;
+
+// Color type, RGBA (32bit)
+typedef struct Color {
+    unsigned char r;
+    unsigned char g;
+    unsigned char b;
+    unsigned char a;
+} Color;
+
+// Rectangle type
+typedef struct Rectangle {
+    int x;
+    int y;
+    int width;
+    int height;
+} Rectangle;
+
+// Image type, bpp always RGBA (32bit)
+// NOTE: Data stored in CPU memory (RAM)
+typedef struct Image {
+    void *data;             // Image raw data
+    int width;              // Image base width
+    int height;             // Image base height
+    int mipmaps;            // Mipmap levels, 1 by default
+    int format;             // Data format (TextureFormat)
+} Image;
+
+// Texture2D type, bpp always RGBA (32bit)
+// 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;
+
+// SpriteFont type, includes texture and charSet array data
+typedef struct SpriteFont {
+    Texture2D texture;      // Font texture
+    int size;               // Base size (default chars height)
+    int numChars;           // Number of characters
+    int *charValues;        // Characters values array
+    Rectangle *charRecs;    // Characters rectangles within the texture
+    Vector2 *charOffsets;   // Characters offsets (on drawing)
+    int *charAdvanceX;      // Characters x advance (on drawing)
+} SpriteFont;
+
+// 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;
+
+// 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;            // minimum vertex box-corner
+    Vector3 max;            // maximum vertex box-corner
+} BoundingBox;
+
+// 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 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)
+    
+    // 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
+typedef struct Material {
+    Shader shader;          // Standard shader (supports 3 map textures)
+
+    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;       // Diffuse color
+    Color colAmbient;       // Ambient color
+    Color colSpecular;      // Specular color
+    
+    float glossiness;       // Glossiness level (Ranges from 0 to 1000)
+} Material;
+
+// Model type
+typedef struct Model {
+    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
+    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;
+
+// Ray type (useful for raycast)
+typedef struct Ray {
+    Vector3 position;       // Ray position (origin)
+    Vector3 direction;      // Ray direction
+} Ray;
+
+// Sound source type
+typedef struct 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;    // Samples per second to be played
+    short bitsPerSample;        // Sample size in bits
+    short channels;
+} Wave;
+
+typedef int RawAudioContext;
+
+// Texture formats
+// NOTE: Support depends on OpenGL version and platform
+typedef enum {
+    UNCOMPRESSED_GRAYSCALE = 1,     // 8 bit per pixel (no alpha)
+    UNCOMPRESSED_GRAY_ALPHA,        // 16 bpp (2 channels)
+    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;
+
+// Color blending modes (pre-defined)
+typedef enum { BLEND_ALPHA = 0, BLEND_ADDITIVE, BLEND_MULTIPLIED } BlendMode;
+
+// Gestures type
+// NOTE: It could be used as flags to enable only some gestures
+typedef enum {
+    GESTURE_NONE        = 0,
+    GESTURE_TAP         = 1,
+    GESTURE_DOUBLETAP   = 2,
+    GESTURE_HOLD        = 4,
+    GESTURE_DRAG        = 8,
+    GESTURE_SWIPE_RIGHT = 16,
+    GESTURE_SWIPE_LEFT  = 32,
+    GESTURE_SWIPE_UP    = 64,
+    GESTURE_SWIPE_DOWN  = 128,
+    GESTURE_PINCH_IN    = 256,
+    GESTURE_PINCH_OUT   = 512
+} Gestures;
+
+// Touch action (fingers or mouse)
+typedef enum { TOUCH_UP, TOUCH_DOWN, TOUCH_MOVE } TouchAction;
+
+// Gesture events
+// NOTE: MAX_TOUCH_POINTS fixed to 2
+typedef struct GestureEvent {
+    int touchAction;
+    int pointCount;
+    int pointerId[MAX_TOUCH_POINTS];
+    Vector2 position[MAX_TOUCH_POINTS];
+} GestureEvent;
+
+// Camera system modes
+typedef enum { CAMERA_CUSTOM = 0, CAMERA_FREE, CAMERA_ORBITAL, CAMERA_FIRST_PERSON, CAMERA_THIRD_PERSON } CameraMode;
+
+#ifdef __cplusplus
+extern "C" {            // Prevents name mangling of functions
+#endif
+
+//------------------------------------------------------------------------------------
+// Global Variables Definition
+//------------------------------------------------------------------------------------
+// It's lonely here...
+
+//------------------------------------------------------------------------------------
+// Window and Graphics Device Functions (Module: core)
+//------------------------------------------------------------------------------------
+#if defined(PLATFORM_ANDROID)
+void InitWindow(int width, int height, struct android_app *state);  // Init Android Activity and OpenGL Graphics
+#elif defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
+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)
+void ToggleFullscreen(void);                                // Fullscreen toggle (only PLATFORM_DESKTOP)
+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 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 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)
+float GetFPS(void);                                         // Returns current FPS
+float GetFrameTime(void);                                   // Returns time in seconds for one frame
+
+Color GetColor(int hexValue);                               // Returns a Color struct from hexadecimal value
+int GetHexValue(Color color);                               // Returns hexadecimal value for a Color
+float *ColorToFloat(Color color);                           // Converts Color to float array and normalizes
+float *VectorToFloat(Vector3 vec);                          // Converts Vector3 to float array
+float *MatrixToFloat(Matrix mat);                           // Converts Matrix to float array
+
+int GetRandomValue(int min, int max);                       // Returns a random value between min and max (both included)
+Color Fade(Color color, float alpha);                       // Color fade-in or fade-out, alpha goes from 0.0f to 1.0f
+
+void SetConfigFlags(char flags);                            // Setup some window configuration flags
+void ShowLogo(void);                                        // Activates raylib logo at startup (can be done with flags)
+
+bool IsFileDropped(void);                                   // Check if a file have been dropped into window
+char **GetDroppedFiles(int *count);                         // Retrieve dropped files into window
+void ClearDroppedFiles(void);                               // Clear dropped files paths buffer
+
+void StorageSaveValue(int position, int value);             // Storage save integer value (to defined position)
+int StorageLoadValue(int position);                         // Storage load integer value (from defined position)
+
+//------------------------------------------------------------------------------------
+// Input Handling Functions (Module: core)
+//------------------------------------------------------------------------------------
+#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
+bool IsKeyPressed(int key);                             // Detect if a key has been pressed once
+bool IsKeyDown(int key);                                // Detect if a key is being pressed
+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
+bool IsMouseButtonReleased(int button);                 // Detect if a mouse button has been released once
+bool IsMouseButtonUp(int button);                       // Detect if a mouse button is NOT being pressed
+int GetMouseX(void);                                    // Returns mouse position X
+int GetMouseY(void);                                    // Returns mouse position Y
+Vector2 GetMousePosition(void);                         // Returns mouse position XY
+void SetMousePosition(Vector2 position);                // Set mouse position XY
+int GetMouseWheelMove(void);                            // Returns mouse wheel movement Y
+
+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)
+
+#if defined(PLATFORM_ANDROID)
+bool IsButtonPressed(int button);                       // Detect if an android physic button has been pressed
+bool IsButtonDown(int button);                          // Detect if an android physic button is being pressed
+bool IsButtonReleased(int button);                      // Detect if an android physic button has been released
+#endif
+
+//------------------------------------------------------------------------------------
+// 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 (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
+
+float GetGestureHoldDuration(void);                     // Get gesture hold time in milliseconds
+Vector2 GetGestureDragVector(void);                     // Get gesture drag vector
+float GetGestureDragAngle(void);                        // Get gesture drag angle
+Vector2 GetGesturePinchVector(void);                    // Get gesture pinch delta
+float GetGesturePinchAngle(void);                       // Get gesture pinch angle
+
+//------------------------------------------------------------------------------------
+// Camera System Functions (Module: camera)
+//------------------------------------------------------------------------------------
+void SetCameraMode(int mode);                               // Set camera mode (multiple camera modes available)
+void UpdateCamera(Camera *camera);                          // Update camera (player position is ignored)
+void UpdateCameraPlayer(Camera *camera, Vector3 *position); // Update camera and player position (1st person and 3rd person cameras)
+
+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)
+void SetCameraSmoothZoomControl(int szKey);                 // Set camera smooth zoom key to combine with mouse (free camera)
+
+void SetCameraMoveControls(int frontKey, int backKey, 
+                           int leftKey, int rightKey, 
+                           int upKey, int downKey);         // Set camera move controls (1st person and 3rd person cameras)
+void SetCameraMouseSensitivity(float sensitivity);          // Set camera mouse sensitivity (1st person and 3rd person cameras)
+
+//------------------------------------------------------------------------------------
+// Basic Shapes Drawing Functions (Module: shapes)
+//------------------------------------------------------------------------------------
+void DrawPixel(int posX, int posY, Color color);                                                   // Draw a pixel
+void DrawPixelV(Vector2 position, Color color);                                                    // Draw a pixel (Vector version)
+void DrawLine(int startPosX, int startPosY, int endPosX, int endPosY, Color color);                // Draw a line
+void DrawLineV(Vector2 startPos, Vector2 endPos, Color color);                                     // Draw a line (Vector version)
+void DrawCircle(int centerX, int centerY, float radius, Color color);                              // Draw a color-filled circle
+void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2);       // Draw a gradient-filled circle
+void DrawCircleV(Vector2 center, float radius, Color color);                                       // Draw a color-filled circle (Vector version)
+void DrawCircleLines(int centerX, int centerY, float radius, Color color);                         // Draw circle outline
+void DrawRectangle(int posX, int posY, int width, int height, Color color);                        // Draw a color-filled rectangle
+void DrawRectangleRec(Rectangle rec, Color color);                                                 // Draw a color-filled rectangle
+void DrawRectangleGradient(int posX, int posY, int width, int height, Color color1, Color color2); // Draw a gradient-filled rectangle
+void DrawRectangleV(Vector2 position, Vector2 size, Color color);                                  // Draw a color-filled rectangle (Vector version)
+void DrawRectangleLines(int posX, int posY, int width, int height, Color color);                   // Draw rectangle outline
+void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color);                                // Draw a color-filled triangle
+void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color);                           // Draw triangle outline
+void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color);               // Draw a regular polygon (Vector version)
+void DrawPolyEx(Vector2 *points, int numPoints, Color color);                                      // Draw a closed polygon defined by points
+void DrawPolyExLines(Vector2 *points, int numPoints, Color color);                                 // Draw polygon lines
+
+bool CheckCollisionRecs(Rectangle rec1, Rectangle rec2);                                           // Check collision between two rectangles
+bool CheckCollisionCircles(Vector2 center1, float radius1, Vector2 center2, float radius2);        // Check collision between two circles
+bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec);                         // Check collision between circle and rectangle
+Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2);                                         // Get collision rectangle for two rectangles collision
+bool CheckCollisionPointRec(Vector2 point, Rectangle rec);                                         // Check if point is inside rectangle
+bool CheckCollisionPointCircle(Vector2 point, Vector2 center, float radius);                       // Check if point is inside circle
+bool CheckCollisionPointTriangle(Vector2 point, Vector2 p1, Vector2 p2, Vector2 p3);               // Check if point is inside a triangle
+
+//------------------------------------------------------------------------------------
+// Texture Loading and Drawing Functions (Module: textures)
+//------------------------------------------------------------------------------------
+Image LoadImage(const char *fileName);                                                             // Load an image into CPU memory (RAM)
+Image LoadImageEx(Color *pixels, int width, int height);                                           // Load image data from Color array data (RGBA - 32bit)
+Image LoadImageRaw(const char *fileName, int width, int height, int format, int headerSize);       // Load image data from RAW file
+Image LoadImageFromRES(const char *rresName, int resId);                                           // Load an image from rRES file (raylib Resource)
+Texture2D LoadTexture(const char *fileName);                                                       // Load an image as texture into GPU memory
+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)
+void ImageFormat(Image *image, int newFormat);                                                     // Convert image data to desired format
+void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp);                            // Dither image data to 16bpp or lower (Floyd-Steinberg dithering)
+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 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 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
+void UpdateTexture(Texture2D texture, void *pixels);                                               // Update GPU texture with new data
+
+void DrawTexture(Texture2D texture, int posX, int posY, Color tint);                               // Draw a Texture2D
+void DrawTextureV(Texture2D texture, Vector2 position, Color tint);                                // Draw a Texture2D with position defined as Vector2
+void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, float scale, Color tint);  // Draw a Texture2D with extended parameters
+void DrawTextureRec(Texture2D texture, Rectangle sourceRec, Vector2 position, Color tint);         // Draw a part of a texture defined by a rectangle
+void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle destRec, Vector2 origin,     // Draw a part of a texture defined by a rectangle with 'pro' parameters
+                    float rotation, Color tint);
+
+//------------------------------------------------------------------------------------
+// Font Loading and Text Drawing Functions (Module: text)
+//------------------------------------------------------------------------------------
+SpriteFont GetDefaultFont(void);                                                                   // Get the default SpriteFont
+SpriteFont LoadSpriteFont(const char *fileName);                                                   // Load a SpriteFont image into GPU memory
+void UnloadSpriteFont(SpriteFont spriteFont);                                                      // Unload SpriteFont from GPU memory
+
+void DrawText(const char *text, int posX, int posY, int fontSize, Color color);                    // Draw text (using default font)
+void DrawTextEx(SpriteFont spriteFont, const char* text, Vector2 position,                         // Draw text using SpriteFont and additional parameters
+                int fontSize, int spacing, Color tint);
+int MeasureText(const char *text, int fontSize);                                                   // Measure string width for default font
+Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, int fontSize, int spacing);         // Measure string size for SpriteFont
+
+void DrawFPS(int posX, int posY);                                                                  // Shows current FPS on top-left corner
+const char *FormatText(const char *text, ...);                                                     // Formatting of text with variables to 'embed'
+const char *SubText(const char *text, int position, int length);                                   // Get a piece of a text string
+
+//------------------------------------------------------------------------------------
+// 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
+void DrawCubeTexture(Texture2D texture, Vector3 position, float width, float height, float lenght, Color color); // Draw cube textured
+void DrawSphere(Vector3 centerPos, float radius, Color color);                                     // Draw sphere
+void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color color);            // Draw sphere with extended parameters
+void DrawSphereWires(Vector3 centerPos, float radius, int rings, int slices, Color color);         // Draw sphere wires
+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 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, 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
+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)
+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 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
+bool CheckCollisionSpheres(Vector3 centerA, float radiusA, Vector3 centerB, float radiusB);                     // Detect collision between two spheres
+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, 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
+//------------------------------------------------------------------------------------
+// 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
+
+//------------------------------------------------------------------------------------
+// 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
+Sound LoadSoundFromRES(const char *rresName, int resId);        // Load sound to memory from rRES file (raylib Resource)
+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 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)
+
+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)
+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
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // RAYLIB_H

BIN
release/html5/libraylib.bc


+ 896 - 0
release/html5/raylib.h

@@ -0,0 +1,896 @@
+/**********************************************************************************************
+*
+*   raylib 1.5.0 (www.raylib.com)
+*
+*   A simple and easy-to-use library to learn videogames programming
+*
+*   Features:
+*     Library written in plain C code (C99)
+*     Uses C# PascalCase/camelCase notation
+*     Hardware accelerated with OpenGL (1.1, 3.3 or ES2)
+*     Unique OpenGL abstraction layer [rlgl]
+*     Powerful fonts module with SpriteFonts support (including AngelCode fonts and TTF)
+*     Multiple textures support, including compressed formats and mipmaps generation
+*     Basic 3d support for Shapes, Models, Heightmaps and Billboards
+*     Powerful math module for Vector and Matrix operations [raymath]
+*     Audio loading and playing with streaming support (WAV and OGG)
+*     Multiplatform support, including Android devices, Raspberry Pi and HTML5
+*
+*   Used external libs:
+*     GLFW3 (www.glfw.org) for window/context management and input
+*     GLAD for OpenGL extensions loading (3.3 Core profile, only PLATFORM_DESKTOP)
+*     stb_image (Sean Barret) for images loading (JPEG, PNG, BMP, TGA, PSD, GIF, HDR, PIC)
+*     stb_image_write (Sean Barret) for image writting (PNG)
+*     stb_vorbis (Sean Barret) for ogg audio loading
+*     stb_truetype (Sean Barret) for ttf fonts loading
+*     OpenAL Soft for audio device/context management
+*     tinfl for data decompression (DEFLATE algorithm)
+*
+*   Some design decisions:
+*     32bit Colors - All defined color are always RGBA (struct Color is 4 byte)
+*     One custom default font is loaded automatically when InitWindow()
+*     If using OpenGL 3.3 or ES2, several vertex buffers (VAO/VBO) are created to manage lines-triangles-quads
+*     If using OpenGL 3.3 or ES2, two default shaders are loaded automatically (internally defined)
+*
+*   -- LICENSE --
+*
+*   raylib is licensed under an unmodified zlib/libpng license, which is an OSI-certified,
+*   BSD-like license that allows static linking with closed source software:
+*
+*   Copyright (c) 2013 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 RAYLIB_H
+#define RAYLIB_H
+
+// Choose your platform here or just define it at compile time: -DPLATFORM_DESKTOP
+//#define PLATFORM_DESKTOP      // Windows, Linux or OSX
+//#define PLATFORM_ANDROID      // Android device
+//#define PLATFORM_RPI          // Raspberry Pi
+//#define PLATFORM_WEB          // HTML5 (emscripten, asm.js)
+//#define PLATFORM_OCULUS       // Oculus Rift CV1
+
+// Security check in case no PLATFORM_* defined
+#if !defined(PLATFORM_DESKTOP) && !defined(PLATFORM_ANDROID) && !defined(PLATFORM_RPI) && !defined(PLATFORM_WEB)
+    #define PLATFORM_DESKTOP
+#endif
+
+#if defined(PLATFORM_ANDROID)
+    typedef struct android_app; // Define android_app struct (android_native_app_glue.h)
+#endif
+
+//----------------------------------------------------------------------------------
+// Some basic Defines
+//----------------------------------------------------------------------------------
+#ifndef PI
+    #define PI 3.14159265358979323846
+#endif
+
+#define DEG2RAD (PI/180.0f)
+#define RAD2DEG (180.0f/PI)
+
+// raylib Config Flags
+#define FLAG_FULLSCREEN_MODE    1
+#define FLAG_SHOW_LOGO          2
+#define FLAG_SHOW_MOUSE_CURSOR  4
+#define FLAG_CENTERED_MODE      8
+#define FLAG_MSAA_4X_HINT      16
+#define FLAG_VSYNC_HINT        32
+
+// Keyboard Function Keys
+#define KEY_SPACE            32
+#define KEY_ESCAPE          256
+#define KEY_ENTER           257
+#define KEY_BACKSPACE       259
+#define KEY_RIGHT           262
+#define KEY_LEFT            263
+#define KEY_DOWN            264
+#define KEY_UP              265
+#define KEY_F1              290
+#define KEY_F2              291
+#define KEY_F3              292
+#define KEY_F4              293
+#define KEY_F5              294
+#define KEY_F6              295
+#define KEY_F7              296
+#define KEY_F8              297
+#define KEY_F9              298
+#define KEY_F10             299
+#define KEY_F11             300
+#define KEY_F12             301
+#define KEY_LEFT_SHIFT      340
+#define KEY_LEFT_CONTROL    341
+#define KEY_LEFT_ALT        342
+#define KEY_RIGHT_SHIFT     344
+#define KEY_RIGHT_CONTROL   345
+#define KEY_RIGHT_ALT       346
+
+// Keyboard Alpha Numeric Keys
+#define KEY_ZERO             48
+#define KEY_ONE              49
+#define KEY_TWO              50
+#define KEY_THREE            51
+#define KEY_FOUR             52
+#define KEY_FIVE             53
+#define KEY_SIX              54
+#define KEY_SEVEN            55
+#define KEY_EIGHT            56
+#define KEY_NINE             57
+#define KEY_A                65
+#define KEY_B                66
+#define KEY_C                67
+#define KEY_D                68
+#define KEY_E                69
+#define KEY_F                70
+#define KEY_G                71
+#define KEY_H                72
+#define KEY_I                73
+#define KEY_J                74
+#define KEY_K                75
+#define KEY_L                76
+#define KEY_M                77
+#define KEY_N                78
+#define KEY_O                79
+#define KEY_P                80
+#define KEY_Q                81
+#define KEY_R                82
+#define KEY_S                83
+#define KEY_T                84
+#define KEY_U                85
+#define KEY_V                86
+#define KEY_W                87
+#define KEY_X                88
+#define KEY_Y                89
+#define KEY_Z                90
+
+// Mouse Buttons
+#define MOUSE_LEFT_BUTTON     0
+#if defined(PLATFORM_WEB)
+    #define MOUSE_RIGHT_BUTTON    2
+    #define MOUSE_MIDDLE_BUTTON   1
+#else
+    #define MOUSE_RIGHT_BUTTON    1
+    #define MOUSE_MIDDLE_BUTTON   2
+#endif
+
+// Touch points registered
+#define MAX_TOUCH_POINTS     2
+
+// Gamepad Number
+#define GAMEPAD_PLAYER1       0
+#define GAMEPAD_PLAYER2       1
+#define GAMEPAD_PLAYER3       2     // Not supported
+#define GAMEPAD_PLAYER4       3     // Not supported
+
+// Gamepad Buttons
+// NOTE: Adjusted for a PS3 USB Controller
+#define GAMEPAD_BUTTON_A        2
+#define GAMEPAD_BUTTON_B        1
+#define GAMEPAD_BUTTON_X        3
+#define GAMEPAD_BUTTON_Y        4
+#define GAMEPAD_BUTTON_R1       7
+#define GAMEPAD_BUTTON_R2       5
+#define GAMEPAD_BUTTON_L1       6
+#define GAMEPAD_BUTTON_L2       8
+#define GAMEPAD_BUTTON_SELECT   9
+#define GAMEPAD_BUTTON_START   10
+
+// 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
+#define ANDROID_MENU            82
+#define ANDROID_VOLUME_UP       24
+#define ANDROID_VOLUME_DOWN     25
+
+// Some Basic Colors
+// NOTE: Custom raylib color palette for amazing visuals on WHITE background
+#define LIGHTGRAY  (Color){ 200, 200, 200, 255 }   // Light Gray
+#define GRAY       (Color){ 130, 130, 130, 255 }   // Gray
+#define DARKGRAY   (Color){ 80, 80, 80, 255 }      // Dark Gray
+#define YELLOW     (Color){ 253, 249, 0, 255 }     // Yellow
+#define GOLD       (Color){ 255, 203, 0, 255 }     // Gold
+#define ORANGE     (Color){ 255, 161, 0, 255 }     // Orange
+#define PINK       (Color){ 255, 109, 194, 255 }   // Pink
+#define RED        (Color){ 230, 41, 55, 255 }     // Red
+#define MAROON     (Color){ 190, 33, 55, 255 }     // Maroon
+#define GREEN      (Color){ 0, 228, 48, 255 }      // Green
+#define LIME       (Color){ 0, 158, 47, 255 }      // Lime
+#define DARKGREEN  (Color){ 0, 117, 44, 255 }      // Dark Green
+#define SKYBLUE    (Color){ 102, 191, 255, 255 }   // Sky Blue
+#define BLUE       (Color){ 0, 121, 241, 255 }     // Blue
+#define DARKBLUE   (Color){ 0, 82, 172, 255 }      // Dark Blue
+#define PURPLE     (Color){ 200, 122, 255, 255 }   // Purple
+#define VIOLET     (Color){ 135, 60, 190, 255 }    // Violet
+#define DARKPURPLE (Color){ 112, 31, 126, 255 }    // Dark Purple
+#define BEIGE      (Color){ 211, 176, 131, 255 }   // Beige
+#define BROWN      (Color){ 127, 106, 79, 255 }    // Brown
+#define DARKBROWN  (Color){ 76, 63, 47, 255 }      // Dark Brown
+
+#define WHITE      (Color){ 255, 255, 255, 255 }   // White
+#define BLACK      (Color){ 0, 0, 0, 255 }         // Black
+#define BLANK      (Color){ 0, 0, 0, 0 }           // Blank (Transparent)
+#define MAGENTA    (Color){ 255, 0, 255, 255 }     // Magenta
+#define RAYWHITE   (Color){ 245, 245, 245, 255 }   // My own White (raylib logo)
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+#ifndef __cplusplus
+// Boolean type
+    #if !defined(_STDBOOL_H)
+        typedef enum { false, true } bool;
+        #define _STDBOOL_H
+    #endif
+#endif
+
+// byte type
+typedef unsigned char byte;
+
+// 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;
+
+// Color type, RGBA (32bit)
+typedef struct Color {
+    unsigned char r;
+    unsigned char g;
+    unsigned char b;
+    unsigned char a;
+} Color;
+
+// Rectangle type
+typedef struct Rectangle {
+    int x;
+    int y;
+    int width;
+    int height;
+} Rectangle;
+
+// Image type, bpp always RGBA (32bit)
+// NOTE: Data stored in CPU memory (RAM)
+typedef struct Image {
+    void *data;             // Image raw data
+    int width;              // Image base width
+    int height;             // Image base height
+    int mipmaps;            // Mipmap levels, 1 by default
+    int format;             // Data format (TextureFormat)
+} Image;
+
+// Texture2D type, bpp always RGBA (32bit)
+// 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;
+
+// SpriteFont type, includes texture and charSet array data
+typedef struct SpriteFont {
+    Texture2D texture;      // Font texture
+    int size;               // Base size (default chars height)
+    int numChars;           // Number of characters
+    int *charValues;        // Characters values array
+    Rectangle *charRecs;    // Characters rectangles within the texture
+    Vector2 *charOffsets;   // Characters offsets (on drawing)
+    int *charAdvanceX;      // Characters x advance (on drawing)
+} SpriteFont;
+
+// 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;
+
+// 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;            // minimum vertex box-corner
+    Vector3 max;            // maximum vertex box-corner
+} BoundingBox;
+
+// 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 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)
+    
+    // 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
+typedef struct Material {
+    Shader shader;          // Standard shader (supports 3 map textures)
+
+    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;       // Diffuse color
+    Color colAmbient;       // Ambient color
+    Color colSpecular;      // Specular color
+    
+    float glossiness;       // Glossiness level (Ranges from 0 to 1000)
+} Material;
+
+// Model type
+typedef struct Model {
+    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
+    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;
+
+// Ray type (useful for raycast)
+typedef struct Ray {
+    Vector3 position;       // Ray position (origin)
+    Vector3 direction;      // Ray direction
+} Ray;
+
+// Sound source type
+typedef struct 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;    // Samples per second to be played
+    short bitsPerSample;        // Sample size in bits
+    short channels;
+} Wave;
+
+typedef int RawAudioContext;
+
+// Texture formats
+// NOTE: Support depends on OpenGL version and platform
+typedef enum {
+    UNCOMPRESSED_GRAYSCALE = 1,     // 8 bit per pixel (no alpha)
+    UNCOMPRESSED_GRAY_ALPHA,        // 16 bpp (2 channels)
+    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;
+
+// Color blending modes (pre-defined)
+typedef enum { BLEND_ALPHA = 0, BLEND_ADDITIVE, BLEND_MULTIPLIED } BlendMode;
+
+// Gestures type
+// NOTE: It could be used as flags to enable only some gestures
+typedef enum {
+    GESTURE_NONE        = 0,
+    GESTURE_TAP         = 1,
+    GESTURE_DOUBLETAP   = 2,
+    GESTURE_HOLD        = 4,
+    GESTURE_DRAG        = 8,
+    GESTURE_SWIPE_RIGHT = 16,
+    GESTURE_SWIPE_LEFT  = 32,
+    GESTURE_SWIPE_UP    = 64,
+    GESTURE_SWIPE_DOWN  = 128,
+    GESTURE_PINCH_IN    = 256,
+    GESTURE_PINCH_OUT   = 512
+} Gestures;
+
+// Touch action (fingers or mouse)
+typedef enum { TOUCH_UP, TOUCH_DOWN, TOUCH_MOVE } TouchAction;
+
+// Gesture events
+// NOTE: MAX_TOUCH_POINTS fixed to 2
+typedef struct GestureEvent {
+    int touchAction;
+    int pointCount;
+    int pointerId[MAX_TOUCH_POINTS];
+    Vector2 position[MAX_TOUCH_POINTS];
+} GestureEvent;
+
+// Camera system modes
+typedef enum { CAMERA_CUSTOM = 0, CAMERA_FREE, CAMERA_ORBITAL, CAMERA_FIRST_PERSON, CAMERA_THIRD_PERSON } CameraMode;
+
+#ifdef __cplusplus
+extern "C" {            // Prevents name mangling of functions
+#endif
+
+//------------------------------------------------------------------------------------
+// Global Variables Definition
+//------------------------------------------------------------------------------------
+// It's lonely here...
+
+//------------------------------------------------------------------------------------
+// Window and Graphics Device Functions (Module: core)
+//------------------------------------------------------------------------------------
+#if defined(PLATFORM_ANDROID)
+void InitWindow(int width, int height, struct android_app *state);  // Init Android Activity and OpenGL Graphics
+#elif defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
+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)
+void ToggleFullscreen(void);                                // Fullscreen toggle (only PLATFORM_DESKTOP)
+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 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 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)
+float GetFPS(void);                                         // Returns current FPS
+float GetFrameTime(void);                                   // Returns time in seconds for one frame
+
+Color GetColor(int hexValue);                               // Returns a Color struct from hexadecimal value
+int GetHexValue(Color color);                               // Returns hexadecimal value for a Color
+float *ColorToFloat(Color color);                           // Converts Color to float array and normalizes
+float *VectorToFloat(Vector3 vec);                          // Converts Vector3 to float array
+float *MatrixToFloat(Matrix mat);                           // Converts Matrix to float array
+
+int GetRandomValue(int min, int max);                       // Returns a random value between min and max (both included)
+Color Fade(Color color, float alpha);                       // Color fade-in or fade-out, alpha goes from 0.0f to 1.0f
+
+void SetConfigFlags(char flags);                            // Setup some window configuration flags
+void ShowLogo(void);                                        // Activates raylib logo at startup (can be done with flags)
+
+bool IsFileDropped(void);                                   // Check if a file have been dropped into window
+char **GetDroppedFiles(int *count);                         // Retrieve dropped files into window
+void ClearDroppedFiles(void);                               // Clear dropped files paths buffer
+
+void StorageSaveValue(int position, int value);             // Storage save integer value (to defined position)
+int StorageLoadValue(int position);                         // Storage load integer value (from defined position)
+
+//------------------------------------------------------------------------------------
+// Input Handling Functions (Module: core)
+//------------------------------------------------------------------------------------
+#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
+bool IsKeyPressed(int key);                             // Detect if a key has been pressed once
+bool IsKeyDown(int key);                                // Detect if a key is being pressed
+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
+bool IsMouseButtonReleased(int button);                 // Detect if a mouse button has been released once
+bool IsMouseButtonUp(int button);                       // Detect if a mouse button is NOT being pressed
+int GetMouseX(void);                                    // Returns mouse position X
+int GetMouseY(void);                                    // Returns mouse position Y
+Vector2 GetMousePosition(void);                         // Returns mouse position XY
+void SetMousePosition(Vector2 position);                // Set mouse position XY
+int GetMouseWheelMove(void);                            // Returns mouse wheel movement Y
+
+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)
+
+#if defined(PLATFORM_ANDROID)
+bool IsButtonPressed(int button);                       // Detect if an android physic button has been pressed
+bool IsButtonDown(int button);                          // Detect if an android physic button is being pressed
+bool IsButtonReleased(int button);                      // Detect if an android physic button has been released
+#endif
+
+//------------------------------------------------------------------------------------
+// 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 (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
+
+float GetGestureHoldDuration(void);                     // Get gesture hold time in milliseconds
+Vector2 GetGestureDragVector(void);                     // Get gesture drag vector
+float GetGestureDragAngle(void);                        // Get gesture drag angle
+Vector2 GetGesturePinchVector(void);                    // Get gesture pinch delta
+float GetGesturePinchAngle(void);                       // Get gesture pinch angle
+
+//------------------------------------------------------------------------------------
+// Camera System Functions (Module: camera)
+//------------------------------------------------------------------------------------
+void SetCameraMode(int mode);                               // Set camera mode (multiple camera modes available)
+void UpdateCamera(Camera *camera);                          // Update camera (player position is ignored)
+void UpdateCameraPlayer(Camera *camera, Vector3 *position); // Update camera and player position (1st person and 3rd person cameras)
+
+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)
+void SetCameraSmoothZoomControl(int szKey);                 // Set camera smooth zoom key to combine with mouse (free camera)
+
+void SetCameraMoveControls(int frontKey, int backKey, 
+                           int leftKey, int rightKey, 
+                           int upKey, int downKey);         // Set camera move controls (1st person and 3rd person cameras)
+void SetCameraMouseSensitivity(float sensitivity);          // Set camera mouse sensitivity (1st person and 3rd person cameras)
+
+//------------------------------------------------------------------------------------
+// Basic Shapes Drawing Functions (Module: shapes)
+//------------------------------------------------------------------------------------
+void DrawPixel(int posX, int posY, Color color);                                                   // Draw a pixel
+void DrawPixelV(Vector2 position, Color color);                                                    // Draw a pixel (Vector version)
+void DrawLine(int startPosX, int startPosY, int endPosX, int endPosY, Color color);                // Draw a line
+void DrawLineV(Vector2 startPos, Vector2 endPos, Color color);                                     // Draw a line (Vector version)
+void DrawCircle(int centerX, int centerY, float radius, Color color);                              // Draw a color-filled circle
+void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2);       // Draw a gradient-filled circle
+void DrawCircleV(Vector2 center, float radius, Color color);                                       // Draw a color-filled circle (Vector version)
+void DrawCircleLines(int centerX, int centerY, float radius, Color color);                         // Draw circle outline
+void DrawRectangle(int posX, int posY, int width, int height, Color color);                        // Draw a color-filled rectangle
+void DrawRectangleRec(Rectangle rec, Color color);                                                 // Draw a color-filled rectangle
+void DrawRectangleGradient(int posX, int posY, int width, int height, Color color1, Color color2); // Draw a gradient-filled rectangle
+void DrawRectangleV(Vector2 position, Vector2 size, Color color);                                  // Draw a color-filled rectangle (Vector version)
+void DrawRectangleLines(int posX, int posY, int width, int height, Color color);                   // Draw rectangle outline
+void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color);                                // Draw a color-filled triangle
+void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color);                           // Draw triangle outline
+void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color);               // Draw a regular polygon (Vector version)
+void DrawPolyEx(Vector2 *points, int numPoints, Color color);                                      // Draw a closed polygon defined by points
+void DrawPolyExLines(Vector2 *points, int numPoints, Color color);                                 // Draw polygon lines
+
+bool CheckCollisionRecs(Rectangle rec1, Rectangle rec2);                                           // Check collision between two rectangles
+bool CheckCollisionCircles(Vector2 center1, float radius1, Vector2 center2, float radius2);        // Check collision between two circles
+bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec);                         // Check collision between circle and rectangle
+Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2);                                         // Get collision rectangle for two rectangles collision
+bool CheckCollisionPointRec(Vector2 point, Rectangle rec);                                         // Check if point is inside rectangle
+bool CheckCollisionPointCircle(Vector2 point, Vector2 center, float radius);                       // Check if point is inside circle
+bool CheckCollisionPointTriangle(Vector2 point, Vector2 p1, Vector2 p2, Vector2 p3);               // Check if point is inside a triangle
+
+//------------------------------------------------------------------------------------
+// Texture Loading and Drawing Functions (Module: textures)
+//------------------------------------------------------------------------------------
+Image LoadImage(const char *fileName);                                                             // Load an image into CPU memory (RAM)
+Image LoadImageEx(Color *pixels, int width, int height);                                           // Load image data from Color array data (RGBA - 32bit)
+Image LoadImageRaw(const char *fileName, int width, int height, int format, int headerSize);       // Load image data from RAW file
+Image LoadImageFromRES(const char *rresName, int resId);                                           // Load an image from rRES file (raylib Resource)
+Texture2D LoadTexture(const char *fileName);                                                       // Load an image as texture into GPU memory
+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)
+void ImageFormat(Image *image, int newFormat);                                                     // Convert image data to desired format
+void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp);                            // Dither image data to 16bpp or lower (Floyd-Steinberg dithering)
+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 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 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
+void UpdateTexture(Texture2D texture, void *pixels);                                               // Update GPU texture with new data
+
+void DrawTexture(Texture2D texture, int posX, int posY, Color tint);                               // Draw a Texture2D
+void DrawTextureV(Texture2D texture, Vector2 position, Color tint);                                // Draw a Texture2D with position defined as Vector2
+void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, float scale, Color tint);  // Draw a Texture2D with extended parameters
+void DrawTextureRec(Texture2D texture, Rectangle sourceRec, Vector2 position, Color tint);         // Draw a part of a texture defined by a rectangle
+void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle destRec, Vector2 origin,     // Draw a part of a texture defined by a rectangle with 'pro' parameters
+                    float rotation, Color tint);
+
+//------------------------------------------------------------------------------------
+// Font Loading and Text Drawing Functions (Module: text)
+//------------------------------------------------------------------------------------
+SpriteFont GetDefaultFont(void);                                                                   // Get the default SpriteFont
+SpriteFont LoadSpriteFont(const char *fileName);                                                   // Load a SpriteFont image into GPU memory
+void UnloadSpriteFont(SpriteFont spriteFont);                                                      // Unload SpriteFont from GPU memory
+
+void DrawText(const char *text, int posX, int posY, int fontSize, Color color);                    // Draw text (using default font)
+void DrawTextEx(SpriteFont spriteFont, const char* text, Vector2 position,                         // Draw text using SpriteFont and additional parameters
+                int fontSize, int spacing, Color tint);
+int MeasureText(const char *text, int fontSize);                                                   // Measure string width for default font
+Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, int fontSize, int spacing);         // Measure string size for SpriteFont
+
+void DrawFPS(int posX, int posY);                                                                  // Shows current FPS on top-left corner
+const char *FormatText(const char *text, ...);                                                     // Formatting of text with variables to 'embed'
+const char *SubText(const char *text, int position, int length);                                   // Get a piece of a text string
+
+//------------------------------------------------------------------------------------
+// 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
+void DrawCubeTexture(Texture2D texture, Vector3 position, float width, float height, float lenght, Color color); // Draw cube textured
+void DrawSphere(Vector3 centerPos, float radius, Color color);                                     // Draw sphere
+void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color color);            // Draw sphere with extended parameters
+void DrawSphereWires(Vector3 centerPos, float radius, int rings, int slices, Color color);         // Draw sphere wires
+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 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, 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
+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)
+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 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
+bool CheckCollisionSpheres(Vector3 centerA, float radiusA, Vector3 centerB, float radiusB);                     // Detect collision between two spheres
+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, 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
+//------------------------------------------------------------------------------------
+// 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
+
+//------------------------------------------------------------------------------------
+// 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
+Sound LoadSoundFromRES(const char *rresName, int resId);        // Load sound to memory from rRES file (raylib Resource)
+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 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)
+
+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)
+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
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // RAYLIB_H

+ 0 - 0
release/linux/helpme!


+ 0 - 0
release/osx/helpme!


BIN
release/win32/mingw32/libraylib.a


+ 896 - 0
release/win32/raylib.h

@@ -0,0 +1,896 @@
+/**********************************************************************************************
+*
+*   raylib 1.5.0 (www.raylib.com)
+*
+*   A simple and easy-to-use library to learn videogames programming
+*
+*   Features:
+*     Library written in plain C code (C99)
+*     Uses C# PascalCase/camelCase notation
+*     Hardware accelerated with OpenGL (1.1, 3.3 or ES2)
+*     Unique OpenGL abstraction layer [rlgl]
+*     Powerful fonts module with SpriteFonts support (including AngelCode fonts and TTF)
+*     Multiple textures support, including compressed formats and mipmaps generation
+*     Basic 3d support for Shapes, Models, Heightmaps and Billboards
+*     Powerful math module for Vector and Matrix operations [raymath]
+*     Audio loading and playing with streaming support (WAV and OGG)
+*     Multiplatform support, including Android devices, Raspberry Pi and HTML5
+*
+*   Used external libs:
+*     GLFW3 (www.glfw.org) for window/context management and input
+*     GLAD for OpenGL extensions loading (3.3 Core profile, only PLATFORM_DESKTOP)
+*     stb_image (Sean Barret) for images loading (JPEG, PNG, BMP, TGA, PSD, GIF, HDR, PIC)
+*     stb_image_write (Sean Barret) for image writting (PNG)
+*     stb_vorbis (Sean Barret) for ogg audio loading
+*     stb_truetype (Sean Barret) for ttf fonts loading
+*     OpenAL Soft for audio device/context management
+*     tinfl for data decompression (DEFLATE algorithm)
+*
+*   Some design decisions:
+*     32bit Colors - All defined color are always RGBA (struct Color is 4 byte)
+*     One custom default font is loaded automatically when InitWindow()
+*     If using OpenGL 3.3 or ES2, several vertex buffers (VAO/VBO) are created to manage lines-triangles-quads
+*     If using OpenGL 3.3 or ES2, two default shaders are loaded automatically (internally defined)
+*
+*   -- LICENSE --
+*
+*   raylib is licensed under an unmodified zlib/libpng license, which is an OSI-certified,
+*   BSD-like license that allows static linking with closed source software:
+*
+*   Copyright (c) 2013 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 RAYLIB_H
+#define RAYLIB_H
+
+// Choose your platform here or just define it at compile time: -DPLATFORM_DESKTOP
+//#define PLATFORM_DESKTOP      // Windows, Linux or OSX
+//#define PLATFORM_ANDROID      // Android device
+//#define PLATFORM_RPI          // Raspberry Pi
+//#define PLATFORM_WEB          // HTML5 (emscripten, asm.js)
+//#define PLATFORM_OCULUS       // Oculus Rift CV1
+
+// Security check in case no PLATFORM_* defined
+#if !defined(PLATFORM_DESKTOP) && !defined(PLATFORM_ANDROID) && !defined(PLATFORM_RPI) && !defined(PLATFORM_WEB)
+    #define PLATFORM_DESKTOP
+#endif
+
+#if defined(PLATFORM_ANDROID)
+    typedef struct android_app; // Define android_app struct (android_native_app_glue.h)
+#endif
+
+//----------------------------------------------------------------------------------
+// Some basic Defines
+//----------------------------------------------------------------------------------
+#ifndef PI
+    #define PI 3.14159265358979323846
+#endif
+
+#define DEG2RAD (PI/180.0f)
+#define RAD2DEG (180.0f/PI)
+
+// raylib Config Flags
+#define FLAG_FULLSCREEN_MODE    1
+#define FLAG_SHOW_LOGO          2
+#define FLAG_SHOW_MOUSE_CURSOR  4
+#define FLAG_CENTERED_MODE      8
+#define FLAG_MSAA_4X_HINT      16
+#define FLAG_VSYNC_HINT        32
+
+// Keyboard Function Keys
+#define KEY_SPACE            32
+#define KEY_ESCAPE          256
+#define KEY_ENTER           257
+#define KEY_BACKSPACE       259
+#define KEY_RIGHT           262
+#define KEY_LEFT            263
+#define KEY_DOWN            264
+#define KEY_UP              265
+#define KEY_F1              290
+#define KEY_F2              291
+#define KEY_F3              292
+#define KEY_F4              293
+#define KEY_F5              294
+#define KEY_F6              295
+#define KEY_F7              296
+#define KEY_F8              297
+#define KEY_F9              298
+#define KEY_F10             299
+#define KEY_F11             300
+#define KEY_F12             301
+#define KEY_LEFT_SHIFT      340
+#define KEY_LEFT_CONTROL    341
+#define KEY_LEFT_ALT        342
+#define KEY_RIGHT_SHIFT     344
+#define KEY_RIGHT_CONTROL   345
+#define KEY_RIGHT_ALT       346
+
+// Keyboard Alpha Numeric Keys
+#define KEY_ZERO             48
+#define KEY_ONE              49
+#define KEY_TWO              50
+#define KEY_THREE            51
+#define KEY_FOUR             52
+#define KEY_FIVE             53
+#define KEY_SIX              54
+#define KEY_SEVEN            55
+#define KEY_EIGHT            56
+#define KEY_NINE             57
+#define KEY_A                65
+#define KEY_B                66
+#define KEY_C                67
+#define KEY_D                68
+#define KEY_E                69
+#define KEY_F                70
+#define KEY_G                71
+#define KEY_H                72
+#define KEY_I                73
+#define KEY_J                74
+#define KEY_K                75
+#define KEY_L                76
+#define KEY_M                77
+#define KEY_N                78
+#define KEY_O                79
+#define KEY_P                80
+#define KEY_Q                81
+#define KEY_R                82
+#define KEY_S                83
+#define KEY_T                84
+#define KEY_U                85
+#define KEY_V                86
+#define KEY_W                87
+#define KEY_X                88
+#define KEY_Y                89
+#define KEY_Z                90
+
+// Mouse Buttons
+#define MOUSE_LEFT_BUTTON     0
+#if defined(PLATFORM_WEB)
+    #define MOUSE_RIGHT_BUTTON    2
+    #define MOUSE_MIDDLE_BUTTON   1
+#else
+    #define MOUSE_RIGHT_BUTTON    1
+    #define MOUSE_MIDDLE_BUTTON   2
+#endif
+
+// Touch points registered
+#define MAX_TOUCH_POINTS     2
+
+// Gamepad Number
+#define GAMEPAD_PLAYER1       0
+#define GAMEPAD_PLAYER2       1
+#define GAMEPAD_PLAYER3       2     // Not supported
+#define GAMEPAD_PLAYER4       3     // Not supported
+
+// Gamepad Buttons
+// NOTE: Adjusted for a PS3 USB Controller
+#define GAMEPAD_BUTTON_A        2
+#define GAMEPAD_BUTTON_B        1
+#define GAMEPAD_BUTTON_X        3
+#define GAMEPAD_BUTTON_Y        4
+#define GAMEPAD_BUTTON_R1       7
+#define GAMEPAD_BUTTON_R2       5
+#define GAMEPAD_BUTTON_L1       6
+#define GAMEPAD_BUTTON_L2       8
+#define GAMEPAD_BUTTON_SELECT   9
+#define GAMEPAD_BUTTON_START   10
+
+// 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
+#define ANDROID_MENU            82
+#define ANDROID_VOLUME_UP       24
+#define ANDROID_VOLUME_DOWN     25
+
+// Some Basic Colors
+// NOTE: Custom raylib color palette for amazing visuals on WHITE background
+#define LIGHTGRAY  (Color){ 200, 200, 200, 255 }   // Light Gray
+#define GRAY       (Color){ 130, 130, 130, 255 }   // Gray
+#define DARKGRAY   (Color){ 80, 80, 80, 255 }      // Dark Gray
+#define YELLOW     (Color){ 253, 249, 0, 255 }     // Yellow
+#define GOLD       (Color){ 255, 203, 0, 255 }     // Gold
+#define ORANGE     (Color){ 255, 161, 0, 255 }     // Orange
+#define PINK       (Color){ 255, 109, 194, 255 }   // Pink
+#define RED        (Color){ 230, 41, 55, 255 }     // Red
+#define MAROON     (Color){ 190, 33, 55, 255 }     // Maroon
+#define GREEN      (Color){ 0, 228, 48, 255 }      // Green
+#define LIME       (Color){ 0, 158, 47, 255 }      // Lime
+#define DARKGREEN  (Color){ 0, 117, 44, 255 }      // Dark Green
+#define SKYBLUE    (Color){ 102, 191, 255, 255 }   // Sky Blue
+#define BLUE       (Color){ 0, 121, 241, 255 }     // Blue
+#define DARKBLUE   (Color){ 0, 82, 172, 255 }      // Dark Blue
+#define PURPLE     (Color){ 200, 122, 255, 255 }   // Purple
+#define VIOLET     (Color){ 135, 60, 190, 255 }    // Violet
+#define DARKPURPLE (Color){ 112, 31, 126, 255 }    // Dark Purple
+#define BEIGE      (Color){ 211, 176, 131, 255 }   // Beige
+#define BROWN      (Color){ 127, 106, 79, 255 }    // Brown
+#define DARKBROWN  (Color){ 76, 63, 47, 255 }      // Dark Brown
+
+#define WHITE      (Color){ 255, 255, 255, 255 }   // White
+#define BLACK      (Color){ 0, 0, 0, 255 }         // Black
+#define BLANK      (Color){ 0, 0, 0, 0 }           // Blank (Transparent)
+#define MAGENTA    (Color){ 255, 0, 255, 255 }     // Magenta
+#define RAYWHITE   (Color){ 245, 245, 245, 255 }   // My own White (raylib logo)
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+#ifndef __cplusplus
+// Boolean type
+    #if !defined(_STDBOOL_H)
+        typedef enum { false, true } bool;
+        #define _STDBOOL_H
+    #endif
+#endif
+
+// byte type
+typedef unsigned char byte;
+
+// 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;
+
+// Color type, RGBA (32bit)
+typedef struct Color {
+    unsigned char r;
+    unsigned char g;
+    unsigned char b;
+    unsigned char a;
+} Color;
+
+// Rectangle type
+typedef struct Rectangle {
+    int x;
+    int y;
+    int width;
+    int height;
+} Rectangle;
+
+// Image type, bpp always RGBA (32bit)
+// NOTE: Data stored in CPU memory (RAM)
+typedef struct Image {
+    void *data;             // Image raw data
+    int width;              // Image base width
+    int height;             // Image base height
+    int mipmaps;            // Mipmap levels, 1 by default
+    int format;             // Data format (TextureFormat)
+} Image;
+
+// Texture2D type, bpp always RGBA (32bit)
+// 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;
+
+// SpriteFont type, includes texture and charSet array data
+typedef struct SpriteFont {
+    Texture2D texture;      // Font texture
+    int size;               // Base size (default chars height)
+    int numChars;           // Number of characters
+    int *charValues;        // Characters values array
+    Rectangle *charRecs;    // Characters rectangles within the texture
+    Vector2 *charOffsets;   // Characters offsets (on drawing)
+    int *charAdvanceX;      // Characters x advance (on drawing)
+} SpriteFont;
+
+// 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;
+
+// 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;            // minimum vertex box-corner
+    Vector3 max;            // maximum vertex box-corner
+} BoundingBox;
+
+// 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 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)
+    
+    // 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
+typedef struct Material {
+    Shader shader;          // Standard shader (supports 3 map textures)
+
+    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;       // Diffuse color
+    Color colAmbient;       // Ambient color
+    Color colSpecular;      // Specular color
+    
+    float glossiness;       // Glossiness level (Ranges from 0 to 1000)
+} Material;
+
+// Model type
+typedef struct Model {
+    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
+    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;
+
+// Ray type (useful for raycast)
+typedef struct Ray {
+    Vector3 position;       // Ray position (origin)
+    Vector3 direction;      // Ray direction
+} Ray;
+
+// Sound source type
+typedef struct 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;    // Samples per second to be played
+    short bitsPerSample;        // Sample size in bits
+    short channels;
+} Wave;
+
+typedef int RawAudioContext;
+
+// Texture formats
+// NOTE: Support depends on OpenGL version and platform
+typedef enum {
+    UNCOMPRESSED_GRAYSCALE = 1,     // 8 bit per pixel (no alpha)
+    UNCOMPRESSED_GRAY_ALPHA,        // 16 bpp (2 channels)
+    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;
+
+// Color blending modes (pre-defined)
+typedef enum { BLEND_ALPHA = 0, BLEND_ADDITIVE, BLEND_MULTIPLIED } BlendMode;
+
+// Gestures type
+// NOTE: It could be used as flags to enable only some gestures
+typedef enum {
+    GESTURE_NONE        = 0,
+    GESTURE_TAP         = 1,
+    GESTURE_DOUBLETAP   = 2,
+    GESTURE_HOLD        = 4,
+    GESTURE_DRAG        = 8,
+    GESTURE_SWIPE_RIGHT = 16,
+    GESTURE_SWIPE_LEFT  = 32,
+    GESTURE_SWIPE_UP    = 64,
+    GESTURE_SWIPE_DOWN  = 128,
+    GESTURE_PINCH_IN    = 256,
+    GESTURE_PINCH_OUT   = 512
+} Gestures;
+
+// Touch action (fingers or mouse)
+typedef enum { TOUCH_UP, TOUCH_DOWN, TOUCH_MOVE } TouchAction;
+
+// Gesture events
+// NOTE: MAX_TOUCH_POINTS fixed to 2
+typedef struct GestureEvent {
+    int touchAction;
+    int pointCount;
+    int pointerId[MAX_TOUCH_POINTS];
+    Vector2 position[MAX_TOUCH_POINTS];
+} GestureEvent;
+
+// Camera system modes
+typedef enum { CAMERA_CUSTOM = 0, CAMERA_FREE, CAMERA_ORBITAL, CAMERA_FIRST_PERSON, CAMERA_THIRD_PERSON } CameraMode;
+
+#ifdef __cplusplus
+extern "C" {            // Prevents name mangling of functions
+#endif
+
+//------------------------------------------------------------------------------------
+// Global Variables Definition
+//------------------------------------------------------------------------------------
+// It's lonely here...
+
+//------------------------------------------------------------------------------------
+// Window and Graphics Device Functions (Module: core)
+//------------------------------------------------------------------------------------
+#if defined(PLATFORM_ANDROID)
+void InitWindow(int width, int height, struct android_app *state);  // Init Android Activity and OpenGL Graphics
+#elif defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
+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)
+void ToggleFullscreen(void);                                // Fullscreen toggle (only PLATFORM_DESKTOP)
+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 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 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)
+float GetFPS(void);                                         // Returns current FPS
+float GetFrameTime(void);                                   // Returns time in seconds for one frame
+
+Color GetColor(int hexValue);                               // Returns a Color struct from hexadecimal value
+int GetHexValue(Color color);                               // Returns hexadecimal value for a Color
+float *ColorToFloat(Color color);                           // Converts Color to float array and normalizes
+float *VectorToFloat(Vector3 vec);                          // Converts Vector3 to float array
+float *MatrixToFloat(Matrix mat);                           // Converts Matrix to float array
+
+int GetRandomValue(int min, int max);                       // Returns a random value between min and max (both included)
+Color Fade(Color color, float alpha);                       // Color fade-in or fade-out, alpha goes from 0.0f to 1.0f
+
+void SetConfigFlags(char flags);                            // Setup some window configuration flags
+void ShowLogo(void);                                        // Activates raylib logo at startup (can be done with flags)
+
+bool IsFileDropped(void);                                   // Check if a file have been dropped into window
+char **GetDroppedFiles(int *count);                         // Retrieve dropped files into window
+void ClearDroppedFiles(void);                               // Clear dropped files paths buffer
+
+void StorageSaveValue(int position, int value);             // Storage save integer value (to defined position)
+int StorageLoadValue(int position);                         // Storage load integer value (from defined position)
+
+//------------------------------------------------------------------------------------
+// Input Handling Functions (Module: core)
+//------------------------------------------------------------------------------------
+#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
+bool IsKeyPressed(int key);                             // Detect if a key has been pressed once
+bool IsKeyDown(int key);                                // Detect if a key is being pressed
+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
+bool IsMouseButtonReleased(int button);                 // Detect if a mouse button has been released once
+bool IsMouseButtonUp(int button);                       // Detect if a mouse button is NOT being pressed
+int GetMouseX(void);                                    // Returns mouse position X
+int GetMouseY(void);                                    // Returns mouse position Y
+Vector2 GetMousePosition(void);                         // Returns mouse position XY
+void SetMousePosition(Vector2 position);                // Set mouse position XY
+int GetMouseWheelMove(void);                            // Returns mouse wheel movement Y
+
+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)
+
+#if defined(PLATFORM_ANDROID)
+bool IsButtonPressed(int button);                       // Detect if an android physic button has been pressed
+bool IsButtonDown(int button);                          // Detect if an android physic button is being pressed
+bool IsButtonReleased(int button);                      // Detect if an android physic button has been released
+#endif
+
+//------------------------------------------------------------------------------------
+// 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 (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
+
+float GetGestureHoldDuration(void);                     // Get gesture hold time in milliseconds
+Vector2 GetGestureDragVector(void);                     // Get gesture drag vector
+float GetGestureDragAngle(void);                        // Get gesture drag angle
+Vector2 GetGesturePinchVector(void);                    // Get gesture pinch delta
+float GetGesturePinchAngle(void);                       // Get gesture pinch angle
+
+//------------------------------------------------------------------------------------
+// Camera System Functions (Module: camera)
+//------------------------------------------------------------------------------------
+void SetCameraMode(int mode);                               // Set camera mode (multiple camera modes available)
+void UpdateCamera(Camera *camera);                          // Update camera (player position is ignored)
+void UpdateCameraPlayer(Camera *camera, Vector3 *position); // Update camera and player position (1st person and 3rd person cameras)
+
+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)
+void SetCameraSmoothZoomControl(int szKey);                 // Set camera smooth zoom key to combine with mouse (free camera)
+
+void SetCameraMoveControls(int frontKey, int backKey, 
+                           int leftKey, int rightKey, 
+                           int upKey, int downKey);         // Set camera move controls (1st person and 3rd person cameras)
+void SetCameraMouseSensitivity(float sensitivity);          // Set camera mouse sensitivity (1st person and 3rd person cameras)
+
+//------------------------------------------------------------------------------------
+// Basic Shapes Drawing Functions (Module: shapes)
+//------------------------------------------------------------------------------------
+void DrawPixel(int posX, int posY, Color color);                                                   // Draw a pixel
+void DrawPixelV(Vector2 position, Color color);                                                    // Draw a pixel (Vector version)
+void DrawLine(int startPosX, int startPosY, int endPosX, int endPosY, Color color);                // Draw a line
+void DrawLineV(Vector2 startPos, Vector2 endPos, Color color);                                     // Draw a line (Vector version)
+void DrawCircle(int centerX, int centerY, float radius, Color color);                              // Draw a color-filled circle
+void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2);       // Draw a gradient-filled circle
+void DrawCircleV(Vector2 center, float radius, Color color);                                       // Draw a color-filled circle (Vector version)
+void DrawCircleLines(int centerX, int centerY, float radius, Color color);                         // Draw circle outline
+void DrawRectangle(int posX, int posY, int width, int height, Color color);                        // Draw a color-filled rectangle
+void DrawRectangleRec(Rectangle rec, Color color);                                                 // Draw a color-filled rectangle
+void DrawRectangleGradient(int posX, int posY, int width, int height, Color color1, Color color2); // Draw a gradient-filled rectangle
+void DrawRectangleV(Vector2 position, Vector2 size, Color color);                                  // Draw a color-filled rectangle (Vector version)
+void DrawRectangleLines(int posX, int posY, int width, int height, Color color);                   // Draw rectangle outline
+void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color);                                // Draw a color-filled triangle
+void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color);                           // Draw triangle outline
+void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color);               // Draw a regular polygon (Vector version)
+void DrawPolyEx(Vector2 *points, int numPoints, Color color);                                      // Draw a closed polygon defined by points
+void DrawPolyExLines(Vector2 *points, int numPoints, Color color);                                 // Draw polygon lines
+
+bool CheckCollisionRecs(Rectangle rec1, Rectangle rec2);                                           // Check collision between two rectangles
+bool CheckCollisionCircles(Vector2 center1, float radius1, Vector2 center2, float radius2);        // Check collision between two circles
+bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec);                         // Check collision between circle and rectangle
+Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2);                                         // Get collision rectangle for two rectangles collision
+bool CheckCollisionPointRec(Vector2 point, Rectangle rec);                                         // Check if point is inside rectangle
+bool CheckCollisionPointCircle(Vector2 point, Vector2 center, float radius);                       // Check if point is inside circle
+bool CheckCollisionPointTriangle(Vector2 point, Vector2 p1, Vector2 p2, Vector2 p3);               // Check if point is inside a triangle
+
+//------------------------------------------------------------------------------------
+// Texture Loading and Drawing Functions (Module: textures)
+//------------------------------------------------------------------------------------
+Image LoadImage(const char *fileName);                                                             // Load an image into CPU memory (RAM)
+Image LoadImageEx(Color *pixels, int width, int height);                                           // Load image data from Color array data (RGBA - 32bit)
+Image LoadImageRaw(const char *fileName, int width, int height, int format, int headerSize);       // Load image data from RAW file
+Image LoadImageFromRES(const char *rresName, int resId);                                           // Load an image from rRES file (raylib Resource)
+Texture2D LoadTexture(const char *fileName);                                                       // Load an image as texture into GPU memory
+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)
+void ImageFormat(Image *image, int newFormat);                                                     // Convert image data to desired format
+void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp);                            // Dither image data to 16bpp or lower (Floyd-Steinberg dithering)
+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 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 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
+void UpdateTexture(Texture2D texture, void *pixels);                                               // Update GPU texture with new data
+
+void DrawTexture(Texture2D texture, int posX, int posY, Color tint);                               // Draw a Texture2D
+void DrawTextureV(Texture2D texture, Vector2 position, Color tint);                                // Draw a Texture2D with position defined as Vector2
+void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, float scale, Color tint);  // Draw a Texture2D with extended parameters
+void DrawTextureRec(Texture2D texture, Rectangle sourceRec, Vector2 position, Color tint);         // Draw a part of a texture defined by a rectangle
+void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle destRec, Vector2 origin,     // Draw a part of a texture defined by a rectangle with 'pro' parameters
+                    float rotation, Color tint);
+
+//------------------------------------------------------------------------------------
+// Font Loading and Text Drawing Functions (Module: text)
+//------------------------------------------------------------------------------------
+SpriteFont GetDefaultFont(void);                                                                   // Get the default SpriteFont
+SpriteFont LoadSpriteFont(const char *fileName);                                                   // Load a SpriteFont image into GPU memory
+void UnloadSpriteFont(SpriteFont spriteFont);                                                      // Unload SpriteFont from GPU memory
+
+void DrawText(const char *text, int posX, int posY, int fontSize, Color color);                    // Draw text (using default font)
+void DrawTextEx(SpriteFont spriteFont, const char* text, Vector2 position,                         // Draw text using SpriteFont and additional parameters
+                int fontSize, int spacing, Color tint);
+int MeasureText(const char *text, int fontSize);                                                   // Measure string width for default font
+Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, int fontSize, int spacing);         // Measure string size for SpriteFont
+
+void DrawFPS(int posX, int posY);                                                                  // Shows current FPS on top-left corner
+const char *FormatText(const char *text, ...);                                                     // Formatting of text with variables to 'embed'
+const char *SubText(const char *text, int position, int length);                                   // Get a piece of a text string
+
+//------------------------------------------------------------------------------------
+// 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
+void DrawCubeTexture(Texture2D texture, Vector3 position, float width, float height, float lenght, Color color); // Draw cube textured
+void DrawSphere(Vector3 centerPos, float radius, Color color);                                     // Draw sphere
+void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color color);            // Draw sphere with extended parameters
+void DrawSphereWires(Vector3 centerPos, float radius, int rings, int slices, Color color);         // Draw sphere wires
+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 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, 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
+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)
+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 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
+bool CheckCollisionSpheres(Vector3 centerA, float radiusA, Vector3 centerB, float radiusB);                     // Detect collision between two spheres
+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, 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
+//------------------------------------------------------------------------------------
+// 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
+
+//------------------------------------------------------------------------------------
+// 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
+Sound LoadSoundFromRES(const char *rresName, int resId);        // Load sound to memory from rRES file (raylib Resource)
+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 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)
+
+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)
+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
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // RAYLIB_H

+ 1 - 1
shaders/glsl100/bloom.fs

@@ -26,7 +26,7 @@ void main()
     }
     
     // Texel color fetching from texture sampler
-    vec4 texelColor = texture(texture0, fragTexCoord);
+    vec4 texelColor = texture2D(texture0, fragTexCoord);
     
     // Calculate final fragment color
     if (texelColor.r < 0.3) tc = sum*sum*0.012 + texelColor;

+ 1 - 1
shaders/glsl100/grayscale.fs

@@ -15,7 +15,7 @@ uniform vec4 colDiffuse;
 void main()
 {
     // Texel color fetching from texture sampler
-    vec4 texelColor = texture(texture0, fragTexCoord)*colDiffuse*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));

+ 155 - 0
shaders/glsl100/standard.fs

@@ -0,0 +1,155 @@
+#version 100
+
+precision mediump float;
+
+varying vec3 fragPosition;
+varying vec2 fragTexCoord;
+varying vec4 fragColor;
+varying vec3 fragNormal;
+
+uniform sampler2D texture0;
+uniform sampler2D texture1;
+uniform sampler2D texture2;
+
+uniform vec4 colAmbient;
+uniform vec4 colDiffuse;
+uniform vec4 colSpecular;
+uniform float glossiness;
+
+uniform int useNormal;
+uniform int useSpecular;
+
+uniform mat4 modelMatrix;
+uniform vec3 viewDir;
+
+struct Light {
+    int enabled;
+    int type;
+    vec3 position;
+    vec3 direction;
+    vec4 diffuse;
+    float intensity;
+    float radius;
+    float coneAngle;
+};
+
+const int maxLights = 8;
+uniform int lightsCount;
+uniform Light lights[maxLights];
+
+vec3 CalcPointLight(Light l, vec3 n, vec3 v, float s)
+{
+    vec3 surfacePos = vec3(modelMatrix*vec4(fragPosition, 1));
+    vec3 surfaceToLight = l.position - surfacePos;
+    
+    // Diffuse shading
+    float brightness = clamp(dot(n, surfaceToLight)/(length(surfaceToLight)*length(n)), 0, 1);
+    float diff = 1.0/dot(surfaceToLight/l.radius, surfaceToLight/l.radius)*brightness*l.intensity;
+    
+    // Specular shading
+    float spec = 0.0;
+    if (diff > 0.0)
+    {
+        vec3 h = normalize(-l.direction + v);
+        spec = pow(dot(n, h), 3 + glossiness)*s;
+    }
+    
+    return (diff*l.diffuse.rgb + spec*colSpecular.rgb);
+}
+
+vec3 CalcDirectionalLight(Light l, vec3 n, vec3 v, float s)
+{
+    vec3 lightDir = normalize(-l.direction);
+    
+    // Diffuse shading
+    float diff = clamp(dot(n, lightDir), 0.0, 1.0)*l.intensity;
+    
+    // Specular shading
+    float spec = 0.0;
+    if (diff > 0.0)
+    {
+        vec3 h = normalize(lightDir + v);
+        spec = pow(dot(n, h), 3 + glossiness)*s;
+    }
+    
+    // Combine results
+    return (diff*l.intensity*l.diffuse.rgb + spec*colSpecular.rgb);
+}
+
+vec3 CalcSpotLight(Light l, vec3 n, vec3 v, float s)
+{
+    vec3 surfacePos = vec3(modelMatrix*vec4(fragPosition, 1));
+    vec3 lightToSurface = normalize(surfacePos - l.position);
+    vec3 lightDir = normalize(-l.direction);
+    
+    // Diffuse shading
+    float diff = clamp(dot(n, lightDir), 0.0, 1.0)*l.intensity;
+    
+    // Spot attenuation
+    float attenuation = clamp(dot(n, lightToSurface), 0.0, 1.0);
+    attenuation = dot(lightToSurface, -lightDir);
+    
+    float lightToSurfaceAngle = degrees(acos(attenuation));
+    if (lightToSurfaceAngle > l.coneAngle) attenuation = 0.0;
+    
+    float falloff = (l.coneAngle - lightToSurfaceAngle)/l.coneAngle;
+    
+    // Combine diffuse and attenuation
+    float diffAttenuation = diff*attenuation;
+    
+    // Specular shading
+    float spec = 0.0;
+    if (diffAttenuation > 0.0)
+    {
+        vec3 h = normalize(lightDir + v);
+        spec = pow(dot(n, h), 3 + glossiness)*s;
+    }
+    
+    return (falloff*(diffAttenuation*l.diffuse.rgb + spec*colSpecular.rgb));
+}
+
+void main()
+{
+    // Calculate fragment normal in screen space
+    // NOTE: important to multiply model matrix by fragment normal to apply model transformation (rotation and scale)
+    mat3 normalMatrix = transpose(inverse(mat3(modelMatrix)));
+    vec3 normal = normalize(normalMatrix*fragNormal);
+
+    // Normalize normal and view direction vectors
+    vec3 n = normalize(normal);
+    vec3 v = normalize(viewDir);
+
+    // Calculate diffuse texture color fetching
+    vec4 texelColor = texture2D(texture0, fragTexCoord);
+    vec3 lighting = colAmbient.rgb;
+    
+    // Calculate normal texture color fetching or set to maximum normal value by default
+    if (useNormal == 1)
+    {
+        n *= texture2D(texture1, fragTexCoord).rgb;
+        n = normalize(n);
+    }
+    
+    // Calculate specular texture color fetching or set to maximum specular value by default
+    float spec = 1.0;
+    if (useSpecular == 1) spec *= normalize(texture2D(texture2, fragTexCoord).r);
+    
+    for (int i = 0; i < lightsCount; i++)
+    {
+        // Check if light is enabled
+        if (lights[i].enabled == 1)
+        {
+            // Calculate lighting based on light type
+            switch (lights[i].type)
+            {
+                case 0: lighting += CalcPointLight(lights[i], n, v, spec); break;
+                case 1: lighting += CalcDirectionalLight(lights[i], n, v, spec); break;
+                case 2: lighting += CalcSpotLight(lights[i], n, v, spec); break;
+                default: break;
+            }
+        }
+    }
+    
+    // Calculate final fragment color
+    gl_FragColor = vec4(texelColor.rgb*lighting*colDiffuse.rgb, texelColor.a*colDiffuse.a);
+}

+ 23 - 0
shaders/glsl100/standard.vs

@@ -0,0 +1,23 @@
+#version 100
+
+attribute vec3 vertexPosition;
+attribute vec3 vertexNormal;
+attribute vec2 vertexTexCoord;
+attribute vec4 vertexColor;
+
+varying vec3 fragPosition;
+varying vec2 fragTexCoord;
+varying vec4 fragColor;
+varying vec3 fragNormal;
+
+uniform mat4 mvpMatrix;
+
+void main()
+{
+    fragPosition = vertexPosition;
+    fragTexCoord = vertexTexCoord;
+    fragColor = vertexColor;
+    fragNormal = vertexNormal;
+
+    gl_Position = mvpMatrix*vec4(vertexPosition, 1.0);
+}

+ 0 - 0
examples/resources/shaders/standard.fs → shaders/glsl330/standard.fs


+ 0 - 0
examples/resources/shaders/standard.vs → shaders/glsl330/standard.vs


+ 2 - 11
src/Makefile

@@ -51,6 +51,7 @@ ifeq ($(PLATFORM),PLATFORM_RPI)
 else
     # define raylib graphics api to use (OpenGL 1.1 by default)
     GRAPHICS ?= GRAPHICS_API_OPENGL_11
+    #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)
@@ -92,13 +93,7 @@ else
 endif
 
 # define all object files required
-ifeq ($(PLATFORM),PLATFORM_DESKTOP)
-    OBJS = core.o rlgl.o glad.o shapes.o text.o textures.o models.o audio.o utils.o camera.o gestures.o stb_vorbis.o
-else
-    #GLAD only required on desktop platform
-    OBJS = core.o rlgl.o shapes.o text.o textures.o models.o audio.o stb_vorbis.o utils.o camera.o gestures.o
-endif
-
+OBJS = core.o rlgl.o shapes.o text.o textures.o models.o audio.o utils.o camera.o gestures.o stb_vorbis.o
 
 # typing 'make' will invoke the default target entry called 'all',
 # in this case, the 'default' target entry is raylib
@@ -153,10 +148,6 @@ camera.o: camera.c
 gestures.o: gestures.c
 	$(CC) -c gestures.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
 
-# compile glad module
-glad.o: external/glad.c
-	$(CC) -c external/glad.c $(CFLAGS) $(INCLUDES)
-
 # compile stb_vorbis library
 stb_vorbis.o: external/stb_vorbis.c
 	$(CC) -c external/stb_vorbis.c -O1 $(INCLUDES) -D$(PLATFORM)

+ 2 - 2
src/android/jni/Android.mk

@@ -46,13 +46,13 @@ LOCAL_SRC_FILES  :=\
                     ../../models.c \
                     ../../utils.c \
                     ../../audio.c \
-                    ../../stb_vorbis.c \
+                    ../../external/stb_vorbis.c \
 
 # Required includes paths (.h)
 LOCAL_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)/include $(LOCAL_PATH)/../..
 
 # Required flags for compilation: defines PLATFORM_ANDROID and GRAPHICS_API_OPENGL_ES2
-LOCAL_CFLAGS     := -Wall -std=c99 -Wno-missing-braces -g -DPLATFORM_ANDROID -DGRAPHICS_API_OPENGL_ES2
+LOCAL_CFLAGS     := -Wall -std=c99 -Wno-missing-braces -DPLATFORM_ANDROID -DGRAPHICS_API_OPENGL_ES2
 
 # Build the static library libraylib.a
 include $(BUILD_STATIC_LIBRARY)

+ 265 - 241
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.
@@ -37,12 +50,18 @@
 
 #include "AL/al.h"              // OpenAL basic header
 #include "AL/alc.h"             // OpenAL context header (like OpenGL, OpenAL requires a context to work)
-#include "AL/alext.h"           // OpenAL extensions for other format types
 
 #include <stdlib.h>             // Required for: malloc(), free()
 #include <string.h>             // Required for: strcmp(), strncmp()
 #include <stdio.h>              // Required for: FILE, fopen(), fclose(), fread()
 
+#ifndef AL_FORMAT_MONO_FLOAT32
+    #define AL_FORMAT_MONO_FLOAT32 0x10010
+#endif
+#ifndef AL_FORMAT_STEREO_FLOAT32
+    #define AL_FORMAT_STEREO_FLOAT32 0x10011
+#endif
+
 #if defined(AUDIO_STANDALONE)
     #include <stdarg.h>         // Required for: va_list, va_start(), vfprintf(), va_end()
 #else
@@ -62,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
@@ -80,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
@@ -93,39 +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)
@@ -135,11 +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 bool musicEnabled_g = false;
+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
@@ -151,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
@@ -198,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;
@@ -215,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();
@@ -234,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)
@@ -274,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;
@@ -287,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)
     {
@@ -308,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)   
     { 
@@ -362,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++)
@@ -393,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++)
@@ -404,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)
 //----------------------------------------------------------------------------------
@@ -798,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
@@ -824,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
-            musicEnabled_g = 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;
-            musicEnabled_g = 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
         {
@@ -880,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;
-            musicEnabled_g = 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
         {
@@ -914,28 +940,72 @@ 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 (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(musicStreams[index].stream);
+        
+        musicStreams[index].enabled = false;
         
-        if (musicChannels_g[index].chipTune && musicChannels_g[index].xmctx)
+        if (musicStreams[index].stream || musicStreams[index].xmctx)
         {
-            jar_xm_free_context(musicChannels_g[index].xmctx);
-            musicChannels_g[index].xmctx = 0;
+            musicStreams[index].stream = NULL;
+            musicStreams[index].xmctx = NULL;
         }
-        else if (musicChannels_g[index].chipTune && musicChannels_g[index].modctx.mod_loaded) jar_mod_unload(&musicChannels_g[index].modctx);
-        else stb_vorbis_close(musicChannels_g[index].stream);
-        
-        if (!GetMusicStreamCount()) musicEnabled_g = false;
+    }
+}
+
+// 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 (musicChannels_g[index].stream || musicChannels_g[index].xmctx)
+        if (!active && musicStreams[index].loop)
         {
-            musicChannels_g[index].stream = NULL;
-            musicChannels_g[index].xmctx = NULL;
+            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);
+        
     }
 }
 
@@ -947,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;
@@ -957,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 && musicEnabled_g)
+    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;
     }
 }
 
@@ -971,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;
         }
     }
 }
@@ -990,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;
     }
@@ -1003,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);
     }
 }
 
@@ -1023,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;
 }
@@ -1034,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);
         }
     }
 
@@ -1071,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;
@@ -1103,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;
@@ -1129,62 +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) && musicEnabled_g && 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;
-            }
-            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 = true;
-        }
-
-        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)
 {

+ 21 - 14
src/audio.h

@@ -2,13 +2,26 @@
 *
 *   raylib.audio
 *
-*   Basic functions to manage Audio: InitAudioDevice, LoadAudioFiles, PlayAudioFiles
+*   Basic functions to manage Audio: 
+*       Manage audio device (init/close)
+*       Load and Unload audio files
+*       Play/Stop/Pause/Resume loaded audio
+*       Manage mixing channels
+*       Manage raw audio context
 *
 *   Uses external lib:
 *       OpenAL Soft - Audio device management lib (http://kcat.strangesoft.net/openal.html)
 *       stb_vorbis - Ogg audio files loading (http://www.nothings.org/stb_vorbis/)
+*       jar_xm - XM module file loading
+*       jar_mod - MOD audio file loading
 *
-*   Copyright (c) 2015 Ramon Santamaria (@raysan5)
+*   Many thanks to Joshua Reisenauer (github: @kd7tck) for the following additions:
+*       XM audio module support (jar_xm)
+*       MOD audio module support (jar_mod)
+*       Mixing channels support
+*       Raw audio context support
+*
+*   Copyright (c) 2014-2016 Ramon Santamaria (@raysan5)
 *
 *   This software is provided "as-is", without any express or implied warranty. In no event
 *   will the authors be held liable for any damages arising from the use of this software.
@@ -63,9 +76,6 @@ typedef struct Wave {
     short channels;
 } Wave;
 
-typedef int RawAudioContext;
-
-
 #ifdef __cplusplus
 extern "C" {            // Prevents name mangling of functions
 #endif
@@ -80,7 +90,7 @@ extern "C" {            // Prevents name mangling of functions
 //----------------------------------------------------------------------------------
 void InitAudioDevice(void);                                     // Initialize audio device and context
 void CloseAudioDevice(void);                                    // Close the audio device and context (and music stream)
-bool IsAudioDeviceReady(void);                                  // True if call to InitAudioDevice() was successful and CloseAudioDevice() has not been called yet
+bool IsAudioDeviceReady(void);                                  // Check if device has been initialized successfully
 
 Sound LoadSound(char *fileName);                                // Load sound to memory
 Sound LoadSoundFromWave(Wave wave);                             // Load sound to memory from wave data
@@ -100,17 +110,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
 }

+ 112 - 517
src/core.c

@@ -9,7 +9,7 @@
 *       PLATFORM_ANDROID - Only OpenGL ES 2.0 devices
 *       PLATFORM_RPI - Rapsberry Pi (tested on Raspbian)
 *       PLATFORM_WEB - Emscripten, HTML5
-*       PLATFORM_OCULUS - Oculus Rift CV1 (with desktop mirror)
+*       Oculus Rift CV1 (with desktop mirror) - View [rlgl] module to enable it
 *
 *   On PLATFORM_DESKTOP, the external lib GLFW3 (www.glfw.com) is used to manage graphic
 *   device, OpenGL context and input on multiple operating systems (Windows, Linux, OSX).
@@ -54,18 +54,6 @@
 #include <string.h>         // String function definitions, memset()
 #include <errno.h>          // Macros for reporting and retrieving error conditions through error codes
 
-#if defined(PLATFORM_OCULUS)
-    #define PLATFORM_DESKTOP      // Enable PLATFORM_DESKTOP code-base
-#endif
-
-#if defined(PLATFORM_DESKTOP)
-    #include "external/glad.h"    // GLAD library: Manage OpenGL headers and extensions
-#endif
-
-#if defined(PLATFORM_OCULUS)
-    #include "../examples/oculus_glfw_sample/OculusSDK/LibOVR/Include/OVR_CAPI_GL.h"    // Oculus SDK for OpenGL
-#endif
-
 #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
     //#define GLFW_INCLUDE_NONE   // Disable the standard OpenGL header inclusion on GLFW3
     #include <GLFW/glfw3.h>       // GLFW3 library: Windows, OpenGL context and Input management
@@ -138,31 +126,7 @@
 //----------------------------------------------------------------------------------
 // Types and Structures Definition
 //----------------------------------------------------------------------------------
-#if defined(PLATFORM_OCULUS)
-typedef struct OculusBuffer {
-    ovrTextureSwapChain textureChain;
-    GLuint depthId;
-    GLuint fboId;
-    int width;
-    int height;
-} OculusBuffer;
-
-typedef struct OculusMirror {
-    ovrMirrorTexture texture;
-    GLuint fboId;
-    int width;
-    int height;
-} OculusMirror;
-
-typedef struct OculusLayer {
-    ovrViewScaleDesc viewScaleDesc;
-    ovrLayerEyeFov eyeLayer;      // layer 0
-    //ovrLayerQuad quadLayer;     // TODO: layer 1: '2D' quad for GUI
-    Matrix eyeProjections[2];
-    int width;
-    int height;
-} OculusLayer;
-#endif
+// ...
 
 //----------------------------------------------------------------------------------
 // Global Variables Definition
@@ -209,35 +173,22 @@ float gamepadAxisValues[MAX_GAMEPADS][MAX_GAMEPAD_AXIS];      // Gamepad axis st
 #endif
 
 #if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI)
-static EGLDisplay display;          // Native display device (physical screen connection)
-static EGLSurface surface;          // Surface to draw on, framebuffers (connected to context)
-static EGLContext context;          // Graphic context, mode in which drawing can be done
-static EGLConfig config;            // Graphic config
-static uint64_t baseTime;                   // Base time measure for hi-res timer
-static bool windowShouldClose = false;      // Flag to set window for closing
-#endif
-
-#if defined(PLATFORM_OCULUS)
-// OVR device variables
-static ovrSession session;
-static ovrHmdDesc hmdDesc;
-static ovrGraphicsLuid luid;
-static OculusLayer layer;
-static OculusBuffer buffer;
-static OculusMirror mirror;
-static unsigned int frameIndex = 0;
-#endif
-
-static unsigned int displayWidth, displayHeight;     // Display width and height (monitor, device-screen, LCD, ...)
-static int screenWidth, screenHeight;       // Screen width and height (used render area)
-static int renderWidth, renderHeight;       // Framebuffer width and height (render area)
-                                            // NOTE: Framebuffer could include black bars
+static EGLDisplay display;              // Native display device (physical screen connection)
+static EGLSurface surface;              // Surface to draw on, framebuffers (connected to context)
+static EGLContext context;              // Graphic context, mode in which drawing can be done
+static EGLConfig config;                // Graphic config
+static uint64_t baseTime;               // Base time measure for hi-res timer
+static bool windowShouldClose = false;  // Flag to set window for closing
+#endif
 
+// 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, 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)
 static Matrix downscaleView;                // Matrix to downscale view (in case screen size bigger than display size)
-static Matrix cameraView;                   // Store camera view matrix (required for Oculus Rift)
 
 #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
 static const char *windowTitle;             // Window text title...
@@ -262,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
@@ -274,20 +225,19 @@ 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
 
 //----------------------------------------------------------------------------------
 // Other Modules Functions Declaration (required by core)
 //----------------------------------------------------------------------------------
-extern void LoadDefaultFont(void);              // [Module: text] Loads default font on InitWindow()
-extern void UnloadDefaultFont(void);            // [Module: text] Unloads default font from GPU memory
+extern void LoadDefaultFont(void);          // [Module: text] Loads default font on InitWindow()
+extern void UnloadDefaultFont(void);        // [Module: text] Unloads default font from GPU memory
 
 //----------------------------------------------------------------------------------
 // Module specific Functions Declaration
 //----------------------------------------------------------------------------------
-static void InitDisplay(int width, int height);         // Initialize display device and framebuffer
-static void InitGraphics(void);                         // Initialize OpenGL graphics
+static void InitGraphicsDevice(int width, int height);  // Initialize graphics device
 static void SetupFramebufferSize(int displayWidth, int displayHeight);
 static void InitTimer(void);                            // Initialize timer
 static double GetTime(void);                            // Returns time since InitTimer() was run
@@ -336,19 +286,6 @@ static void InitGamepad(void);                          // Init raw gamepad inpu
 static void *GamepadThread(void *arg);                  // Mouse reading thread
 #endif
 
-#if defined(PLATFORM_OCULUS)
-// Oculus Rift functions
-static Matrix FromOvrMatrix(ovrMatrix4f ovrM);
-static OculusBuffer LoadOculusBuffer(ovrSession session, int width, int height);
-static void UnloadOculusBuffer(ovrSession session, OculusBuffer buffer);
-static void SetOculusBuffer(ovrSession session, OculusBuffer buffer);
-static void UnsetOculusBuffer(OculusBuffer buffer);
-static OculusMirror LoadOculusMirror(ovrSession session, int width, int height);    // Load Oculus mirror buffers
-static void UnloadOculusMirror(ovrSession session, OculusMirror mirror);            // Unload Oculus mirror buffers
-static void BlitOculusMirror(ovrSession session, OculusMirror mirror);
-static OculusLayer InitOculusLayer(ovrSession session);
-#endif
-
 //----------------------------------------------------------------------------------
 // Module Functions Definition - Window and OpenGL Context Functions
 //----------------------------------------------------------------------------------
@@ -361,11 +298,8 @@ void InitWindow(int width, int height, const char *title)
     // Store window title (could be useful...)
     windowTitle = title;
 
-    // Init device display (monitor, LCD, ...)
-    InitDisplay(width, height);
-
-    // Init OpenGL graphics
-    InitGraphics();
+    // Init graphics device (display device and OpenGL context)
+    InitGraphicsDevice(width, height);
 
     // Load default font for convenience
     // NOTE: External function (defined in module: text)
@@ -397,11 +331,6 @@ void InitWindow(int width, int height, const char *title)
     //emscripten_set_gamepaddisconnected_callback(NULL, 1, EmscriptenInputCallback);
 #endif
 
-#if defined(PLATFORM_OCULUS)
-    // Recenter OVR tracking origin
-    ovr_RecenterTrackingOrigin(session);
-#endif
-
     mousePosition.x = (float)screenWidth/2.0f;
     mousePosition.y = (float)screenHeight/2.0f;
 
@@ -510,74 +439,20 @@ void CloseWindow(void)
 
         eglTerminate(display);
         display = EGL_NO_DISPLAY;
-    }
+    }   
 #endif
 
-#if defined(PLATFORM_OCULUS)
-    ovr_Destroy(session);   // Must be called after glfwTerminate()
-    ovr_Shutdown();
+#if defined(PLATFORM_RPI)
+    // Wait for mouse and gamepad threads to finish before closing
+    // NOTE: Those threads should already have finished at this point
+    // because they are controlled by windowShouldClose variable
+    pthread_join(mouseThreadId, NULL);
+    pthread_join(gamepadThreadId, NULL);
 #endif
 
     TraceLog(INFO, "Window closed successfully");
 }
 
-#if defined(PLATFORM_OCULUS)
-// Init Oculus Rift device
-// NOTE: Device initialization should be done before window creation?
-void InitOculusDevice(void)
-{
-    ovrResult result = ovr_Initialize(NULL);
-    if (OVR_FAILURE(result)) TraceLog(ERROR, "OVR: Could not initialize Oculus device");
-
-    result = ovr_Create(&session, &luid);
-    if (OVR_FAILURE(result))
-    {
-        TraceLog(WARNING, "OVR: Could not create Oculus session");
-        ovr_Shutdown();
-    }
-
-    hmdDesc = ovr_GetHmdDesc(session);
-    
-    TraceLog(INFO, "OVR: Product Name: %s", hmdDesc.ProductName);
-    TraceLog(INFO, "OVR: Manufacturer: %s", hmdDesc.Manufacturer);
-    TraceLog(INFO, "OVR: Product ID: %i", hmdDesc.ProductId);
-    TraceLog(INFO, "OVR: Product Type: %i", hmdDesc.Type);
-    TraceLog(INFO, "OVR: Serian Number: %s", hmdDesc.SerialNumber);
-    TraceLog(INFO, "OVR: Resolution: %ix%i", hmdDesc.Resolution.w, hmdDesc.Resolution.h);
-    
-    screenWidth = hmdDesc.Resolution.w/2;
-    screenHeight = hmdDesc.Resolution.h/2;
-    
-    // Initialize Oculus Buffers
-    layer = InitOculusLayer(session);   
-    buffer = LoadOculusBuffer(session, layer.width, layer.height);
-    mirror = LoadOculusMirror(session, hmdDesc.Resolution.w/2, hmdDesc.Resolution.h/2);
-    layer.eyeLayer.ColorTexture[0] = buffer.textureChain;     //SetOculusLayerTexture(eyeLayer, buffer.textureChain);
-}
-
-// Close Oculus Rift device
-void CloseOculusDevice(void)
-{
-    UnloadOculusMirror(session, mirror);    // Unload Oculus mirror buffer
-    UnloadOculusBuffer(session, buffer);    // Unload Oculus texture buffers
-
-    ovr_Destroy(session);   // Must be called after glfwTerminate() -->  REALLY???
-    ovr_Shutdown();
-}
-
-// Update Oculus Rift tracking (position and orientation)
-void UpdateOculusTracking(void)
-{
-    frameIndex++;
-   
-    ovrPosef eyePoses[2];
-    ovr_GetEyePoses(session, frameIndex, ovrTrue, layer.viewScaleDesc.HmdToEyeOffset, eyePoses, &layer.eyeLayer.SensorSampleTime);
-    
-    layer.eyeLayer.RenderPose[0] = eyePoses[0];
-    layer.eyeLayer.RenderPose[1] = eyePoses[1];
-}
-#endif
-
 // Detect if KEY_ESCAPE pressed or Close icon pressed
 bool WindowShouldClose(void)
 {
@@ -604,16 +479,14 @@ bool IsWindowMinimized(void)
 }
 
 // Fullscreen toggle
-// TODO: When destroying window context is lost and resources too, take care!
 void ToggleFullscreen(void)
 {
 #if defined(PLATFORM_DESKTOP)
     fullscreen = !fullscreen;          // Toggle fullscreen flag
 
-    rlglClose();                       // De-init rlgl
-    glfwDestroyWindow(window);         // Destroy the current window (we will recreate it!)
-
-    InitWindow(screenWidth, screenHeight, windowTitle);
+    // NOTE: glfwSetWindowMonitor() doesn't work properly (bugs)
+    if (fullscreen) glfwSetWindowMonitor(window, glfwGetPrimaryMonitor(), 0, 0, screenWidth, screenHeight, GLFW_DONT_CARE);
+    else glfwSetWindowMonitor(window, NULL, 0, 0, screenWidth, screenHeight, GLFW_DONT_CARE);
 #endif
 
 #if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI)
@@ -647,18 +520,6 @@ void BeginDrawing(void)
     updateTime = currentTime - previousTime;
     previousTime = currentTime;
     
-#if defined(PLATFORM_OCULUS)
-    frameIndex++;
-   
-    ovrPosef eyePoses[2];
-    ovr_GetEyePoses(session, frameIndex, ovrTrue, layer.viewScaleDesc.HmdToEyeOffset, eyePoses, &layer.eyeLayer.SensorSampleTime);
-    
-    layer.eyeLayer.RenderPose[0] = eyePoses[0];
-    layer.eyeLayer.RenderPose[1] = eyePoses[1];
-    
-    SetOculusBuffer(session, buffer);
-#endif
-
     rlClearScreenBuffers();             // Clear current framebuffers
     rlLoadIdentity();                   // Reset current matrix (MODELVIEW)
     rlMultMatrixf(MatrixToFloat(downscaleView));       // If downscale required, apply it here
@@ -670,49 +531,7 @@ void BeginDrawing(void)
 // End canvas drawing and Swap Buffers (Double Buffering)
 void EndDrawing(void)
 {
-#if defined(PLATFORM_OCULUS)
-    for (int eye = 0; eye < 2; eye++)
-    {
-        rlViewport(layer.eyeLayer.Viewport[eye].Pos.x, layer.eyeLayer.Viewport[eye].Pos.y, layer.eyeLayer.Viewport[eye].Size.w, layer.eyeLayer.Viewport[eye].Size.h);
-
-        Quaternion eyeRPose = (Quaternion){ layer.eyeLayer.RenderPose[eye].Orientation.x, 
-                                            layer.eyeLayer.RenderPose[eye].Orientation.y, 
-                                            layer.eyeLayer.RenderPose[eye].Orientation.z, 
-                                            layer.eyeLayer.RenderPose[eye].Orientation.w };
-        QuaternionInvert(&eyeRPose);
-        Matrix eyeOrientation = QuaternionToMatrix(eyeRPose);
-        Matrix eyeTranslation = MatrixTranslate(-layer.eyeLayer.RenderPose[eye].Position.x, 
-                                                -layer.eyeLayer.RenderPose[eye].Position.y, 
-                                                -layer.eyeLayer.RenderPose[eye].Position.z);
-
-        Matrix eyeView = MatrixMultiply(eyeTranslation, eyeOrientation);
-        Matrix modelEyeView = MatrixMultiply(cameraView, eyeView);  // Using internal camera modelview matrix
-
-        SetMatrixModelview(modelEyeView);
-        SetMatrixProjection(layer.eyeProjections[eye]);
-#endif
-    
-        rlglDraw();                     // Draw Buffers (Only OpenGL 3+ and ES2)
-
-#if defined(PLATFORM_OCULUS)
-    }
-    
-    UnsetOculusBuffer(buffer);
-    
-    ovr_CommitTextureSwapChain(session, buffer.textureChain);
-    
-    ovrLayerHeader *layers = &layer.eyeLayer.Header;
-    ovr_SubmitFrame(session, frameIndex, &layer.viewScaleDesc, &layers, 1);
-
-    // Blit mirror texture to back buffer
-    BlitOculusMirror(session, mirror);
-
-    // Get session status information
-    ovrSessionStatus sessionStatus;
-    ovr_GetSessionStatus(session, &sessionStatus);
-    if (sessionStatus.ShouldQuit) TraceLog(WARNING, "OVR: Session should quit...");
-    if (sessionStatus.ShouldRecenter) ovr_RecenterTrackingOrigin(session);
-#endif
+    rlglDraw();                     // Draw Buffers (Only OpenGL 3+ and ES2)
 
     SwapBuffers();                  // Copy back buffer to front buffer
     PollInputEvents();              // Poll user events
@@ -766,6 +585,8 @@ void End2dMode(void)
 void Begin3dMode(Camera camera)
 {
     rlglDraw();                         // Draw Buffers (Only OpenGL 3+ and ES2)
+    
+    if (IsVrDeviceReady()) BeginVrDrawing();
 
     rlMatrixMode(RL_PROJECTION);        // Switch to projection matrix
 
@@ -784,7 +605,7 @@ void Begin3dMode(Camera camera)
     rlLoadIdentity();                   // Reset current matrix (MODELVIEW)
 
     // Setup Camera view
-    cameraView = MatrixLookAt(camera.position, camera.target, camera.up);
+    Matrix cameraView = MatrixLookAt(camera.position, camera.target, camera.up);
     rlMultMatrixf(MatrixToFloat(cameraView));      // Multiply MODELVIEW matrix by view matrix (camera)
     
     rlEnableDepthTest();                // Enable DEPTH_TEST for 3D
@@ -792,8 +613,10 @@ void Begin3dMode(Camera camera)
 
 // Ends 3D mode and returns to default 2D orthographic mode
 void End3dMode(void)
-{
-    rlglDraw();                         // Draw Buffers (Only OpenGL 3+ and ES2)
+{        
+    rlglDraw();                         // Process internal buffers (update + draw)
+    
+    if (IsVrDeviceReady()) EndVrDrawing();
 
     rlMatrixMode(RL_PROJECTION);        // Switch to projection matrix
     rlPopMatrix();                      // Restore previous matrix (PROJECTION) from matrix stack
@@ -1615,7 +1438,7 @@ bool IsButtonReleased(int button)
 // Initialize display device and framebuffer
 // NOTE: width and height represent the screen (framebuffer) desired size, not actual display size
 // If width or height are 0, default display size will be used for framebuffer size
-static void InitDisplay(int width, int height)
+static void InitGraphicsDevice(int width, int height)
 {
     screenWidth = width;        // User desired width
     screenHeight = height;      // User desired height
@@ -1625,31 +1448,7 @@ static void InitDisplay(int width, int height)
 
     // Downscale matrix is required in case desired screen area is bigger than display area
     downscaleView = MatrixIdentity();
-    
-#if defined(PLATFORM_OCULUS)
-    ovrResult result = ovr_Initialize(NULL);
-    if (OVR_FAILURE(result)) TraceLog(ERROR, "OVR: Could not initialize Oculus device");
 
-    result = ovr_Create(&session, &luid);
-    if (OVR_FAILURE(result))
-    {
-        TraceLog(WARNING, "OVR: Could not create Oculus session");
-        ovr_Shutdown();
-    }
-
-    hmdDesc = ovr_GetHmdDesc(session);
-    
-    TraceLog(INFO, "OVR: Product Name: %s", hmdDesc.ProductName);
-    TraceLog(INFO, "OVR: Manufacturer: %s", hmdDesc.Manufacturer);
-    TraceLog(INFO, "OVR: Product ID: %i", hmdDesc.ProductId);
-    TraceLog(INFO, "OVR: Product Type: %i", hmdDesc.Type);
-    TraceLog(INFO, "OVR: Serian Number: %s", hmdDesc.SerialNumber);
-    TraceLog(INFO, "OVR: Resolution: %ix%i", hmdDesc.Resolution.w, hmdDesc.Resolution.h);
-    
-    screenWidth = hmdDesc.Resolution.w/2;
-    screenHeight = hmdDesc.Resolution.h/2;
-#endif
-    
 #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
     glfwSetErrorCallback(ErrorCallback);
 
@@ -1686,16 +1485,21 @@ static void InitDisplay(int width, int height)
     // NOTE: When asking for an OpenGL context version, most drivers provide highest supported version
     // with forward compatibility to older OpenGL versions.
     // For example, if using OpenGL 1.1, driver can provide a 3.3 context fordward compatible.
-
-    // Check selection OpenGL version (not initialized yet!)
-    if (rlGetVersion() == OPENGL_33)
+    
+    if (configFlags & FLAG_MSAA_4X_HINT)
     {
-        if (configFlags & FLAG_MSAA_4X_HINT)
-        {
-            glfwWindowHint(GLFW_SAMPLES, 4);       // Enables multisampling x4 (MSAA), default is 0
-            TraceLog(INFO, "Trying to enable MSAA x4");
-        }
+        glfwWindowHint(GLFW_SAMPLES, 4);       // Enables multisampling x4 (MSAA), default is 0
+        TraceLog(INFO, "Trying to enable MSAA x4");
+    }
 
+    // Check selection OpenGL version
+    if (rlGetVersion() == OPENGL_21)
+    {
+        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);        // Choose OpenGL major version (just hint)
+        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);        // Choose OpenGL minor version (just hint)
+    }
+    else if (rlGetVersion() == OPENGL_33)
+    {
         glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);        // Choose OpenGL major version (just hint)
         glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);        // Choose OpenGL minor version (just hint)
         glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // Profiles Hint: Only 3.3 and above!
@@ -1710,25 +1514,40 @@ static void InitDisplay(int width, int height)
 
     if (fullscreen)
     {
-        // At this point we need to manage render size vs screen size
-        // NOTE: This function uses and modifies global module variables: 
-        //       screenWidth/screenHeight - renderWidth/renderHeight - downscaleView
-        SetupFramebufferSize(displayWidth, displayHeight);
-        
-        // TODO: SetupFramebufferSize() does not consider properly display video modes.
-        // It setups a renderWidth/renderHeight with black bars that could not match a valid video mode,
-        // and so, framebuffer is not scaled properly to some monitors.
-        
+        // Obtain recommended displayWidth/displayHeight from a valid videomode for the monitor
         int count; 
         const GLFWvidmode *modes = glfwGetVideoModes(glfwGetPrimaryMonitor(), &count);
         
+        // Get closest videomode to desired screenWidth/screenHeight
         for (int i = 0; i < count; i++)
         {
-            // TODO: Check modes[i]->width;
-            // TODO: Check modes[i]->height;
+            if (modes[i].width >= screenWidth)
+            {
+                if (modes[i].height >= screenHeight)
+                {
+                    displayWidth = modes[i].width;
+                    displayHeight = modes[i].height;
+                    break;
+                }
+            }
         }
         
-        window = glfwCreateWindow(screenWidth, screenHeight, windowTitle, glfwGetPrimaryMonitor(), NULL);
+        TraceLog(WARNING, "Closest fullscreen videomode: %i x %i", displayWidth, displayHeight);
+
+        // NOTE: ISSUE: Closest videomode could not match monitor aspect-ratio, for example,
+        // for a desired screen size of 800x450 (16:9), closest supported videomode is 800x600 (4:3),
+        // framebuffer is rendered correctly but once displayed on a 16:9 monitor, it gets stretched
+        // by the sides to fit all monitor space...
+
+        // At this point we need to manage render size vs screen size
+        // NOTE: This function uses and modifies global module variables: 
+        //       screenWidth/screenHeight - renderWidth/renderHeight - downscaleView
+        SetupFramebufferSize(displayWidth, displayHeight);
+
+        window = glfwCreateWindow(displayWidth, displayHeight, windowTitle, glfwGetPrimaryMonitor(), NULL);
+        
+        // NOTE: Full-screen change, not working properly...
+        //glfwSetWindowMonitor(window, glfwGetPrimaryMonitor(), 0, 0, screenWidth, screenHeight, GLFW_DONT_CARE);
     }
     else
     {
@@ -1778,24 +1597,12 @@ static void InitDisplay(int width, int height)
 #endif
 
     glfwMakeContextCurrent(window);
-#if defined(PLATFORM_OCULUS)
-    glfwSwapInterval(0);
-#endif
+    glfwSwapInterval(0);                // Disable VSync by default
 
 #if defined(PLATFORM_DESKTOP)
-    // Load OpenGL 3.3 extensions using GLAD
-    if (rlGetVersion() == OPENGL_33)
-    {
-        // NOTE: glad is generated and contains only required OpenGL 3.3 Core extensions
-        if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) TraceLog(WARNING, "GLAD: Cannot load OpenGL extensions");
-        else TraceLog(INFO, "GLAD: OpenGL extensions loaded successfully");
-
-        if (GLAD_GL_VERSION_3_3) TraceLog(INFO, "OpenGL 3.3 Core profile supported");
-        else TraceLog(ERROR, "OpenGL 3.3 Core profile not supported");
-        
-        // With GLAD, we can check if an extension is supported using the GLAD_GL_xxx booleans
-        //if (GLAD_GL_ARB_vertex_array_object) // Use GL_ARB_vertex_array_object
-    }
+    // Load OpenGL 3.3 extensions
+    // NOTE: GLFW loader function is passed as parameter
+    rlglLoadExtensions(glfwGetProcAddress);
 #endif
     
     // Enables GPU v-sync, so frames are not limited to screen refresh rate (60Hz -> 60 FPS)
@@ -1956,37 +1763,33 @@ static void InitDisplay(int width, int height)
         TraceLog(INFO, "Viewport offsets: %i, %i", renderOffsetX, renderOffsetY);
     }
 #endif // defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI)
-}
 
-// Initialize OpenGL graphics
-static void InitGraphics(void)
-{
-    rlglInit();                     // Init rlgl
-    rlglInitGraphics(renderOffsetX, renderOffsetY, renderWidth, renderHeight);  // Init graphics (OpenGL stuff)
+    // Initialize OpenGL context (states and resources)
+    rlglInit(screenWidth, screenHeight);
+    
+    // Initialize screen viewport (area of the screen that you will actually draw to)
+    // NOTE: Viewport must be recalculated if screen is resized
+    rlViewport(renderOffsetX/2, renderOffsetY/2, renderWidth - renderOffsetX, renderHeight - renderOffsetY);
 
-#if defined(PLATFORM_OCULUS)
-    // Initialize Oculus Buffers
-    layer = InitOculusLayer(session);   
-    buffer = LoadOculusBuffer(session, layer.width, layer.height);
-    mirror = LoadOculusMirror(session, hmdDesc.Resolution.w/2, hmdDesc.Resolution.h/2);
-    layer.eyeLayer.ColorTexture[0] = buffer.textureChain;     //SetOculusLayerTexture(eyeLayer, buffer.textureChain);
-#endif
+    // Initialize internal projection and modelview matrices
+    // NOTE: Default to orthographic projection mode with top-left corner at (0,0)
+    rlMatrixMode(RL_PROJECTION);                // Switch to PROJECTION matrix
+    rlLoadIdentity();                           // Reset current matrix (PROJECTION)
+    rlOrtho(0, renderWidth - renderOffsetX, renderHeight - renderOffsetY, 0, 0.0f, 1.0f); 
+    rlMatrixMode(RL_MODELVIEW);                 // Switch back to MODELVIEW matrix
+    rlLoadIdentity();                           // Reset current matrix (MODELVIEW)
 
     ClearBackground(RAYWHITE);      // Default background color for raylib games :P
 
 #if defined(PLATFORM_ANDROID)
-    windowReady = true;     // IMPORTANT!
+    windowReady = true;             // IMPORTANT!
 #endif
 }
 
 // Compute framebuffer size relative to screen size and display size
-// NOTE: Global variables renderWidth/renderHeight can be modified
+// NOTE: Global variables renderWidth/renderHeight and renderOffsetX/renderOffsetY can be modified
 static void SetupFramebufferSize(int displayWidth, int displayHeight)
-{
-    // TODO: SetupFramebufferSize() does not consider properly display video modes.
-    // It setups a renderWidth/renderHeight with black bars that could not match a valid video mode,
-    // and so, framebuffer is not scaled properly to some monitors.
-    
+{    
     // Calculate renderWidth and renderHeight, we have the display size (input params) and the desired screen size (global var)
     if ((screenWidth > displayWidth) || (screenHeight > displayHeight))
     {
@@ -2335,8 +2138,14 @@ static void CursorEnterCallback(GLFWwindow *window, int enter)
 // NOTE: Window resizing not allowed by default
 static void WindowSizeCallback(GLFWwindow *window, int width, int height)
 {
-    // If window is resized, graphics device is re-initialized (but only ortho mode)
-    rlglInitGraphics(0, 0, width, height);
+    // If window is resized, viewport and projection matrix needs to be re-calculated
+    rlViewport(0, 0, width, height);            // Set viewport width and height
+    rlMatrixMode(RL_PROJECTION);                // Switch to PROJECTION matrix
+    rlLoadIdentity();                           // Reset current matrix (PROJECTION)
+    rlOrtho(0, width, height, 0, 0.0f, 1.0f);   // Orthographic projection mode with top-left corner at (0,0)
+    rlMatrixMode(RL_MODELVIEW);                 // Switch back to MODELVIEW matrix
+    rlLoadIdentity();                           // Reset current matrix (MODELVIEW)
+    rlClearScreenBuffers();                     // Clear screen buffers (color and depth)
 
     // Window size must be updated to be used on 3D mode to get new aspect ratio (Begin3dMode())
     screenWidth = width;
@@ -2345,9 +2154,6 @@ static void WindowSizeCallback(GLFWwindow *window, int width, int height)
     renderHeight = height;
     
     // NOTE: Postprocessing texture is not scaled to new size
-
-    // Background must be also re-cleared
-    ClearBackground(RAYWHITE);
 }
 
 // GLFW3 WindowIconify Callback, runs when window is minimized/restored
@@ -2414,11 +2220,8 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
                 }
                 else
                 {
-                    // Init device display (monitor, LCD, ...)
-                    InitDisplay(screenWidth, screenHeight);
-
-                    // Init OpenGL graphics
-                    InitGraphics();
+                    // Init graphics device (display device and OpenGL context)
+                    InitGraphicsDevice(screenWidth, screenHeight);
 
                     // Load default font for convenience
                     // NOTE: External function (defined in module: text)
@@ -2871,7 +2674,7 @@ static void *MouseThread(void *arg)
     int mouseRelX = 0;
     int mouseRelY = 0;
 
-    while(1)
+    while (!windowShouldClose)
     {
         if (read(mouseStream, &mouse, sizeof(MouseEvent)) == (int)sizeof(MouseEvent))
         {
@@ -2961,7 +2764,7 @@ static void *GamepadThread(void *arg)
     // Read gamepad event
     struct js_event gamepadEvent;
     
-    while (1) 
+    while (!windowShouldClose)
     {
         for (int i = 0; i < MAX_GAMEPADS; i++)
         {
@@ -2996,215 +2799,7 @@ static void *GamepadThread(void *arg)
 
     return NULL;
 }
-#endif
-
-
-#if defined(PLATFORM_OCULUS)
-// Convert from Oculus ovrMatrix4f struct to raymath Matrix struct
-static Matrix FromOvrMatrix(ovrMatrix4f ovrmat)
-{
-    Matrix rmat;
-    
-    rmat.m0 = ovrmat.M[0][0];
-    rmat.m1 = ovrmat.M[1][0];
-    rmat.m2 = ovrmat.M[2][0];
-    rmat.m3 = ovrmat.M[3][0];
-    rmat.m4 = ovrmat.M[0][1];
-    rmat.m5 = ovrmat.M[1][1];
-    rmat.m6 = ovrmat.M[2][1];
-    rmat.m7 = ovrmat.M[3][1];
-    rmat.m8 = ovrmat.M[0][2];
-    rmat.m9 = ovrmat.M[1][2];
-    rmat.m10 = ovrmat.M[2][2];
-    rmat.m11 = ovrmat.M[3][2];
-    rmat.m12 = ovrmat.M[0][3];
-    rmat.m13 = ovrmat.M[1][3];
-    rmat.m14 = ovrmat.M[2][3];
-    rmat.m15 = ovrmat.M[3][3];
-    
-    MatrixTranspose(&rmat);
-    
-    return rmat;
-}
-
-// Load Oculus required buffers: texture-swap-chain, fbo, texture-depth
-static OculusBuffer LoadOculusBuffer(ovrSession session, int width, int height)
-{
-    OculusBuffer buffer;
-    buffer.width = width;
-    buffer.height = height;
-    
-    // Create OVR texture chain
-    ovrTextureSwapChainDesc desc = {};
-    desc.Type = ovrTexture_2D;
-    desc.ArraySize = 1;
-    desc.Width = width;
-    desc.Height = height;
-    desc.MipLevels = 1;
-    desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;   // Requires glEnable(GL_FRAMEBUFFER_SRGB);
-    desc.SampleCount = 1;
-    desc.StaticImage = ovrFalse;
-
-    ovrResult result = ovr_CreateTextureSwapChainGL(session, &desc, &buffer.textureChain);
-    
-    if (!OVR_SUCCESS(result)) TraceLog(WARNING, "OVR: Failed to create swap textures buffer");
-
-    int textureCount = 0;
-    ovr_GetTextureSwapChainLength(session, buffer.textureChain, &textureCount);
-    
-    if (!OVR_SUCCESS(result) || !textureCount) TraceLog(WARNING, "OVR: Unable to count swap chain textures");
-
-    for (int i = 0; i < textureCount; ++i)
-    {
-        GLuint chainTexId;
-        ovr_GetTextureSwapChainBufferGL(session, buffer.textureChain, i, &chainTexId);
-        glBindTexture(GL_TEXTURE_2D, chainTexId);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-    }
-    
-    glBindTexture(GL_TEXTURE_2D, 0);
-    
-    /*
-    // Setup framebuffer object (using depth texture)
-    glGenFramebuffers(1, &buffer.fboId);
-    glGenTextures(1, &buffer.depthId);
-    glBindTexture(GL_TEXTURE_2D, buffer.depthId);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, buffer.width, buffer.height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
-    */
-    
-    // Setup framebuffer object (using depth renderbuffer)
-    glGenFramebuffers(1, &buffer.fboId);
-    glGenRenderbuffers(1, &buffer.depthId);
-    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, buffer.fboId);
-    glBindRenderbuffer(GL_RENDERBUFFER, buffer.depthId);
-    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, buffer.width, buffer.height);
-    glBindRenderbuffer(GL_RENDERBUFFER, 0);
-    glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, buffer.depthId);
-    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
-
-    return buffer;
-}
-
-// Unload texture required buffers
-static void UnloadOculusBuffer(ovrSession session, OculusBuffer buffer)
-{
-    if (buffer.textureChain)
-    {
-        ovr_DestroyTextureSwapChain(session, buffer.textureChain);
-        buffer.textureChain = NULL;
-    }
-
-    if (buffer.depthId != 0) glDeleteTextures(1, &buffer.depthId);
-    if (buffer.fboId != 0) glDeleteFramebuffers(1, &buffer.fboId);
-}
-
-// Set current Oculus buffer
-static void SetOculusBuffer(ovrSession session, OculusBuffer buffer)
-{
-    GLuint currentTexId;
-    int currentIndex;
-    
-    ovr_GetTextureSwapChainCurrentIndex(session, buffer.textureChain, &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);
-    
-    // Required if OculusBuffer format is OVR_FORMAT_R8G8B8A8_UNORM_SRGB
-    glEnable(GL_FRAMEBUFFER_SRGB);
-}
-
-// Unset Oculus buffer
-static void UnsetOculusBuffer(OculusBuffer buffer)
-{
-    glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
-    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
-}
-
-// Load Oculus mirror buffers
-static OculusMirror LoadOculusMirror(ovrSession session, int width, int height)
-{
-    OculusMirror mirror;
-    mirror.width = width;
-    mirror.height = height;
-    
-    ovrMirrorTextureDesc mirrorDesc;
-    memset(&mirrorDesc, 0, sizeof(mirrorDesc));
-    mirrorDesc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
-    mirrorDesc.Width = mirror.width;
-    mirrorDesc.Height = mirror.height;
-    
-    if (!OVR_SUCCESS(ovr_CreateMirrorTextureGL(session, &mirrorDesc, &mirror.texture))) TraceLog(WARNING, "Could not create mirror texture");
-
-    glGenFramebuffers(1, &mirror.fboId);
-
-    return mirror;
-}
-
-// Unload Oculus mirror buffers
-static void UnloadOculusMirror(ovrSession session, OculusMirror mirror)
-{
-    if (mirror.fboId != 0) glDeleteFramebuffers(1, &mirror.fboId);
-    if (mirror.texture) ovr_DestroyMirrorTexture(session, mirror.texture);
-}
-
-static void BlitOculusMirror(ovrSession session, OculusMirror mirror)
-{
-    GLuint mirrorTextureId;
-    
-    ovr_GetMirrorTextureBufferGL(session, mirror.texture, &mirrorTextureId);
-    
-    glBindFramebuffer(GL_READ_FRAMEBUFFER, mirror.fboId);
-    glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mirrorTextureId, 0);
-    glBlitFramebuffer(0, 0, mirror.width, mirror.height, 0, mirror.height, mirror.width, 0, GL_COLOR_BUFFER_BIT, GL_NEAREST);
-    glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
-}
-
-// Requires: session, hmdDesc
-static OculusLayer InitOculusLayer(ovrSession session)
-{
-    OculusLayer layer = { 0 };
-    
-    layer.viewScaleDesc.HmdSpaceToWorldScaleInMeters = 1.0f;
-
-    memset(&layer.eyeLayer, 0, sizeof(ovrLayerEyeFov));
-    layer.eyeLayer.Header.Type = ovrLayerType_EyeFov;
-    layer.eyeLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft;
-
-    ovrEyeRenderDesc eyeRenderDescs[2];
-    
-    for (int eye = 0; eye < 2; eye++)
-    {
-        eyeRenderDescs[eye] = ovr_GetRenderDesc(session, eye, hmdDesc.DefaultEyeFov[eye]);
-        ovrMatrix4f ovrPerspectiveProjection = ovrMatrix4f_Projection(eyeRenderDescs[eye].Fov, 0.01f, 10000.0f, ovrProjection_None); //ovrProjection_ClipRangeOpenGL);
-        layer.eyeProjections[eye] = FromOvrMatrix(ovrPerspectiveProjection);      // NOTE: struct ovrMatrix4f { float M[4][4] } --> struct Matrix
-
-        layer.viewScaleDesc.HmdToEyeOffset[eye] = eyeRenderDescs[eye].HmdToEyeOffset;
-        layer.eyeLayer.Fov[eye] = eyeRenderDescs[eye].Fov;
-        
-        ovrSizei eyeSize = ovr_GetFovTextureSize(session, eye, layer.eyeLayer.Fov[eye], 1.0f);
-        layer.eyeLayer.Viewport[eye].Size = eyeSize;
-        layer.eyeLayer.Viewport[eye].Pos.x = layer.width;
-        layer.eyeLayer.Viewport[eye].Pos.y = 0;
-
-        layer.height = eyeSize.h;     //std::max(renderTargetSize.y, (uint32_t)eyeSize.h);
-        layer.width += eyeSize.w;
-    }
-    
-    return layer;
-}
-#endif
+#endif      // PLATFORM_RPI
 
 // Plays raylib logo appearing animation
 static void LogoAnimation(void)

+ 196 - 0
src/external/OculusSDK/LibOVR/Include/Extras/OVR_CAPI_Util.h

@@ -0,0 +1,196 @@
+/********************************************************************************//**
+\file      OVR_CAPI_Util.h
+\brief     This header provides LibOVR utility function declarations
+\copyright Copyright 2015-2016 Oculus VR, LLC All Rights reserved.
+*************************************************************************************/
+
+#ifndef OVR_CAPI_Util_h
+#define OVR_CAPI_Util_h
+
+
+#include "../OVR_CAPI.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/// Enumerates modifications to the projection matrix based on the application's needs.
+///
+/// \see ovrMatrix4f_Projection
+///
+typedef enum ovrProjectionModifier_
+{
+    /// Use for generating a default projection matrix that is:
+    /// * Right-handed.
+    /// * Near depth values stored in the depth buffer are smaller than far depth values.
+    /// * Both near and far are explicitly defined.
+    /// * With a clipping range that is (0 to w).
+    ovrProjection_None = 0x00,
+
+    /// Enable if using left-handed transformations in your application.
+    ovrProjection_LeftHanded = 0x01,
+
+    /// After the projection transform is applied, far values stored in the depth buffer will be less than closer depth values.
+    /// NOTE: Enable only if the application is using a floating-point depth buffer for proper precision.
+    ovrProjection_FarLessThanNear = 0x02,
+
+    /// When this flag is used, the zfar value pushed into ovrMatrix4f_Projection() will be ignored
+    /// NOTE: Enable only if ovrProjection_FarLessThanNear is also enabled where the far clipping plane will be pushed to infinity.
+    ovrProjection_FarClipAtInfinity = 0x04,
+
+    /// Enable if the application is rendering with OpenGL and expects a projection matrix with a clipping range of (-w to w).
+    /// Ignore this flag if your application already handles the conversion from D3D range (0 to w) to OpenGL.
+    ovrProjection_ClipRangeOpenGL = 0x08,
+} ovrProjectionModifier;
+
+
+/// Return values for ovr_Detect.
+///
+/// \see ovr_Detect
+///
+typedef struct OVR_ALIGNAS(8) ovrDetectResult_
+{
+    /// Is ovrFalse when the Oculus Service is not running.
+    ///   This means that the Oculus Service is either uninstalled or stopped.
+    ///   IsOculusHMDConnected will be ovrFalse in this case.
+    /// Is ovrTrue when the Oculus Service is running.
+    ///   This means that the Oculus Service is installed and running.
+    ///   IsOculusHMDConnected will reflect the state of the HMD.
+    ovrBool IsOculusServiceRunning;
+
+    /// Is ovrFalse when an Oculus HMD is not detected.
+    ///   If the Oculus Service is not running, this will be ovrFalse.
+    /// Is ovrTrue when an Oculus HMD is detected.
+    ///   This implies that the Oculus Service is also installed and running.
+    ovrBool IsOculusHMDConnected;
+
+    OVR_UNUSED_STRUCT_PAD(pad0, 6) ///< \internal struct padding
+
+} ovrDetectResult;
+
+OVR_STATIC_ASSERT(sizeof(ovrDetectResult) == 8, "ovrDetectResult size mismatch");
+
+
+/// Detects Oculus Runtime and Device Status
+///
+/// Checks for Oculus Runtime and Oculus HMD device status without loading the LibOVRRT
+/// shared library.  This may be called before ovr_Initialize() to help decide whether or
+/// not to initialize LibOVR.
+///
+/// \param[in] timeoutMilliseconds Specifies a timeout to wait for HMD to be attached or 0 to poll.
+///
+/// \return Returns an ovrDetectResult object indicating the result of detection.
+///
+/// \see ovrDetectResult
+///
+OVR_PUBLIC_FUNCTION(ovrDetectResult) ovr_Detect(int timeoutMilliseconds);
+
+// On the Windows platform,
+#ifdef _WIN32
+    /// This is the Windows Named Event name that is used to check for HMD connected state.
+    #define OVR_HMD_CONNECTED_EVENT_NAME L"OculusHMDConnected"
+#endif // _WIN32
+
+
+/// Used to generate projection from ovrEyeDesc::Fov.
+///
+/// \param[in] fov Specifies the ovrFovPort to use.
+/// \param[in] znear Distance to near Z limit.
+/// \param[in] zfar Distance to far Z limit.
+/// \param[in] projectionModFlags A combination of the ovrProjectionModifier flags.
+///
+/// \return Returns the calculated projection matrix.
+/// 
+/// \see ovrProjectionModifier
+///
+OVR_PUBLIC_FUNCTION(ovrMatrix4f) ovrMatrix4f_Projection(ovrFovPort fov, float znear, float zfar, unsigned int projectionModFlags);
+
+
+/// Extracts the required data from the result of ovrMatrix4f_Projection.
+///
+/// \param[in] projection Specifies the project matrix from which to extract ovrTimewarpProjectionDesc.
+/// \param[in] projectionModFlags A combination of the ovrProjectionModifier flags.
+/// \return Returns the extracted ovrTimewarpProjectionDesc.
+/// \see ovrTimewarpProjectionDesc
+///
+OVR_PUBLIC_FUNCTION(ovrTimewarpProjectionDesc) ovrTimewarpProjectionDesc_FromProjection(ovrMatrix4f projection, unsigned int projectionModFlags);
+
+
+/// Generates an orthographic sub-projection.
+///
+/// Used for 2D rendering, Y is down.
+///
+/// \param[in] projection The perspective matrix that the orthographic matrix is derived from.
+/// \param[in] orthoScale Equal to 1.0f / pixelsPerTanAngleAtCenter.
+/// \param[in] orthoDistance Equal to the distance from the camera in meters, such as 0.8m.
+/// \param[in] HmdToEyeOffsetX Specifies the offset of the eye from the center.
+///
+/// \return Returns the calculated projection matrix.
+///
+OVR_PUBLIC_FUNCTION(ovrMatrix4f) ovrMatrix4f_OrthoSubProjection(ovrMatrix4f projection, ovrVector2f orthoScale,
+                                                                float orthoDistance, float HmdToEyeOffsetX);
+
+
+
+/// Computes offset eye poses based on headPose returned by ovrTrackingState.
+///
+/// \param[in] headPose Indicates the HMD position and orientation to use for the calculation.
+/// \param[in] hmdToEyeOffset Can be ovrEyeRenderDesc.HmdToEyeOffset returned from
+///            ovr_GetRenderDesc. For monoscopic rendering, use a vector that is the average 
+///            of the two vectors for both eyes.
+/// \param[out] outEyePoses If outEyePoses are used for rendering, they should be passed to 
+///             ovr_SubmitFrame in ovrLayerEyeFov::RenderPose or ovrLayerEyeFovDepth::RenderPose.
+///
+OVR_PUBLIC_FUNCTION(void) ovr_CalcEyePoses(ovrPosef headPose,
+                                           const ovrVector3f hmdToEyeOffset[2],
+                                           ovrPosef outEyePoses[2]);
+
+
+/// Returns the predicted head pose in outHmdTrackingState and offset eye poses in outEyePoses.
+///
+/// This is a thread-safe function where caller should increment frameIndex with every frame
+/// and pass that index where applicable to functions called on the rendering thread.
+/// Assuming outEyePoses are used for rendering, it should be passed as a part of ovrLayerEyeFov.
+/// The caller does not need to worry about applying HmdToEyeOffset to the returned outEyePoses variables.
+///
+/// \param[in]  hmd Specifies an ovrSession previously returned by ovr_Create.
+/// \param[in]  frameIndex Specifies the targeted frame index, or 0 to refer to one frame after 
+///             the last time ovr_SubmitFrame was called.
+/// \param[in]  latencyMarker Specifies that this call is the point in time where
+///             the "App-to-Mid-Photon" latency timer starts from. If a given ovrLayer
+///             provides "SensorSampleTimestamp", that will override the value stored here.
+/// \param[in]  hmdToEyeOffset Can be ovrEyeRenderDesc.HmdToEyeOffset returned from
+///             ovr_GetRenderDesc. For monoscopic rendering, use a vector that is the average
+///             of the two vectors for both eyes.
+/// \param[out] outEyePoses The predicted eye poses.
+/// \param[out] outSensorSampleTime The time when this function was called. May be NULL, in which case it is ignored.
+///
+OVR_PUBLIC_FUNCTION(void) ovr_GetEyePoses(ovrSession session, long long frameIndex, ovrBool latencyMarker,
+                                             const ovrVector3f hmdToEyeOffset[2],
+                                             ovrPosef outEyePoses[2],
+                                             double* outSensorSampleTime);
+
+
+
+/// Tracking poses provided by the SDK come in a right-handed coordinate system. If an application
+/// is passing in ovrProjection_LeftHanded into ovrMatrix4f_Projection, then it should also use
+/// this function to flip the HMD tracking poses to be left-handed.
+///
+/// While this utility function is intended to convert a left-handed ovrPosef into a right-handed
+/// coordinate system, it will also work for converting right-handed to left-handed since the
+/// flip operation is the same for both cases.
+/// 
+/// \param[in]  inPose that is right-handed
+/// \param[out] outPose that is requested to be left-handed (can be the same pointer to inPose)
+///
+OVR_PUBLIC_FUNCTION(void) ovrPosef_FlipHandedness(const ovrPosef* inPose, ovrPosef* outPose);
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif // Header include guard

+ 3804 - 0
src/external/OculusSDK/LibOVR/Include/Extras/OVR_Math.h

@@ -0,0 +1,3804 @@
+/********************************************************************************//**
+\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);
+            }
+        }
+    }
+
+    // Decompose a quat into quat = swing * twist, where twist is a rotation about axis,
+    // and swing is a rotation perpendicular to axis.
+    Quat GetSwingTwist(const Vector3<T>& axis, Quat* twist) const
+    {
+        OVR_MATH_ASSERT(twist);
+        OVR_MATH_ASSERT(axis.IsNormalized());
+
+        // Create a normalized quaternion from projection of (x,y,z) onto axis
+        T d = axis.Dot(Vector3<T>(x, y, z));
+        *twist = Quat(axis.x*d, axis.y*d, axis.z*d, w);
+        T len = twist->Length();
+        if (len == 0)
+            twist->w = T(1);    // identity
+        else
+            twist /= len;       // normalize
+
+        return *this * twist.Inverted();
+    }
+
+    // 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).Normalized();    // normalize so errors don't accumulate
+    }
+
+    // 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

+ 70 - 0
src/external/OculusSDK/LibOVR/Include/Extras/OVR_StereoProjection.h

@@ -0,0 +1,70 @@
+/************************************************************************************
+
+Filename    :   OVR_StereoProjection.h
+Content     :   Stereo projection functions
+Created     :   November 30, 2013
+Authors     :   Tom Fosyth
+
+Copyright   :   Copyright 2014-2016 Oculus VR, LLC All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.3 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.3 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#ifndef OVR_StereoProjection_h
+#define OVR_StereoProjection_h
+
+
+#include "Extras/OVR_Math.h"
+
+
+namespace OVR {
+
+
+//-----------------------------------------------------------------------------------
+// ***** Stereo Enumerations
+
+// StereoEye specifies which eye we are rendering for; it is used to
+// retrieve StereoEyeParams.
+enum StereoEye
+{
+    StereoEye_Left,
+    StereoEye_Right,
+    StereoEye_Center
+};
+
+
+
+//-----------------------------------------------------------------------------------
+// ***** Propjection functions
+
+Matrix4f            CreateProjection ( bool rightHanded, bool isOpenGL, FovPort fov, StereoEye eye,
+                                       float zNear = 0.01f, float zFar = 10000.0f,
+                                       bool flipZ = false, bool farAtInfinity = false);
+
+Matrix4f            CreateOrthoSubProjection ( bool rightHanded, StereoEye eyeType,
+                                               float tanHalfFovX, float tanHalfFovY,
+                                               float unitsX, float unitsY, float distanceFromCamera,
+                                               float interpupillaryDistance, Matrix4f const &projection,
+                                               float zNear = 0.0f, float zFar = 0.0f,
+                                               bool flipZ = false, bool farAtInfinity = false);
+
+ScaleAndOffset2D    CreateNDCScaleAndOffsetFromFov ( FovPort fov );
+
+
+} //namespace OVR
+
+#endif // OVR_StereoProjection_h

+ 2128 - 0
src/external/OculusSDK/LibOVR/Include/OVR_CAPI.h

@@ -0,0 +1,2128 @@
+/********************************************************************************//**
+\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 ovr_GetTrackerDesc
+///
+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,
+
+    // Added in 1.5 compressed formats can be used for static layers
+    OVR_FORMAT_BC1_UNORM,
+    OVR_FORMAT_BC1_UNORM_SRGB,
+    OVR_FORMAT_BC2_UNORM,
+    OVR_FORMAT_BC2_UNORM_SRGB,
+    OVR_FORMAT_BC3_UNORM,
+    OVR_FORMAT_BC3_UNORM_SRGB,
+    OVR_FORMAT_BC6H_UF16,
+    OVR_FORMAT_BC6H_SF16,
+    OVR_FORMAT_BC7_UNORM,
+    OVR_FORMAT_BC7_UNORM_SRGB,
+
+    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_RThumbRest     = 0x00000008,
+    ovrTouch_RIndexTrigger  = 0x00000010,
+
+    // Bit mask of all the button touches on the right controller
+    ovrTouch_RButtonMask    = ovrTouch_A | ovrTouch_B | ovrTouch_RThumb | ovrTouch_RThumbRest | ovrTouch_RIndexTrigger,
+
+    ovrTouch_X              = ovrButton_X,
+    ovrTouch_Y              = ovrButton_Y,
+    ovrTouch_LThumb         = ovrButton_LThumb,
+    ovrTouch_LThumbRest     = 0x00000800,
+    ovrTouch_LIndexTrigger  = 0x00001000,
+
+    // Bit mask of all the button touches on the left controller
+    ovrTouch_LButtonMask    = ovrTouch_X | ovrTouch_Y | ovrTouch_LThumb | ovrTouch_LThumbRest | 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
+
+/// 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);
+
+
+/// Identify client application info.
+///
+/// The string is one or more newline-delimited lines of optional info
+/// indicating engine name, engine version, engine plugin name, engine plugin
+/// version, engine editor. The order of the lines is not relevant. Individual
+/// lines are optional. A newline is not necessary at the end of the last line.
+/// Call after ovr_Initialize and before the first call to ovr_Create.
+/// Each value is limited to 20 characters. Key names such as 'EngineName:'
+/// 'EngineVersion:' do not count towards this limit.
+///
+/// \param[in] identity Specifies one or more newline-delimited lines of optional info:
+///             EngineName: %s\n
+///             EngineVersion: %s\n
+///             EnginePluginName: %s\n
+///             EnginePluginVersion: %s\n
+///             EngineEditor: <boolean> ('true' or 'false')\n
+///
+/// <b>Example code</b>
+///     \code{.cpp}
+///     ovr_IdentifyClient("EngineName: Unity\n"
+///                        "EngineVersion: 5.3.3\n"
+///                        "EnginePluginName: OVRPlugin\n"
+///                        "EnginePluginVersion: 1.2.0\n"
+///                        "EngineEditor: true");
+///     \endcode
+///
+OVR_PUBLIC_FUNCTION(ovrResult) ovr_IdentifyClient(const char* identity);
+
+
+//-------------------------------------------------------------------------------------
+/// @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 session 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 ovrSession 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 session.
+///
+/// \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 "SensorSampleTime", 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(session, 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(session, 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(session, 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(session, 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 session 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

+ 80 - 0
src/external/OculusSDK/LibOVR/Include/OVR_CAPI_Audio.h

@@ -0,0 +1,80 @@
+/********************************************************************************//**
+\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
+// Prevents <Windows.h> from defining min() and max() macro symbols.
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
+#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

+ 155 - 0
src/external/OculusSDK/LibOVR/Include/OVR_CAPI_D3D.h

@@ -0,0 +1,155 @@
+/********************************************************************************//**
+\file      OVR_CAPI_D3D.h
+\brief     D3D specific structures used by the CAPI interface.
+\copyright Copyright 2014-2016 Oculus VR, LLC All Rights reserved.
+************************************************************************************/
+
+#ifndef OVR_CAPI_D3D_h
+#define OVR_CAPI_D3D_h
+
+#include "OVR_CAPI.h"
+#include "OVR_Version.h"
+
+
+#if defined (_WIN32)
+#include <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 session 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 session 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

+ 99 - 0
src/external/OculusSDK/LibOVR/Include/OVR_CAPI_GL.h

@@ -0,0 +1,99 @@
+/********************************************************************************//**
+\file      OVR_CAPI_GL.h
+\brief     OpenGL-specific structures used by the CAPI interface.
+\copyright Copyright 2015 Oculus VR, LLC. All Rights reserved.
+************************************************************************************/
+
+#ifndef OVR_CAPI_GL_h
+#define OVR_CAPI_GL_h
+
+#include "OVR_CAPI.h"
+
+/// Creates a TextureSwapChain suitable for use with OpenGL.
+///
+/// \param[in]  session Specifies an ovrSession previously returned by ovr_Create.
+/// \param[in]  desc Specifies the requested texture properties. See notes for more info about texture format.
+/// \param[out] out_TextureSwapChain Returns the created ovrTextureSwapChain, which will be valid upon
+///             a successful return value, else it will be NULL. This texture swap chain must be eventually
+///             destroyed via ovr_DestroyTextureSwapChain before destroying the session 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 session 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

+ 53 - 0
src/external/OculusSDK/LibOVR/Include/OVR_CAPI_Keys.h

@@ -0,0 +1,53 @@
+/********************************************************************************//**
+\file      OVR_CAPI.h
+\brief     Keys for CAPI proprty function calls
+\copyright Copyright 2015 Oculus VR, LLC All Rights reserved.
+************************************************************************************/
+
+#ifndef OVR_CAPI_Keys_h
+#define OVR_CAPI_Keys_h
+
+#include "OVR_Version.h"
+
+
+
+#define OVR_KEY_USER                        "User"                // string
+
+#define OVR_KEY_NAME                        "Name"                // string
+
+#define OVR_KEY_GENDER                      "Gender"              // string "Male", "Female", or "Unknown"
+#define OVR_DEFAULT_GENDER                  "Unknown"
+
+#define OVR_KEY_PLAYER_HEIGHT               "PlayerHeight"        // float meters
+#define OVR_DEFAULT_PLAYER_HEIGHT           1.778f
+
+#define OVR_KEY_EYE_HEIGHT                  "EyeHeight"           // float meters
+#define OVR_DEFAULT_EYE_HEIGHT              1.675f
+
+#define OVR_KEY_NECK_TO_EYE_DISTANCE        "NeckEyeDistance"     // float[2] meters
+#define OVR_DEFAULT_NECK_TO_EYE_HORIZONTAL  0.0805f
+#define OVR_DEFAULT_NECK_TO_EYE_VERTICAL    0.075f
+
+
+#define OVR_KEY_EYE_TO_NOSE_DISTANCE        "EyeToNoseDist"       // float[2] meters
+
+
+
+
+
+#define OVR_PERF_HUD_MODE                       "PerfHudMode"                       // int, allowed values are defined in enum ovrPerfHudMode
+
+#define OVR_LAYER_HUD_MODE                      "LayerHudMode"                      // int, allowed values are defined in enum ovrLayerHudMode
+#define OVR_LAYER_HUD_CURRENT_LAYER             "LayerHudCurrentLayer"              // int, The layer to show 
+#define OVR_LAYER_HUD_SHOW_ALL_LAYERS           "LayerHudShowAll"                   // bool, Hide other layers when the hud is enabled
+
+#define OVR_DEBUG_HUD_STEREO_MODE               "DebugHudStereoMode"                // int, allowed values are defined in enum ovrDebugHudStereoMode
+#define OVR_DEBUG_HUD_STEREO_GUIDE_INFO_ENABLE  "DebugHudStereoGuideInfoEnable"     // bool
+#define OVR_DEBUG_HUD_STEREO_GUIDE_SIZE         "DebugHudStereoGuideSize2f"         // float[2]
+#define OVR_DEBUG_HUD_STEREO_GUIDE_POSITION     "DebugHudStereoGuidePosition3f"     // float[3]
+#define OVR_DEBUG_HUD_STEREO_GUIDE_YAWPITCHROLL "DebugHudStereoGuideYawPitchRoll3f" // float[3]
+#define OVR_DEBUG_HUD_STEREO_GUIDE_COLOR        "DebugHudStereoGuideColor4f"        // float[4]
+
+
+
+#endif // OVR_CAPI_Keys_h

+ 147 - 0
src/external/OculusSDK/LibOVR/Include/OVR_ErrorCode.h

@@ -0,0 +1,147 @@
+/********************************************************************************//**
+\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,
+} ovrSuccessType;
+#endif
+
+// Public success types
+// Success is a value greater or equal to 0, while all error types are negative values.
+typedef enum ovrSuccessTypes_
+{
+    /// 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,
+
+} ovrSuccessTypes;
+
+// Public error types
+typedef enum ovrErrorType_
+{
+    /* General errors */
+    ovrError_MemoryAllocationFailure    = -1000,   ///< Failure to allocate memory.
+    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_AudioDeviceNotFound        = -2001,   ///< Failure to find the specified audio device.
+    ovrError_AudioComError              = -2002,   ///< Generic COM 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
+
+    /* 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.
+
+
+} 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 */

+ 60 - 0
src/external/OculusSDK/LibOVR/Include/OVR_Version.h

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

BIN
src/external/OculusSDK/LibOVR/LibOVRRT32_1.dll


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 9
src/external/glad.c


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 1
src/external/glad.h


+ 26 - 18
src/external/jar_mod.h

@@ -64,7 +64,7 @@
 // - "Load" a MOD from file, context must already be initialized.
 //   Return size of file in bytes.
 // -------------------------------------------
-// void jar_mod_fillbuffer( jar_mod_context_t * modctx, unsigned short * outbuffer, unsigned long nbsample, jar_mod_tracker_buffer_state * trkbuf )
+// void jar_mod_fillbuffer( jar_mod_context_t * modctx, short * outbuffer, unsigned long nbsample, jar_mod_tracker_buffer_state * trkbuf )
 //
 // - Generate and return the next samples chunk to outbuffer.
 //   nbsample specify the number of stereo 16bits samples you want.
@@ -1063,7 +1063,6 @@ bool jar_mod_init(jar_mod_context_t * modctx)
         modctx->stereo_separation = 1;
         modctx->bits = 16;
         modctx->filter = 1;
-        modctx->loopcount = 0;
 
         for(i=0; i < PERIOD_TABLE_LENGTH - 1; i++)
         {
@@ -1472,7 +1471,7 @@ void jar_mod_fillbuffer( jar_mod_context_t * modctx, short * outbuffer, unsigned
 }
 
 //resets internals for mod context
-static void jar_mod_reset( jar_mod_context_t * modctx)
+static bool jar_mod_reset( jar_mod_context_t * modctx)
 {
     if(modctx)
     {
@@ -1488,7 +1487,6 @@ static void jar_mod_reset( jar_mod_context_t * modctx)
         modctx->patterntickse = 0;
         modctx->patternticksaim = 0;
         modctx->sampleticksconst = 0;
-        modctx->loopcount = 0;
         modctx->samplenb = 0;
         memclear(modctx->channels, 0, sizeof(modctx->channels));
         modctx->number_of_channels = 0;
@@ -1496,8 +1494,9 @@ static void jar_mod_reset( jar_mod_context_t * modctx)
         modctx->last_r_sample = 0;
         modctx->last_l_sample = 0;
         
-        jar_mod_init(modctx);
+        return jar_mod_init(modctx);
     }
+    return 0;
 }
 
 void jar_mod_unload( jar_mod_context_t * modctx)
@@ -1508,6 +1507,8 @@ void jar_mod_unload( jar_mod_context_t * modctx)
         {
             free(modctx->modfile);
             modctx->modfile = 0;
+            modctx->modfilesize = 0;
+            modctx->loopcount = 0;
         }
         jar_mod_reset(modctx);
     }
@@ -1556,27 +1557,34 @@ mulong jar_mod_current_samples(jar_mod_context_t * modctx)
 // Works, however it is very slow, this data should be cached to ensure it is run only once per file
 mulong jar_mod_max_samples(jar_mod_context_t * ctx)
 {
-    jar_mod_context_t tmpctx;
-    jar_mod_init(&tmpctx);
-    if(!jar_mod_load(&tmpctx, (void*)ctx->modfile, ctx->modfilesize)) return 0;
+    mint buff[2];
+    mulong len;
+    mulong lastcount = ctx->loopcount;
     
-    muint buff[2];
-    mulong lastcount = tmpctx.loopcount;
+    while(ctx->loopcount <= lastcount)
+        jar_mod_fillbuffer(ctx, buff, 1, 0);
     
-    while(1){
-        jar_mod_fillbuffer( &tmpctx, buff, 1, 0 );
-        if(tmpctx.loopcount > lastcount) break;
-    }
-    return tmpctx.samplenb;
+    len = ctx->samplenb;
+    jar_mod_seek_start(ctx);
+    
+    return len;
 }
 
 // move seek_val to sample index, 0 -> jar_mod_max_samples is the range
 void jar_mod_seek_start(jar_mod_context_t * ctx)
 {
-    if(ctx)
+    if(ctx && ctx->modfile)
     {
-        jar_mod_reset(ctx);
-        jar_mod_load(ctx, ctx->modfile, ctx->modfilesize);
+        muchar* ftmp = ctx->modfile;
+        mulong stmp = ctx->modfilesize;
+        muint lcnt = ctx->loopcount;
+        
+        if(jar_mod_reset(ctx)){
+            jar_mod_load(ctx, ftmp, stmp);
+            ctx->modfile = ftmp;
+            ctx->modfilesize = stmp;
+            ctx->loopcount = lcnt;
+        }
     }
 }
 

BIN
src/external/pthread/pthreadGC2.dll


+ 17 - 17
src/gestures.c

@@ -111,6 +111,19 @@ static double GetCurrentTime(void);
 // Module Functions Definition
 //----------------------------------------------------------------------------------
 
+// Enable only desired getures to be detected
+void SetGesturesEnabled(unsigned int gestureFlags)
+{
+    enabledGestures = gestureFlags;
+}
+
+// Check if a gesture have been detected
+bool IsGestureDetected(int gesture)
+{
+    if ((enabledGestures & currentGesture) == gesture) return true;
+    else return false;
+}
+
 // Process gesture event and translate it into gestures
 void ProcessGestureEvent(GestureEvent event)
 {
@@ -291,20 +304,6 @@ void UpdateGestures(void)
     }
 }
 
-// Check if a gesture have been detected
-bool IsGestureDetected(int gesture)
-{
-    if ((enabledGestures & currentGesture) == gesture) return true;
-    else return false;
-}
-
-// Check gesture type
-int GetGestureDetected(void)
-{
-    // Get current gesture only if enabled
-    return (enabledGestures & currentGesture);
-}
-
 // Get number of touch points
 int GetTouchPointsCount(void)
 {
@@ -313,10 +312,11 @@ int GetTouchPointsCount(void)
     return pointCount;
 }
 
-// Enable only desired getures to be detected
-void SetGesturesEnabled(unsigned int gestureFlags)
+// Get latest detected gesture
+int GetGestureDetected(void)
 {
-    enabledGestures = gestureFlags;
+    // Get current gesture only if enabled
+    return (enabledGestures & currentGesture);
 }
 
 // Hold time measured in ms

+ 4 - 4
src/gestures.h

@@ -90,13 +90,13 @@ extern "C" {            // Prevents name mangling of functions
 //----------------------------------------------------------------------------------
 // Module Functions Declaration
 //----------------------------------------------------------------------------------
+void SetGesturesEnabled(unsigned int gestureFlags);     // Enable a set of gestures using flags
+bool IsGestureDetected(int gesture);                    // Check if a gesture have been detected
 void ProcessGestureEvent(GestureEvent event);           // Process gesture event and translate it into gestures
 void UpdateGestures(void);                              // Update gestures detected (must be called every frame)
-bool IsGestureDetected(int gesture);                    // Check if a gesture have been detected
-int GetGestureDetected(void);                           // Get latest detected gesture
-void SetGesturesEnabled(unsigned int gestureFlags);     // Enable a set of gestures using flags
-int GetTouchPointsCount(void);                          // Get touch points count
 
+int GetTouchPointsCount(void);                          // Get touch points count
+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

BIN
src/libraylib.bc


+ 39 - 43
src/models.c

@@ -40,7 +40,7 @@
 //----------------------------------------------------------------------------------
 // Defines and Macros
 //----------------------------------------------------------------------------------
-#define CUBIC_MAP_HALF_BLOCK_SIZE           0.5
+// ...
 
 //----------------------------------------------------------------------------------
 // Types and Structures Definition
@@ -50,7 +50,7 @@
 //----------------------------------------------------------------------------------
 // Global Variables Definition
 //----------------------------------------------------------------------------------
-extern unsigned int whiteTexture;
+// ...
 
 //----------------------------------------------------------------------------------
 // Module specific Functions Declaration
@@ -739,7 +739,7 @@ Model LoadCubicmap(Image cubicmap)
 {
     Model model = { 0 };
     
-    model.mesh = GenMeshCubicmap(cubicmap, (Vector3){ 1.0, 1.0, 1.5f });
+    model.mesh = GenMeshCubicmap(cubicmap, (Vector3){ 1.0f, 1.5f, 1.0f });
     
     rlglLoadMesh(&model.mesh, false);  // Upload vertex data to GPU (static model)
     
@@ -808,13 +808,6 @@ void UnloadMaterial(Material material)
     rlDeleteTextures(material.texSpecular.id);
 }
 
-// Link a texture to a model
-void SetModelTexture(Model *model, Texture2D texture)
-{
-    if (texture.id <= 0) model->material.texDiffuse.id = whiteTexture;  // Use default white texture
-    else model->material.texDiffuse = texture;
-}
-
 // Generate a mesh from heightmap
 static Mesh GenMeshHeightmap(Image heightmap, Vector3 size)
 {
@@ -1549,8 +1542,11 @@ BoundingBox CalculateBoundingBox(Mesh mesh)
 
 // Detect and resolve cubicmap collisions
 // NOTE: player position (or camera) is modified inside this function
+// TODO: This functions needs to be completely reviewed!
 Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *playerPosition, float radius)
 {
+    #define CUBIC_MAP_HALF_BLOCK_SIZE   0.5
+    
     Color *cubicmapPixels = GetImageData(cubicmap);
     
     // Detect the cell where the player is located
@@ -1562,15 +1558,15 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p
     locationCellX = floor(playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE);
     locationCellY = floor(playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE);
 
-    if (locationCellX >= 0 && locationCellY >= 0 && locationCellX < cubicmap.width && locationCellY < cubicmap.height)
+    if ((locationCellX >= 0) && (locationCellY >= 0) && (locationCellX < cubicmap.width) && (locationCellY < cubicmap.height))
     {
         // Multiple Axis --------------------------------------------------------------------------------------------
 
         // Axis x-, y-
-        if (locationCellX > 0 && locationCellY > 0)
+        if ((locationCellX > 0) && (locationCellY > 0))
         {
-            if ((cubicmapPixels[locationCellY * cubicmap.width + (locationCellX - 1)].r != 0) &&
-                (cubicmapPixels[(locationCellY - 1) * cubicmap.width + (locationCellX)].r != 0))
+            if ((cubicmapPixels[locationCellY*cubicmap.width + (locationCellX - 1)].r != 0) &&
+                (cubicmapPixels[(locationCellY - 1)*cubicmap.width + (locationCellX)].r != 0))
             {
                 if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius) &&
                     ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius))
@@ -1583,10 +1579,10 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p
         }
 
         // Axis x-, y+
-        if (locationCellX > 0 && locationCellY < cubicmap.height - 1)
+        if ((locationCellX > 0) && (locationCellY < cubicmap.height - 1))
         {
-            if ((cubicmapPixels[locationCellY * cubicmap.width + (locationCellX - 1)].r != 0) &&
-                (cubicmapPixels[(locationCellY + 1) * cubicmap.width + (locationCellX)].r != 0))
+            if ((cubicmapPixels[locationCellY*cubicmap.width + (locationCellX - 1)].r != 0) &&
+                (cubicmapPixels[(locationCellY + 1)*cubicmap.width + (locationCellX)].r != 0))
             {
                 if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius) &&
                     ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius))
@@ -1599,10 +1595,10 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p
         }
 
         // Axis x+, y-
-        if (locationCellX < cubicmap.width - 1 && locationCellY > 0)
+        if ((locationCellX < cubicmap.width - 1) && (locationCellY > 0))
         {
-            if ((cubicmapPixels[locationCellY * cubicmap.width + (locationCellX + 1)].r != 0) &&
-                (cubicmapPixels[(locationCellY - 1) * cubicmap.width + (locationCellX)].r != 0))
+            if ((cubicmapPixels[locationCellY*cubicmap.width + (locationCellX + 1)].r != 0) &&
+                (cubicmapPixels[(locationCellY - 1)*cubicmap.width + (locationCellX)].r != 0))
             {
                 if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius) &&
                     ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius))
@@ -1615,10 +1611,10 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p
         }
 
         // Axis x+, y+
-        if (locationCellX < cubicmap.width - 1 && locationCellY < cubicmap.height - 1)
+        if ((locationCellX < cubicmap.width - 1) && (locationCellY < cubicmap.height - 1))
         {
-            if ((cubicmapPixels[locationCellY * cubicmap.width + (locationCellX + 1)].r != 0) &&
-                (cubicmapPixels[(locationCellY + 1) * cubicmap.width + (locationCellX)].r != 0))
+            if ((cubicmapPixels[locationCellY*cubicmap.width + (locationCellX + 1)].r != 0) &&
+                (cubicmapPixels[(locationCellY + 1)*cubicmap.width + (locationCellX)].r != 0))
             {
                 if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius) &&
                     ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius))
@@ -1635,7 +1631,7 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p
         // Axis x-
         if (locationCellX > 0)
         {
-            if (cubicmapPixels[locationCellY * cubicmap.width + (locationCellX - 1)].r != 0)
+            if (cubicmapPixels[locationCellY*cubicmap.width + (locationCellX - 1)].r != 0)
             {
                 if ((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius)
                 {
@@ -1647,7 +1643,7 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p
         // Axis x+
         if (locationCellX < cubicmap.width - 1)
         {
-            if (cubicmapPixels[locationCellY * cubicmap.width + (locationCellX + 1)].r != 0)
+            if (cubicmapPixels[locationCellY*cubicmap.width + (locationCellX + 1)].r != 0)
             {
                 if ((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius)
                 {
@@ -1659,7 +1655,7 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p
         // Axis y-
         if (locationCellY > 0)
         {
-            if (cubicmapPixels[(locationCellY - 1) * cubicmap.width + (locationCellX)].r != 0)
+            if (cubicmapPixels[(locationCellY - 1)*cubicmap.width + (locationCellX)].r != 0)
             {
                 if ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius)
                 {
@@ -1671,7 +1667,7 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p
         // Axis y+
         if (locationCellY < cubicmap.height - 1)
         {
-            if (cubicmapPixels[(locationCellY + 1) * cubicmap.width + (locationCellX)].r != 0)
+            if (cubicmapPixels[(locationCellY + 1)*cubicmap.width + (locationCellX)].r != 0)
             {
                 if ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius)
                 {
@@ -1684,11 +1680,11 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p
         // Diagonals -------------------------------------------------------------------------------------------------------
 
         // Axis x-, y-
-        if (locationCellX > 0 && locationCellY > 0)
+        if ((locationCellX > 0) && (locationCellY > 0))
         {
-            if ((cubicmapPixels[locationCellY * cubicmap.width + (locationCellX - 1)].r == 0) &&
-                (cubicmapPixels[(locationCellY - 1) * cubicmap.width + (locationCellX)].r == 0) &&
-                (cubicmapPixels[(locationCellY - 1) * cubicmap.width + (locationCellX - 1)].r != 0))
+            if ((cubicmapPixels[locationCellY*cubicmap.width + (locationCellX - 1)].r == 0) &&
+                (cubicmapPixels[(locationCellY - 1)*cubicmap.width + (locationCellX)].r == 0) &&
+                (cubicmapPixels[(locationCellY - 1)*cubicmap.width + (locationCellX - 1)].r != 0))
             {
                 if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius) &&
                     ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius))
@@ -1707,11 +1703,11 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p
         }
 
         // Axis x-, y+
-        if (locationCellX > 0 && locationCellY < cubicmap.height - 1)
+        if ((locationCellX > 0) && (locationCellY < cubicmap.height - 1))
         {
-            if ((cubicmapPixels[locationCellY * cubicmap.width + (locationCellX - 1)].r == 0) &&
-                (cubicmapPixels[(locationCellY + 1) * cubicmap.width + (locationCellX)].r == 0) &&
-                (cubicmapPixels[(locationCellY + 1) * cubicmap.width + (locationCellX - 1)].r != 0))
+            if ((cubicmapPixels[locationCellY*cubicmap.width + (locationCellX - 1)].r == 0) &&
+                (cubicmapPixels[(locationCellY + 1)*cubicmap.width + (locationCellX)].r == 0) &&
+                (cubicmapPixels[(locationCellY + 1)*cubicmap.width + (locationCellX - 1)].r != 0))
             {
                 if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius) &&
                     ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius))
@@ -1730,11 +1726,11 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p
         }
 
         // Axis x+, y-
-        if (locationCellX < cubicmap.width - 1 && locationCellY > 0)
+        if ((locationCellX < cubicmap.width - 1) && (locationCellY > 0))
         {
-            if ((cubicmapPixels[locationCellY * cubicmap.width + (locationCellX + 1)].r == 0) &&
-                (cubicmapPixels[(locationCellY - 1) * cubicmap.width + (locationCellX)].r == 0) &&
-                (cubicmapPixels[(locationCellY - 1) * cubicmap.width + (locationCellX + 1)].r != 0))
+            if ((cubicmapPixels[locationCellY*cubicmap.width + (locationCellX + 1)].r == 0) &&
+                (cubicmapPixels[(locationCellY - 1)*cubicmap.width + (locationCellX)].r == 0) &&
+                (cubicmapPixels[(locationCellY - 1)*cubicmap.width + (locationCellX + 1)].r != 0))
             {
                 if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius) &&
                     ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius))
@@ -1753,11 +1749,11 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p
         }
 
         // Axis x+, y+
-        if (locationCellX < cubicmap.width - 1 && locationCellY < cubicmap.height - 1)
+        if ((locationCellX < cubicmap.width - 1) && (locationCellY < cubicmap.height - 1))
         {
-            if ((cubicmapPixels[locationCellY * cubicmap.width + (locationCellX + 1)].r == 0) &&
-                (cubicmapPixels[(locationCellY + 1) * cubicmap.width + (locationCellX)].r == 0) &&
-                (cubicmapPixels[(locationCellY + 1) * cubicmap.width + (locationCellX + 1)].r != 0))
+            if ((cubicmapPixels[locationCellY*cubicmap.width + (locationCellX + 1)].r == 0) &&
+                (cubicmapPixels[(locationCellY + 1)*cubicmap.width + (locationCellX)].r == 0) &&
+                (cubicmapPixels[(locationCellY + 1)*cubicmap.width + (locationCellX + 1)].r != 0))
             {
                 if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius) &&
                     ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius))

+ 0 - 594
src/physac.c

@@ -1,594 +0,0 @@
-/**********************************************************************************************
-*
-*   [physac] raylib physics module - Basic functions to apply physics to 2D objects
-*
-*   Copyright (c) 2016 Victor Fisac and Ramon Santamaria
-*
-*   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.
-*
-**********************************************************************************************/
-
-//#define PHYSAC_STANDALONE     // NOTE: To use the physics module as standalone lib, just uncomment this line
-
-#if defined(PHYSAC_STANDALONE)
-    #include "physac.h"
-#else
-    #include "raylib.h"
-#endif
-
-#include <stdlib.h>         // Required for: malloc(), free()
-#include <math.h>           // Required for: cos(), sin(), abs(), fminf()
-
-//----------------------------------------------------------------------------------
-// Defines and Macros
-//----------------------------------------------------------------------------------
-#define MAX_PHYSIC_OBJECTS      256             // Maximum available physic object slots in objects pool
-#define PHYSICS_STEPS           450             // Physics update steps number (divided calculations in steps per frame) to get more accurately collisions detections
-#define PHYSICS_ACCURACY        0.0001f         // Velocity subtract operations round filter (friction)
-#define PHYSICS_ERRORPERCENT    0.001f          // Collision resolve position fix
-
-//----------------------------------------------------------------------------------
-// Types and Structures Definition
-// NOTE: Below types are required for PHYSAC_STANDALONE usage
-//----------------------------------------------------------------------------------
-// ...
-
-//----------------------------------------------------------------------------------
-// Global Variables Definition
-//----------------------------------------------------------------------------------
-static PhysicObject physicObjects[MAX_PHYSIC_OBJECTS];              // Physic objects pool
-static int physicObjectsCount;                                      // Counts current enabled physic objects
-static Vector2 gravityForce;                                        // Gravity force
-
-//----------------------------------------------------------------------------------
-// Module specific Functions Declaration
-//----------------------------------------------------------------------------------
-static float Vector2DotProduct(Vector2 v1, Vector2 v2);             // Returns the dot product of two Vector2
-static float Vector2Length(Vector2 v);                              // Returns the length of a Vector2
-
-//----------------------------------------------------------------------------------
-// Module Functions Definition
-//----------------------------------------------------------------------------------
-
-// Initializes pointers array (just pointers, fixed size)
-void InitPhysics(Vector2 gravity)
-{
-    // Initialize physics variables
-    physicObjectsCount = 0;
-    gravityForce = gravity;
-}
-
-// Update physic objects, calculating physic behaviours and collisions detection
-void UpdatePhysics()
-{
-    // Reset all physic objects is grounded state
-    for (int i = 0; i < physicObjectsCount; i++) physicObjects[i]->rigidbody.isGrounded = false;
-    
-    for (int steps = 0; steps < PHYSICS_STEPS; steps++)
-    {
-        for (int i = 0; i < physicObjectsCount; i++)
-        {
-            if (physicObjects[i]->enabled)
-            {
-                // Update physic behaviour
-                if (physicObjects[i]->rigidbody.enabled)
-                {
-                    // Apply friction to acceleration in X axis
-                    if (physicObjects[i]->rigidbody.acceleration.x > PHYSICS_ACCURACY) physicObjects[i]->rigidbody.acceleration.x -= physicObjects[i]->rigidbody.friction/PHYSICS_STEPS;
-                    else if (physicObjects[i]->rigidbody.acceleration.x < PHYSICS_ACCURACY) physicObjects[i]->rigidbody.acceleration.x += physicObjects[i]->rigidbody.friction/PHYSICS_STEPS;
-                    else physicObjects[i]->rigidbody.acceleration.x = 0.0f;
-                    
-                    // Apply friction to acceleration in Y axis
-                    if (physicObjects[i]->rigidbody.acceleration.y > PHYSICS_ACCURACY) physicObjects[i]->rigidbody.acceleration.y -= physicObjects[i]->rigidbody.friction/PHYSICS_STEPS;
-                    else if (physicObjects[i]->rigidbody.acceleration.y < PHYSICS_ACCURACY) physicObjects[i]->rigidbody.acceleration.y += physicObjects[i]->rigidbody.friction/PHYSICS_STEPS;
-                    else physicObjects[i]->rigidbody.acceleration.y = 0.0f;
-                    
-                    // Apply friction to velocity in X axis
-                    if (physicObjects[i]->rigidbody.velocity.x > PHYSICS_ACCURACY) physicObjects[i]->rigidbody.velocity.x -= physicObjects[i]->rigidbody.friction/PHYSICS_STEPS;
-                    else if (physicObjects[i]->rigidbody.velocity.x < PHYSICS_ACCURACY) physicObjects[i]->rigidbody.velocity.x += physicObjects[i]->rigidbody.friction/PHYSICS_STEPS;
-                    else physicObjects[i]->rigidbody.velocity.x = 0.0f;
-                    
-                    // Apply friction to velocity in Y axis
-                    if (physicObjects[i]->rigidbody.velocity.y > PHYSICS_ACCURACY) physicObjects[i]->rigidbody.velocity.y -= physicObjects[i]->rigidbody.friction/PHYSICS_STEPS;
-                    else if (physicObjects[i]->rigidbody.velocity.y < PHYSICS_ACCURACY) physicObjects[i]->rigidbody.velocity.y += physicObjects[i]->rigidbody.friction/PHYSICS_STEPS;
-                    else physicObjects[i]->rigidbody.velocity.y = 0.0f;
-                    
-                    // Apply gravity to velocity
-                    if (physicObjects[i]->rigidbody.applyGravity)
-                    {
-                        physicObjects[i]->rigidbody.velocity.x += gravityForce.x/PHYSICS_STEPS;
-                        physicObjects[i]->rigidbody.velocity.y += gravityForce.y/PHYSICS_STEPS;
-                    }
-                    
-                    // Apply acceleration to velocity
-                    physicObjects[i]->rigidbody.velocity.x += physicObjects[i]->rigidbody.acceleration.x/PHYSICS_STEPS;
-                    physicObjects[i]->rigidbody.velocity.y += physicObjects[i]->rigidbody.acceleration.y/PHYSICS_STEPS;
-                    
-                    // Apply velocity to position
-                    physicObjects[i]->transform.position.x += physicObjects[i]->rigidbody.velocity.x/PHYSICS_STEPS;
-                    physicObjects[i]->transform.position.y -= physicObjects[i]->rigidbody.velocity.y/PHYSICS_STEPS;
-                }
-                
-                // Update collision detection
-                if (physicObjects[i]->collider.enabled)
-                {
-                    // Update collider bounds
-                    physicObjects[i]->collider.bounds = TransformToRectangle(physicObjects[i]->transform);
-                    
-                    // Check collision with other colliders
-                    for (int k = 0; k < physicObjectsCount; k++)
-                    {
-                        if (physicObjects[k]->collider.enabled && i != k)
-                        {
-                            // Resolve physic collision
-                            // NOTE: collision resolve is generic for all directions and conditions (no axis separated cases behaviours)
-                            // and it is separated in rigidbody attributes resolve (velocity changes by impulse) and position correction (position overlap)
-                            
-                            // 1. Calculate collision normal
-                            // -------------------------------------------------------------------------------------------------------------------------------------
-                            
-                            // Define collision contact normal, direction and penetration depth
-                            Vector2 contactNormal = { 0.0f, 0.0f };
-                            Vector2 direction = { 0.0f, 0.0f };
-                            float penetrationDepth = 0.0f;
-                            
-                            switch (physicObjects[i]->collider.type)
-                            {
-                                case COLLIDER_RECTANGLE:
-                                {
-                                    switch (physicObjects[k]->collider.type)
-                                    {
-                                        case COLLIDER_RECTANGLE:
-                                        {
-                                            // Check if colliders are overlapped
-                                            if (CheckCollisionRecs(physicObjects[i]->collider.bounds, physicObjects[k]->collider.bounds))
-                                            {
-                                                // Calculate direction vector from i to k
-                                                direction.x = (physicObjects[k]->transform.position.x + physicObjects[k]->transform.scale.x/2) - (physicObjects[i]->transform.position.x + physicObjects[i]->transform.scale.x/2);
-                                                direction.y = (physicObjects[k]->transform.position.y + physicObjects[k]->transform.scale.y/2) - (physicObjects[i]->transform.position.y + physicObjects[i]->transform.scale.y/2);
-                                                
-                                                // Define overlapping and penetration attributes
-                                                Vector2 overlap;
-
-                                                // Calculate overlap on X axis
-                                                overlap.x = (physicObjects[i]->transform.scale.x + physicObjects[k]->transform.scale.x)/2 - abs(direction.x);
-                                                
-                                                // SAT test on X axis
-                                                if (overlap.x > 0.0f)
-                                                {
-                                                    // Calculate overlap on Y axis
-                                                    overlap.y = (physicObjects[i]->transform.scale.y + physicObjects[k]->transform.scale.y)/2 - abs(direction.y);
-                                                    
-                                                    // SAT test on Y axis
-                                                    if (overlap.y > 0.0f)
-                                                    {
-                                                        // Find out which axis is axis of least penetration
-                                                        if (overlap.y > overlap.x)
-                                                        {
-                                                            // Point towards k knowing that direction points from i to k
-                                                            if (direction.x < 0.0f) contactNormal = (Vector2){ -1.0f, 0.0f };
-                                                            else contactNormal = (Vector2){ 1.0f, 0.0f };
-                                                            
-                                                            // Update penetration depth for position correction
-                                                            penetrationDepth = overlap.x;
-                                                        }
-                                                        else
-                                                        {
-                                                            // Point towards k knowing that direction points from i to k
-                                                            if (direction.y < 0.0f) contactNormal = (Vector2){ 0.0f, 1.0f };
-                                                            else contactNormal = (Vector2){ 0.0f, -1.0f };
-                                                            
-                                                            // Update penetration depth for position correction
-                                                            penetrationDepth = overlap.y;
-                                                        }
-                                                    }
-                                                }
-                                            }
-                                        } break;
-                                        case COLLIDER_CIRCLE:
-                                        {
-                                            if (CheckCollisionCircleRec(physicObjects[k]->transform.position, physicObjects[k]->collider.radius, physicObjects[i]->collider.bounds))
-                                            {
-                                                // Calculate direction vector between circles
-                                                direction.x = physicObjects[k]->transform.position.x - physicObjects[i]->transform.position.x + physicObjects[i]->transform.scale.x/2;
-                                                direction.y = physicObjects[k]->transform.position.y - physicObjects[i]->transform.position.y + physicObjects[i]->transform.scale.y/2;
-                                                
-                                                // Calculate closest point on rectangle to circle
-                                                Vector2 closestPoint = { 0.0f, 0.0f };
-                                                if (direction.x > 0.0f) closestPoint.x = physicObjects[i]->collider.bounds.x + physicObjects[i]->collider.bounds.width;
-                                                else closestPoint.x = physicObjects[i]->collider.bounds.x;
-                                                
-                                                if (direction.y > 0.0f) closestPoint.y = physicObjects[i]->collider.bounds.y + physicObjects[i]->collider.bounds.height;
-                                                else closestPoint.y = physicObjects[i]->collider.bounds.y;
-                                                
-                                                // Check if the closest point is inside the circle
-                                                if (CheckCollisionPointCircle(closestPoint, physicObjects[k]->transform.position, physicObjects[k]->collider.radius))
-                                                {
-                                                    // Recalculate direction based on closest point position
-                                                    direction.x = physicObjects[k]->transform.position.x - closestPoint.x;
-                                                    direction.y = physicObjects[k]->transform.position.y - closestPoint.y;
-                                                    float distance = Vector2Length(direction);
-                                                    
-                                                    // Calculate final contact normal
-                                                    contactNormal.x = direction.x/distance;
-                                                    contactNormal.y = -direction.y/distance;
-                                                    
-                                                    // Calculate penetration depth
-                                                    penetrationDepth = physicObjects[k]->collider.radius - distance;
-                                                }
-                                                else
-                                                {
-                                                    if (abs(direction.y) < abs(direction.x))
-                                                    {
-                                                        // Calculate final contact normal
-                                                        if (direction.y > 0.0f)
-                                                        {
-                                                            contactNormal = (Vector2){ 0.0f, -1.0f };
-                                                            penetrationDepth = fabs(physicObjects[i]->collider.bounds.y - physicObjects[k]->transform.position.y - physicObjects[k]->collider.radius);
-                                                        }
-                                                        else 
-                                                        {
-                                                            contactNormal = (Vector2){ 0.0f, 1.0f };
-                                                            penetrationDepth = fabs(physicObjects[i]->collider.bounds.y - physicObjects[k]->transform.position.y + physicObjects[k]->collider.radius);
-                                                        }
-                                                    }
-                                                    else
-                                                    {
-                                                        // Calculate final contact normal
-                                                        if (direction.x > 0.0f)
-                                                        {
-                                                            contactNormal = (Vector2){ 1.0f, 0.0f };
-                                                            penetrationDepth = fabs(physicObjects[k]->transform.position.x + physicObjects[k]->collider.radius - physicObjects[i]->collider.bounds.x);
-                                                        }
-                                                        else 
-                                                        {
-                                                            contactNormal = (Vector2){ -1.0f, 0.0f };
-                                                            penetrationDepth = fabs(physicObjects[i]->collider.bounds.x + physicObjects[i]->collider.bounds.width - physicObjects[k]->transform.position.x - physicObjects[k]->collider.radius);
-                                                        }
-                                                    }
-                                                }
-                                            }
-                                        } break;
-                                    }
-                                } break;
-                                case COLLIDER_CIRCLE:
-                                {
-                                    switch (physicObjects[k]->collider.type)
-                                    {
-                                        case COLLIDER_RECTANGLE:
-                                        {
-                                            if (CheckCollisionCircleRec(physicObjects[i]->transform.position, physicObjects[i]->collider.radius, physicObjects[k]->collider.bounds))
-                                            {
-                                                // Calculate direction vector between circles
-                                                direction.x = physicObjects[k]->transform.position.x + physicObjects[i]->transform.scale.x/2 - physicObjects[i]->transform.position.x;
-                                                direction.y = physicObjects[k]->transform.position.y + physicObjects[i]->transform.scale.y/2 - physicObjects[i]->transform.position.y;
-                                                
-                                                // Calculate closest point on rectangle to circle
-                                                Vector2 closestPoint = { 0.0f, 0.0f };
-                                                if (direction.x > 0.0f) closestPoint.x = physicObjects[k]->collider.bounds.x + physicObjects[k]->collider.bounds.width;
-                                                else closestPoint.x = physicObjects[k]->collider.bounds.x;
-                                                
-                                                if (direction.y > 0.0f) closestPoint.y = physicObjects[k]->collider.bounds.y + physicObjects[k]->collider.bounds.height;
-                                                else closestPoint.y = physicObjects[k]->collider.bounds.y;
-                                                
-                                                // Check if the closest point is inside the circle
-                                                if (CheckCollisionPointCircle(closestPoint, physicObjects[i]->transform.position, physicObjects[i]->collider.radius))
-                                                {
-                                                    // Recalculate direction based on closest point position
-                                                    direction.x = physicObjects[i]->transform.position.x - closestPoint.x;
-                                                    direction.y = physicObjects[i]->transform.position.y - closestPoint.y;
-                                                    float distance = Vector2Length(direction);
-                                                    
-                                                    // Calculate final contact normal
-                                                    contactNormal.x = direction.x/distance;
-                                                    contactNormal.y = -direction.y/distance;
-                                                    
-                                                    // Calculate penetration depth
-                                                    penetrationDepth = physicObjects[k]->collider.radius - distance;
-                                                }
-                                                else
-                                                {
-                                                    if (abs(direction.y) < abs(direction.x))
-                                                    {
-                                                        // Calculate final contact normal
-                                                        if (direction.y > 0.0f)
-                                                        {
-                                                            contactNormal = (Vector2){ 0.0f, -1.0f };
-                                                            penetrationDepth = fabs(physicObjects[k]->collider.bounds.y - physicObjects[i]->transform.position.y - physicObjects[i]->collider.radius);
-                                                        }
-                                                        else 
-                                                        {
-                                                            contactNormal = (Vector2){ 0.0f, 1.0f };
-                                                            penetrationDepth = fabs(physicObjects[k]->collider.bounds.y - physicObjects[i]->transform.position.y + physicObjects[i]->collider.radius);
-                                                        }
-                                                    }
-                                                    else
-                                                    {
-                                                        // Calculate final contact normal and penetration depth
-                                                        if (direction.x > 0.0f)
-                                                        {
-                                                            contactNormal = (Vector2){ 1.0f, 0.0f };
-                                                            penetrationDepth = fabs(physicObjects[i]->transform.position.x + physicObjects[i]->collider.radius - physicObjects[k]->collider.bounds.x);
-                                                        }
-                                                        else 
-                                                        {
-                                                            contactNormal = (Vector2){ -1.0f, 0.0f };
-                                                            penetrationDepth = fabs(physicObjects[k]->collider.bounds.x + physicObjects[k]->collider.bounds.width - physicObjects[i]->transform.position.x - physicObjects[i]->collider.radius);
-                                                        }
-                                                    }
-                                                }
-                                            }
-                                        } break;
-                                        case COLLIDER_CIRCLE:
-                                        {
-                                            // Check if colliders are overlapped
-                                            if (CheckCollisionCircles(physicObjects[i]->transform.position, physicObjects[i]->collider.radius, physicObjects[k]->transform.position, physicObjects[k]->collider.radius))
-                                            {
-                                                // Calculate direction vector between circles
-                                                direction.x = physicObjects[k]->transform.position.x - physicObjects[i]->transform.position.x;
-                                                direction.y = physicObjects[k]->transform.position.y - physicObjects[i]->transform.position.y;
-                                                
-                                                // Calculate distance between circles
-                                                float distance = Vector2Length(direction);
-                                                
-                                                // Check if circles are not completely overlapped
-                                                if (distance != 0.0f)
-                                                {                                                    
-                                                    // Calculate contact normal direction (Y axis needs to be flipped)
-                                                    contactNormal.x = direction.x/distance;
-                                                    contactNormal.y = -direction.y/distance;
-                                                }
-                                                else contactNormal = (Vector2){ 1.0f, 0.0f };   // Choose random (but consistent) values
-                                            }
-                                        } break;
-                                        default: break;
-                                    }
-                                } break;
-                                default: break;
-                            }
-                            
-                            // Update rigidbody grounded state
-                            if (physicObjects[i]->rigidbody.enabled)
-                            {
-                                if (contactNormal.y < 0.0f) physicObjects[i]->rigidbody.isGrounded = true;
-                            }
-                            
-                            // 2. Calculate collision impulse
-                            // -------------------------------------------------------------------------------------------------------------------------------------
-                            
-                            // Calculate relative velocity
-                            Vector2 relVelocity = { 0.0f, 0.0f };
-                            relVelocity.x = physicObjects[k]->rigidbody.velocity.x - physicObjects[i]->rigidbody.velocity.x;
-                            relVelocity.y = physicObjects[k]->rigidbody.velocity.y - physicObjects[i]->rigidbody.velocity.y;
-
-                            // Calculate relative velocity in terms of the normal direction
-                            float velAlongNormal = Vector2DotProduct(relVelocity, contactNormal);
-                        
-                            // Dot not resolve if velocities are separating
-                            if (velAlongNormal <= 0.0f)
-                            {
-                                // Calculate minimum bounciness value from both objects
-                                float e = fminf(physicObjects[i]->rigidbody.bounciness, physicObjects[k]->rigidbody.bounciness);
-                                
-                                // Calculate impulse scalar value
-                                float j = -(1.0f + e)*velAlongNormal;
-                                j /= 1.0f/physicObjects[i]->rigidbody.mass + 1.0f/physicObjects[k]->rigidbody.mass;
-                                
-                                // Calculate final impulse vector
-                                Vector2 impulse = { j*contactNormal.x, j*contactNormal.y };
-                                
-                                // Calculate collision mass ration
-                                float massSum = physicObjects[i]->rigidbody.mass + physicObjects[k]->rigidbody.mass;
-                                float ratio = 0.0f;
-                                
-                                // Apply impulse to current rigidbodies velocities if they are enabled
-                                if (physicObjects[i]->rigidbody.enabled) 
-                                {
-                                    // Calculate inverted mass ration
-                                    ratio = physicObjects[i]->rigidbody.mass/massSum;
-                                    
-                                    // Apply impulse direction to velocity
-                                    physicObjects[i]->rigidbody.velocity.x -= impulse.x*ratio*(1.0f+physicObjects[i]->rigidbody.bounciness);
-                                    physicObjects[i]->rigidbody.velocity.y -= impulse.y*ratio*(1.0f+physicObjects[i]->rigidbody.bounciness);
-                                }
-                                
-                                if (physicObjects[k]->rigidbody.enabled) 
-                                {
-                                    // Calculate inverted mass ration
-                                    ratio = physicObjects[k]->rigidbody.mass/massSum;
-                                    
-                                    // Apply impulse direction to velocity
-                                    physicObjects[k]->rigidbody.velocity.x += impulse.x*ratio*(1.0f+physicObjects[i]->rigidbody.bounciness);
-                                    physicObjects[k]->rigidbody.velocity.y += impulse.y*ratio*(1.0f+physicObjects[i]->rigidbody.bounciness);
-                                }
-                                
-                                // 3. Correct colliders overlaping (transform position)
-                                // ---------------------------------------------------------------------------------------------------------------------------------
-                                
-                                // Calculate transform position penetration correction
-                                Vector2 posCorrection;
-                                posCorrection.x = penetrationDepth/((1.0f/physicObjects[i]->rigidbody.mass) + (1.0f/physicObjects[k]->rigidbody.mass))*PHYSICS_ERRORPERCENT*contactNormal.x;
-                                posCorrection.y = penetrationDepth/((1.0f/physicObjects[i]->rigidbody.mass) + (1.0f/physicObjects[k]->rigidbody.mass))*PHYSICS_ERRORPERCENT*contactNormal.y;
-                                
-                                // Fix transform positions
-                                if (physicObjects[i]->rigidbody.enabled)
-                                {                                        
-                                    // Fix physic objects transform position
-                                    physicObjects[i]->transform.position.x -= 1.0f/physicObjects[i]->rigidbody.mass*posCorrection.x;
-                                    physicObjects[i]->transform.position.y += 1.0f/physicObjects[i]->rigidbody.mass*posCorrection.y;
-                                    
-                                    // Update collider bounds
-                                    physicObjects[i]->collider.bounds = TransformToRectangle(physicObjects[i]->transform);
-                                    
-                                    if (physicObjects[k]->rigidbody.enabled)
-                                    {
-                                        // Fix physic objects transform position
-                                        physicObjects[k]->transform.position.x += 1.0f/physicObjects[k]->rigidbody.mass*posCorrection.x;
-                                        physicObjects[k]->transform.position.y -= 1.0f/physicObjects[k]->rigidbody.mass*posCorrection.y;
-                                        
-                                        // Update collider bounds
-                                        physicObjects[k]->collider.bounds = TransformToRectangle(physicObjects[k]->transform);
-                                    }
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
-}
-
-// Unitialize all physic objects and empty the objects pool
-void ClosePhysics()
-{
-    // Free all dynamic memory allocations
-    for (int i = 0; i < physicObjectsCount; i++) free(physicObjects[i]);
-    
-    // Reset enabled physic objects count
-    physicObjectsCount = 0;
-}
-
-// Create a new physic object dinamically, initialize it and add to pool
-PhysicObject CreatePhysicObject(Vector2 position, float rotation, Vector2 scale)
-{
-    // Allocate dynamic memory
-    PhysicObject obj = (PhysicObject)malloc(sizeof(PhysicObjectData));
-    
-    // Initialize physic object values with generic values
-    obj->id = physicObjectsCount;
-    obj->enabled = true;
-    
-    obj->transform = (Transform){ (Vector2){ position.x - scale.x/2, position.y - scale.y/2 }, rotation, scale };
-    
-    obj->rigidbody.enabled = false;
-    obj->rigidbody.mass = 1.0f;
-    obj->rigidbody.acceleration = (Vector2){ 0.0f, 0.0f };
-    obj->rigidbody.velocity = (Vector2){ 0.0f, 0.0f };
-    obj->rigidbody.applyGravity = false;
-    obj->rigidbody.isGrounded = false;
-    obj->rigidbody.friction = 0.0f;
-    obj->rigidbody.bounciness = 0.0f;
-    
-    obj->collider.enabled = true;
-    obj->collider.type = COLLIDER_RECTANGLE;
-    obj->collider.bounds = TransformToRectangle(obj->transform);
-    obj->collider.radius = 0.0f;
-    
-    // Add new physic object to the pointers array
-    physicObjects[physicObjectsCount] = obj;
-    
-    // Increase enabled physic objects count
-    physicObjectsCount++;
-    
-    return obj;
-}
-
-// Destroy a specific physic object and take it out of the list
-void DestroyPhysicObject(PhysicObject pObj)
-{
-    // Free dynamic memory allocation
-    free(physicObjects[pObj->id]);
-    
-    // Remove *obj from the pointers array
-    for (int i = pObj->id; i < physicObjectsCount; i++)
-    {
-        // Resort all the following pointers of the array
-        if ((i + 1) < physicObjectsCount)
-        {
-            physicObjects[i] = physicObjects[i + 1];
-            physicObjects[i]->id = physicObjects[i + 1]->id;
-        }
-        else free(physicObjects[i]);
-    }
-    
-    // Decrease enabled physic objects count
-    physicObjectsCount--;
-}
-
-// Apply directional force to a physic object
-void ApplyForce(PhysicObject pObj, Vector2 force)
-{
-    if (pObj->rigidbody.enabled)
-    {
-        pObj->rigidbody.velocity.x += force.x/pObj->rigidbody.mass;
-        pObj->rigidbody.velocity.y += force.y/pObj->rigidbody.mass;
-    }
-}
-
-// Apply radial force to all physic objects in range
-void ApplyForceAtPosition(Vector2 position, float force, float radius)
-{
-    for (int i = 0; i < physicObjectsCount; i++)
-    {
-        if (physicObjects[i]->rigidbody.enabled)
-        {
-            // Calculate direction and distance between force and physic object pposition
-            Vector2 distance = (Vector2){ physicObjects[i]->transform.position.x - position.x, physicObjects[i]->transform.position.y - position.y };
-
-            if (physicObjects[i]->collider.type == COLLIDER_RECTANGLE)
-            {
-                distance.x += physicObjects[i]->transform.scale.x/2;
-                distance.y += physicObjects[i]->transform.scale.y/2;
-            }
-            
-            float distanceLength = Vector2Length(distance);
-            
-            // Check if physic object is in force range
-            if (distanceLength <= radius)
-            {
-                // Normalize force direction
-                distance.x /= distanceLength;
-                distance.y /= -distanceLength;
-                
-                // Calculate final force
-                Vector2 finalForce = { distance.x*force, distance.y*force };
-                
-                // Apply force to the physic object
-                ApplyForce(physicObjects[i], finalForce);
-            }
-        }
-    }
-}
-
-// Convert Transform data type to Rectangle (position and scale)
-Rectangle TransformToRectangle(Transform transform)
-{
-    return (Rectangle){transform.position.x, transform.position.y, transform.scale.x, transform.scale.y};
-}
-
-//----------------------------------------------------------------------------------
-// Module specific Functions Definition
-//----------------------------------------------------------------------------------
-
-// Returns the dot product of two Vector2
-static float Vector2DotProduct(Vector2 v1, Vector2 v2)
-{
-    float result;
-
-    result = v1.x*v2.x + v1.y*v2.y;
-
-    return result;
-}
-
-static float Vector2Length(Vector2 v)
-{
-    float result;
-    
-    result = sqrt(v.x*v.x + v.y*v.y);
-    
-    return result;
-}

+ 754 - 22
src/physac.h

@@ -1,8 +1,53 @@
 /**********************************************************************************************
 *
-*   [physac] raylib physics module - Basic functions to apply physics to 2D objects
+*   physac 1.0 - 2D Physics library for raylib (https://github.com/raysan5/raylib)
 *
-*   Copyright (c) 2016 Victor Fisac and Ramon Santamaria
+*   // TODO: Description...
+* 
+*   CONFIGURATION:
+*   
+*   #define PHYSAC_IMPLEMENTATION
+*       Generates the implementation of the library into the included file.
+*       If not defined, the library is in header only mode and can be included in other headers 
+*       or source files without problems. But only ONE file should hold the implementation.
+*
+*   #define PHYSAC_STATIC (defined by default)
+*       The generated implementation will stay private inside implementation file and all 
+*       internal symbols and functions will only be visible inside that file.
+*
+*   #define PHYSAC_NO_THREADS
+*       The generated implementation won't include pthread library and user must create a secondary thread to call PhysicsThread().
+*       It is so important that the thread where PhysicsThread() is called must not have v-sync or any other CPU limitation.
+*
+*   #define PHYSAC_STANDALONE
+*       Avoid raylib.h header inclusion in this file. Data types defined on raylib are defined
+*       internally in the library and input management and drawing functions must be provided by
+*       the user (check library implementation for further details).
+*
+*   #define PHYSAC_MALLOC()
+*   #define PHYSAC_FREE()
+*       You can define your own malloc/free implementation replacing stdlib.h malloc()/free() functions.
+*       Otherwise it will include stdlib.h and use the C standard library malloc()/free() function.
+*       
+*   LIMITATIONS:
+*
+*       - There is a limit of 256 physic objects.
+*       - Physics behaviour can be unexpected using bounciness or friction values out of 0.0f - 1.0f range.
+*       - The module is limited to 2D axis oriented physics.
+*       - Physics colliders must be rectangle or circle shapes (there is not a custom polygon collider type).
+*
+*   VERSIONS:
+*
+*   1.0 (14-Jun-2016) New module defines and fixed some delta time calculation bugs.
+*   0.9 (09-Jun-2016) Module names review and converted to header-only.
+*   0.8 (23-Mar-2016) Complete module redesign, steps-based for better physics resolution.
+*   0.3 (13-Feb-2016) Reviewed to add PhysicObjects pool.
+*   0.2 (03-Jan-2016) Improved physics calculations.
+*   0.1 (30-Dec-2015) Initial release.
+*
+*   LICENSE: zlib/libpng
+*
+*   Copyright (c) 2016 Victor Fisac (main developer) and Ramon Santamaria
 *
 *   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.
@@ -24,6 +69,21 @@
 #ifndef PHYSAC_H
 #define PHYSAC_H
 
+#if !defined(RAYGUI_STANDALONE)
+    #include "raylib.h"
+#endif
+
+#define PHYSAC_STATIC
+#ifdef PHYSAC_STATIC
+    #define PHYSACDEF static            // Functions just visible to module including this file
+#else
+    #ifdef __cplusplus
+        #define PHYSACDEF extern "C"    // Functions visible from other files (no name mangling of functions in C++)
+    #else
+        #define PHYSACDEF extern        // Functions visible from other files
+    #endif
+#endif
+
 //----------------------------------------------------------------------------------
 // Defines and Macros
 //----------------------------------------------------------------------------------
@@ -33,12 +93,28 @@
 // Types and Structures Definition
 // NOTE: Below types are required for PHYSAC_STANDALONE usage
 //----------------------------------------------------------------------------------
+#if defined(PHYSAC_STANDALONE)
+    #ifndef __cplusplus
+    // Boolean type
+        #ifndef true
+            typedef enum { false, true } bool;
+        #endif
+    #endif
+
+    // Vector2 type
+    typedef struct Vector2 {
+        float x;
+        float y;
+    } Vector2;
 
-// Vector2 type
-typedef struct Vector2 {
-    float x;
-    float y;
-} Vector2;
+    // Rectangle type
+    typedef struct Rectangle {
+        int x;
+        int y;
+        int width;
+        int height;
+    } Rectangle;
+#endif
 
 typedef enum { COLLIDER_CIRCLE, COLLIDER_RECTANGLE } ColliderType;
 
@@ -66,35 +142,691 @@ typedef struct Collider {
     int radius;             // Used for COLLIDER_CIRCLE
 } Collider;
 
-typedef struct PhysicObjectData {
+typedef struct PhysicBodyData {
     unsigned int id;
     Transform transform;
     Rigidbody rigidbody;
     Collider collider;
     bool enabled;
-} PhysicObjectData, *PhysicObject;
+} PhysicBodyData, *PhysicBody;
+
+//----------------------------------------------------------------------------------
+// Module Functions Declaration
+//----------------------------------------------------------------------------------
+PHYSACDEF void InitPhysics(Vector2 gravity);                                            // Initializes pointers array (just pointers, fixed size)
+PHYSACDEF void* PhysicsThread(void *arg);                                               // Physics calculations thread function
+PHYSACDEF void ClosePhysics();                                                          // Unitialize all physic objects and empty the objects pool
+
+PHYSACDEF PhysicBody CreatePhysicBody(Vector2 position, float rotation, Vector2 scale); // Create a new physic body dinamically, initialize it and add to pool
+PHYSACDEF void DestroyPhysicBody(PhysicBody pbody);                                     // Destroy a specific physic body and take it out of the list
+
+PHYSACDEF void ApplyForce(PhysicBody pbody, Vector2 force);                             // Apply directional force to a physic body
+PHYSACDEF void ApplyForceAtPosition(Vector2 position, float force, float radius);       // Apply radial force to all physic objects in range
+
+PHYSACDEF Rectangle TransformToRectangle(Transform transform);                          // Convert Transform data type to Rectangle (position and scale)
 
-#ifdef __cplusplus
-extern "C" {            // Prevents name mangling of functions
+#endif // PHYSAC_H
+
+
+/***********************************************************************************
+*
+*   PHYSAC IMPLEMENTATION
+*
+************************************************************************************/
+
+#if defined(PHYSAC_IMPLEMENTATION)
+
+// Check if custom malloc/free functions defined, if not, using standard ones
+#if !defined(PHYSAC_MALLOC)
+    #include <stdlib.h>     // Required for: malloc(), free()
+    
+    #define PHYSAC_MALLOC(size)  malloc(size)
+    #define PHYSAC_FREE(ptr)     free(ptr)
+#endif
+
+#include <math.h>           // Required for: cos(), sin(), abs(), fminf()
+#include <stdint.h>         // Required for typedef unsigned long long int uint64_t, used by hi-res timer
+
+#ifndef PHYSAC_NO_THREADS
+    #include <pthread.h>        // Required for: pthread_create()
+#endif
+
+#if defined(PLATFORM_DESKTOP)
+    // Functions required to query time on Windows
+    int __stdcall QueryPerformanceCounter(unsigned long long int *lpPerformanceCount);
+    int __stdcall QueryPerformanceFrequency(unsigned long long int *lpFrequency);
+#elif defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI)
+    #include <sys/time.h>       // Required for: timespec
+    #include <time.h>           // Required for: clock_gettime()
 #endif
 
 //----------------------------------------------------------------------------------
-// Module Functions Declaration
+// Defines and Macros
+//----------------------------------------------------------------------------------
+#define MAX_PHYSIC_BODIES       256             // Maximum available physic bodies slots in bodies pool
+#define PHYSICS_TIMESTEP        0.016666        // Physics fixed time step (1/fps)
+#define PHYSICS_ACCURACY        0.0001f         // Velocity subtract operations round filter (friction)
+#define PHYSICS_ERRORPERCENT    0.001f          // Collision resolve position fix
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+// NOTE: Below types are required for PHYSAC_STANDALONE usage
+//----------------------------------------------------------------------------------
+// ...
+
 //----------------------------------------------------------------------------------
-void InitPhysics(Vector2 gravity);                                                      // Initializes pointers array (just pointers, fixed size)
-void UpdatePhysics();                                                                   // Update physic objects, calculating physic behaviours and collisions detection
-void ClosePhysics();                                                                    // Unitialize all physic objects and empty the objects pool
+// Global Variables Definition
+//----------------------------------------------------------------------------------
+static bool physicsThreadEnabled = false;                           // Physics calculations thread exit control
+static uint64_t baseTime;                                           // Base time measure for hi-res timer
+static double currentTime, previousTime;                            // Used to track timmings
+static PhysicBody physicBodies[MAX_PHYSIC_BODIES];                  // Physic bodies pool
+static int physicBodiesCount;                                       // Counts current enabled physic bodies
+static Vector2 gravityForce;                                        // Gravity force
+
+//----------------------------------------------------------------------------------
+// Module specific Functions Declaration
+//----------------------------------------------------------------------------------
+static void UpdatePhysics(double deltaTime);                        // Update physic objects, calculating physic behaviours and collisions detection
+static void InitTimer(void);                                        // Initialize hi-resolution timer
+static double GetCurrentTime(void);                                 // Time measure returned are microseconds
+static float Vector2DotProduct(Vector2 v1, Vector2 v2);             // Returns the dot product of two Vector2
+static float Vector2Length(Vector2 v);                              // Returns the length of a Vector2
+
+//----------------------------------------------------------------------------------
+// Module Functions Definition
+//----------------------------------------------------------------------------------
+
+// Initializes pointers array (just pointers, fixed size)
+PHYSACDEF void InitPhysics(Vector2 gravity)
+{
+    // Initialize physics variables
+    physicBodiesCount = 0;
+    gravityForce = gravity;
+    
+    #ifndef PHYSAC_NO_THREADS       // NOTE: if defined, user will need to create a thread for PhysicsThread function manually
+        // Create physics thread
+        pthread_t tid;
+        pthread_create(&tid, NULL, &PhysicsThread, NULL);
+    #endif
+}
+
+// Unitialize all physic objects and empty the objects pool
+PHYSACDEF void ClosePhysics()
+{
+    // Exit physics thread loop
+    physicsThreadEnabled = false;
+    
+    // Free all dynamic memory allocations
+    for (int i = 0; i < physicBodiesCount; i++) PHYSAC_FREE(physicBodies[i]);
+    
+    // Reset enabled physic objects count
+    physicBodiesCount = 0;
+}
+
+// Create a new physic body dinamically, initialize it and add to pool
+PHYSACDEF PhysicBody CreatePhysicBody(Vector2 position, float rotation, Vector2 scale)
+{
+    // Allocate dynamic memory
+    PhysicBody obj = (PhysicBody)PHYSAC_MALLOC(sizeof(PhysicBodyData));
+    
+    // Initialize physic body values with generic values
+    obj->id = physicBodiesCount;
+    obj->enabled = true;
+    
+    obj->transform = (Transform){ (Vector2){ position.x - scale.x/2, position.y - scale.y/2 }, rotation, scale };
+    
+    obj->rigidbody.enabled = false;
+    obj->rigidbody.mass = 1.0f;
+    obj->rigidbody.acceleration = (Vector2){ 0.0f, 0.0f };
+    obj->rigidbody.velocity = (Vector2){ 0.0f, 0.0f };
+    obj->rigidbody.applyGravity = false;
+    obj->rigidbody.isGrounded = false;
+    obj->rigidbody.friction = 0.0f;
+    obj->rigidbody.bounciness = 0.0f;
+    
+    obj->collider.enabled = true;
+    obj->collider.type = COLLIDER_RECTANGLE;
+    obj->collider.bounds = TransformToRectangle(obj->transform);
+    obj->collider.radius = 0.0f;
+    
+    // Add new physic body to the pointers array
+    physicBodies[physicBodiesCount] = obj;
+    
+    // Increase enabled physic bodies count
+    physicBodiesCount++;
+    
+    return obj;
+}
+
+// Destroy a specific physic body and take it out of the list
+PHYSACDEF void DestroyPhysicBody(PhysicBody pbody)
+{
+    // Free dynamic memory allocation
+    PHYSAC_FREE(physicBodies[pbody->id]);
+    
+    // Remove *obj from the pointers array
+    for (int i = pbody->id; i < physicBodiesCount; i++)
+    {
+        // Resort all the following pointers of the array
+        if ((i + 1) < physicBodiesCount)
+        {
+            physicBodies[i] = physicBodies[i + 1];
+            physicBodies[i]->id = physicBodies[i + 1]->id;
+        }
+        else PHYSAC_FREE(physicBodies[i]);
+    }
+    
+    // Decrease enabled physic bodies count
+    physicBodiesCount--;
+}
+
+// Apply directional force to a physic body
+PHYSACDEF void ApplyForce(PhysicBody pbody, Vector2 force)
+{
+    if (pbody->rigidbody.enabled)
+    {
+        pbody->rigidbody.velocity.x += force.x/pbody->rigidbody.mass;
+        pbody->rigidbody.velocity.y += force.y/pbody->rigidbody.mass;
+    }
+}
+
+// Apply radial force to all physic objects in range
+PHYSACDEF void ApplyForceAtPosition(Vector2 position, float force, float radius)
+{
+    for (int i = 0; i < physicBodiesCount; i++)
+    {
+        if (physicBodies[i]->rigidbody.enabled)
+        {
+            // Calculate direction and distance between force and physic body position
+            Vector2 distance = (Vector2){ physicBodies[i]->transform.position.x - position.x, physicBodies[i]->transform.position.y - position.y };
+
+            if (physicBodies[i]->collider.type == COLLIDER_RECTANGLE)
+            {
+                distance.x += physicBodies[i]->transform.scale.x/2;
+                distance.y += physicBodies[i]->transform.scale.y/2;
+            }
+            
+            float distanceLength = Vector2Length(distance);
+            
+            // Check if physic body is in force range
+            if (distanceLength <= radius)
+            {
+                // Normalize force direction
+                distance.x /= distanceLength;
+                distance.y /= -distanceLength;
+                
+                // Calculate final force
+                Vector2 finalForce = { distance.x*force, distance.y*force };
+                
+                // Apply force to the physic body
+                ApplyForce(physicBodies[i], finalForce);
+            }
+        }
+    }
+}
+
+// Convert Transform data type to Rectangle (position and scale)
+PHYSACDEF Rectangle TransformToRectangle(Transform transform)
+{
+    return (Rectangle){transform.position.x, transform.position.y, transform.scale.x, transform.scale.y};
+}
 
-PhysicObject CreatePhysicObject(Vector2 position, float rotation, Vector2 scale);       // Create a new physic object dinamically, initialize it and add to pool
-void DestroyPhysicObject(PhysicObject pObj);                                            // Destroy a specific physic object and take it out of the list
+// Physics calculations thread function
+PHYSACDEF void* PhysicsThread(void *arg)
+{
+    // Initialize thread loop state
+    physicsThreadEnabled = true;
+    
+    // Initialize hi-resolution timer
+    InitTimer();
+    
+    // Physics update loop
+    while (physicsThreadEnabled) 
+    {
+        currentTime = GetCurrentTime();
+        double deltaTime = (double)(currentTime - previousTime);
+        previousTime = currentTime;
 
-void ApplyForce(PhysicObject pObj, Vector2 force);                                      // Apply directional force to a physic object
-void ApplyForceAtPosition(Vector2 position, float force, float radius);                 // Apply radial force to all physic objects in range
+        // Delta time value needs to be inverse multiplied by physics time step value (1/target fps)
+        UpdatePhysics(deltaTime/PHYSICS_TIMESTEP);
+    }
+    
+    return NULL;
+}
+
+//----------------------------------------------------------------------------------
+// Module specific Functions Definition
+//----------------------------------------------------------------------------------
+// Initialize hi-resolution timer
+static void InitTimer(void)
+{
+#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI)
+    struct timespec now;
 
-Rectangle TransformToRectangle(Transform transform);                                    // Convert Transform data type to Rectangle (position and scale)
+    if (clock_gettime(CLOCK_MONOTONIC, &now) == 0)  // Success
+    {
+        baseTime = (uint64_t)now.tv_sec*1000000000LLU + (uint64_t)now.tv_nsec;
+    }
+#endif
 
-#ifdef __cplusplus
+    previousTime = GetCurrentTime();       // Get time as double
 }
+
+// Time measure returned are microseconds
+static double GetCurrentTime(void)
+{
+    double time;
+    
+#if defined(PLATFORM_DESKTOP)
+    unsigned long long int clockFrequency, currentTime;
+    
+    QueryPerformanceFrequency(&clockFrequency);
+    QueryPerformanceCounter(&currentTime);
+    
+    time = (double)((double)currentTime/(double)clockFrequency);
 #endif
 
-#endif // PHYSAC_H
+#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI)
+    struct timespec ts;
+    clock_gettime(CLOCK_MONOTONIC, &ts);
+    uint64_t temp = (uint64_t)ts.tv_sec*1000000000LLU + (uint64_t)ts.tv_nsec;
+
+    time = (double)(temp - baseTime)*1e-9;
+#endif
+
+    return time;
+}
+
+// Returns the dot product of two Vector2
+static float Vector2DotProduct(Vector2 v1, Vector2 v2)
+{
+    float result;
+
+    result = v1.x*v2.x + v1.y*v2.y;
+
+    return result;
+}
+
+static float Vector2Length(Vector2 v)
+{
+    float result;
+    
+    result = sqrt(v.x*v.x + v.y*v.y);
+    
+    return result;
+}
+
+// Update physic objects, calculating physic behaviours and collisions detection
+static void UpdatePhysics(double deltaTime)
+{
+    for (int i = 0; i < physicBodiesCount; i++)
+    {
+        if (physicBodies[i]->enabled)
+        {
+            // Update physic behaviour
+            if (physicBodies[i]->rigidbody.enabled)
+            {
+                // Apply friction to acceleration in X axis
+                if (physicBodies[i]->rigidbody.acceleration.x > PHYSICS_ACCURACY) physicBodies[i]->rigidbody.acceleration.x -= physicBodies[i]->rigidbody.friction*deltaTime;
+                else if (physicBodies[i]->rigidbody.acceleration.x < PHYSICS_ACCURACY) physicBodies[i]->rigidbody.acceleration.x += physicBodies[i]->rigidbody.friction*deltaTime;
+                else physicBodies[i]->rigidbody.acceleration.x = 0.0f;
+                
+                // Apply friction to acceleration in Y axis
+                if (physicBodies[i]->rigidbody.acceleration.y > PHYSICS_ACCURACY) physicBodies[i]->rigidbody.acceleration.y -= physicBodies[i]->rigidbody.friction*deltaTime;
+                else if (physicBodies[i]->rigidbody.acceleration.y < PHYSICS_ACCURACY) physicBodies[i]->rigidbody.acceleration.y += physicBodies[i]->rigidbody.friction*deltaTime;
+                else physicBodies[i]->rigidbody.acceleration.y = 0.0f;
+                
+                // Apply friction to velocity in X axis
+                if (physicBodies[i]->rigidbody.velocity.x > PHYSICS_ACCURACY) physicBodies[i]->rigidbody.velocity.x -= physicBodies[i]->rigidbody.friction*deltaTime;
+                else if (physicBodies[i]->rigidbody.velocity.x < PHYSICS_ACCURACY) physicBodies[i]->rigidbody.velocity.x += physicBodies[i]->rigidbody.friction*deltaTime;
+                else physicBodies[i]->rigidbody.velocity.x = 0.0f;
+                
+                // Apply friction to velocity in Y axis
+                if (physicBodies[i]->rigidbody.velocity.y > PHYSICS_ACCURACY) physicBodies[i]->rigidbody.velocity.y -= physicBodies[i]->rigidbody.friction*deltaTime;
+                else if (physicBodies[i]->rigidbody.velocity.y < PHYSICS_ACCURACY) physicBodies[i]->rigidbody.velocity.y += physicBodies[i]->rigidbody.friction*deltaTime;
+                else physicBodies[i]->rigidbody.velocity.y = 0.0f;
+                
+                // Apply gravity to velocity
+                if (physicBodies[i]->rigidbody.applyGravity)
+                {
+                    physicBodies[i]->rigidbody.velocity.x += gravityForce.x*deltaTime;
+                    physicBodies[i]->rigidbody.velocity.y += gravityForce.y*deltaTime;
+                }
+                
+                // Apply acceleration to velocity
+                physicBodies[i]->rigidbody.velocity.x += physicBodies[i]->rigidbody.acceleration.x*deltaTime;
+                physicBodies[i]->rigidbody.velocity.y += physicBodies[i]->rigidbody.acceleration.y*deltaTime;
+                
+                // Apply velocity to position
+                physicBodies[i]->transform.position.x += physicBodies[i]->rigidbody.velocity.x*deltaTime;
+                physicBodies[i]->transform.position.y -= physicBodies[i]->rigidbody.velocity.y*deltaTime;
+            }
+            
+            // Update collision detection
+            if (physicBodies[i]->collider.enabled)
+            {
+                // Update collider bounds
+                physicBodies[i]->collider.bounds = TransformToRectangle(physicBodies[i]->transform);
+                
+                // Check collision with other colliders
+                for (int k = 0; k < physicBodiesCount; k++)
+                {
+                    if (physicBodies[k]->collider.enabled && i != k)
+                    {
+                        // Resolve physic collision
+                        // NOTE: collision resolve is generic for all directions and conditions (no axis separated cases behaviours)
+                        // and it is separated in rigidbody attributes resolve (velocity changes by impulse) and position correction (position overlap)
+                        
+                        // 1. Calculate collision normal
+                        // -------------------------------------------------------------------------------------------------------------------------------------
+                        
+                        // Define collision contact normal, direction and penetration depth
+                        Vector2 contactNormal = { 0.0f, 0.0f };
+                        Vector2 direction = { 0.0f, 0.0f };
+                        float penetrationDepth = 0.0f;
+                        
+                        switch (physicBodies[i]->collider.type)
+                        {
+                            case COLLIDER_RECTANGLE:
+                            {
+                                switch (physicBodies[k]->collider.type)
+                                {
+                                    case COLLIDER_RECTANGLE:
+                                    {
+                                        // Check if colliders are overlapped
+                                        if (CheckCollisionRecs(physicBodies[i]->collider.bounds, physicBodies[k]->collider.bounds))
+                                        {
+                                            // Calculate direction vector from i to k
+                                            direction.x = (physicBodies[k]->transform.position.x + physicBodies[k]->transform.scale.x/2) - (physicBodies[i]->transform.position.x + physicBodies[i]->transform.scale.x/2);
+                                            direction.y = (physicBodies[k]->transform.position.y + physicBodies[k]->transform.scale.y/2) - (physicBodies[i]->transform.position.y + physicBodies[i]->transform.scale.y/2);
+                                            
+                                            // Define overlapping and penetration attributes
+                                            Vector2 overlap;
+
+                                            // Calculate overlap on X axis
+                                            overlap.x = (physicBodies[i]->transform.scale.x + physicBodies[k]->transform.scale.x)/2 - abs(direction.x);
+                                            
+                                            // SAT test on X axis
+                                            if (overlap.x > 0.0f)
+                                            {
+                                                // Calculate overlap on Y axis
+                                                overlap.y = (physicBodies[i]->transform.scale.y + physicBodies[k]->transform.scale.y)/2 - abs(direction.y);
+                                                
+                                                // SAT test on Y axis
+                                                if (overlap.y > 0.0f)
+                                                {
+                                                    // Find out which axis is axis of least penetration
+                                                    if (overlap.y > overlap.x)
+                                                    {
+                                                        // Point towards k knowing that direction points from i to k
+                                                        if (direction.x < 0.0f) contactNormal = (Vector2){ -1.0f, 0.0f };
+                                                        else contactNormal = (Vector2){ 1.0f, 0.0f };
+                                                        
+                                                        // Update penetration depth for position correction
+                                                        penetrationDepth = overlap.x;
+                                                    }
+                                                    else
+                                                    {
+                                                        // Point towards k knowing that direction points from i to k
+                                                        if (direction.y < 0.0f) contactNormal = (Vector2){ 0.0f, 1.0f };
+                                                        else contactNormal = (Vector2){ 0.0f, -1.0f };
+                                                        
+                                                        // Update penetration depth for position correction
+                                                        penetrationDepth = overlap.y;
+                                                    }
+                                                }
+                                            }
+                                        }
+                                    } break;
+                                    case COLLIDER_CIRCLE:
+                                    {
+                                        if (CheckCollisionCircleRec(physicBodies[k]->transform.position, physicBodies[k]->collider.radius, physicBodies[i]->collider.bounds))
+                                        {
+                                            // Calculate direction vector between circles
+                                            direction.x = physicBodies[k]->transform.position.x - physicBodies[i]->transform.position.x + physicBodies[i]->transform.scale.x/2;
+                                            direction.y = physicBodies[k]->transform.position.y - physicBodies[i]->transform.position.y + physicBodies[i]->transform.scale.y/2;
+                                            
+                                            // Calculate closest point on rectangle to circle
+                                            Vector2 closestPoint = { 0.0f, 0.0f };
+                                            if (direction.x > 0.0f) closestPoint.x = physicBodies[i]->collider.bounds.x + physicBodies[i]->collider.bounds.width;
+                                            else closestPoint.x = physicBodies[i]->collider.bounds.x;
+                                            
+                                            if (direction.y > 0.0f) closestPoint.y = physicBodies[i]->collider.bounds.y + physicBodies[i]->collider.bounds.height;
+                                            else closestPoint.y = physicBodies[i]->collider.bounds.y;
+                                            
+                                            // Check if the closest point is inside the circle
+                                            if (CheckCollisionPointCircle(closestPoint, physicBodies[k]->transform.position, physicBodies[k]->collider.radius))
+                                            {
+                                                // Recalculate direction based on closest point position
+                                                direction.x = physicBodies[k]->transform.position.x - closestPoint.x;
+                                                direction.y = physicBodies[k]->transform.position.y - closestPoint.y;
+                                                float distance = Vector2Length(direction);
+                                                
+                                                // Calculate final contact normal
+                                                contactNormal.x = direction.x/distance;
+                                                contactNormal.y = -direction.y/distance;
+                                                
+                                                // Calculate penetration depth
+                                                penetrationDepth = physicBodies[k]->collider.radius - distance;
+                                            }
+                                            else
+                                            {
+                                                if (abs(direction.y) < abs(direction.x))
+                                                {
+                                                    // Calculate final contact normal
+                                                    if (direction.y > 0.0f)
+                                                    {
+                                                        contactNormal = (Vector2){ 0.0f, -1.0f };
+                                                        penetrationDepth = fabs(physicBodies[i]->collider.bounds.y - physicBodies[k]->transform.position.y - physicBodies[k]->collider.radius);
+                                                    }
+                                                    else 
+                                                    {
+                                                        contactNormal = (Vector2){ 0.0f, 1.0f };
+                                                        penetrationDepth = fabs(physicBodies[i]->collider.bounds.y - physicBodies[k]->transform.position.y + physicBodies[k]->collider.radius);
+                                                    }
+                                                }
+                                                else
+                                                {
+                                                    // Calculate final contact normal
+                                                    if (direction.x > 0.0f)
+                                                    {
+                                                        contactNormal = (Vector2){ 1.0f, 0.0f };
+                                                        penetrationDepth = fabs(physicBodies[k]->transform.position.x + physicBodies[k]->collider.radius - physicBodies[i]->collider.bounds.x);
+                                                    }
+                                                    else 
+                                                    {
+                                                        contactNormal = (Vector2){ -1.0f, 0.0f };
+                                                        penetrationDepth = fabs(physicBodies[i]->collider.bounds.x + physicBodies[i]->collider.bounds.width - physicBodies[k]->transform.position.x - physicBodies[k]->collider.radius);
+                                                    }
+                                                }
+                                            }
+                                        }
+                                    } break;
+                                }
+                            } break;
+                            case COLLIDER_CIRCLE:
+                            {
+                                switch (physicBodies[k]->collider.type)
+                                {
+                                    case COLLIDER_RECTANGLE:
+                                    {
+                                        if (CheckCollisionCircleRec(physicBodies[i]->transform.position, physicBodies[i]->collider.radius, physicBodies[k]->collider.bounds))
+                                        {
+                                            // Calculate direction vector between circles
+                                            direction.x = physicBodies[k]->transform.position.x + physicBodies[i]->transform.scale.x/2 - physicBodies[i]->transform.position.x;
+                                            direction.y = physicBodies[k]->transform.position.y + physicBodies[i]->transform.scale.y/2 - physicBodies[i]->transform.position.y;
+                                            
+                                            // Calculate closest point on rectangle to circle
+                                            Vector2 closestPoint = { 0.0f, 0.0f };
+                                            if (direction.x > 0.0f) closestPoint.x = physicBodies[k]->collider.bounds.x + physicBodies[k]->collider.bounds.width;
+                                            else closestPoint.x = physicBodies[k]->collider.bounds.x;
+                                            
+                                            if (direction.y > 0.0f) closestPoint.y = physicBodies[k]->collider.bounds.y + physicBodies[k]->collider.bounds.height;
+                                            else closestPoint.y = physicBodies[k]->collider.bounds.y;
+                                            
+                                            // Check if the closest point is inside the circle
+                                            if (CheckCollisionPointCircle(closestPoint, physicBodies[i]->transform.position, physicBodies[i]->collider.radius))
+                                            {
+                                                // Recalculate direction based on closest point position
+                                                direction.x = physicBodies[i]->transform.position.x - closestPoint.x;
+                                                direction.y = physicBodies[i]->transform.position.y - closestPoint.y;
+                                                float distance = Vector2Length(direction);
+                                                
+                                                // Calculate final contact normal
+                                                contactNormal.x = direction.x/distance;
+                                                contactNormal.y = -direction.y/distance;
+                                                
+                                                // Calculate penetration depth
+                                                penetrationDepth = physicBodies[k]->collider.radius - distance;
+                                            }
+                                            else
+                                            {
+                                                if (abs(direction.y) < abs(direction.x))
+                                                {
+                                                    // Calculate final contact normal
+                                                    if (direction.y > 0.0f)
+                                                    {
+                                                        contactNormal = (Vector2){ 0.0f, -1.0f };
+                                                        penetrationDepth = fabs(physicBodies[k]->collider.bounds.y - physicBodies[i]->transform.position.y - physicBodies[i]->collider.radius);
+                                                    }
+                                                    else 
+                                                    {
+                                                        contactNormal = (Vector2){ 0.0f, 1.0f };
+                                                        penetrationDepth = fabs(physicBodies[k]->collider.bounds.y - physicBodies[i]->transform.position.y + physicBodies[i]->collider.radius);
+                                                    }
+                                                }
+                                                else
+                                                {
+                                                    // Calculate final contact normal and penetration depth
+                                                    if (direction.x > 0.0f)
+                                                    {
+                                                        contactNormal = (Vector2){ 1.0f, 0.0f };
+                                                        penetrationDepth = fabs(physicBodies[i]->transform.position.x + physicBodies[i]->collider.radius - physicBodies[k]->collider.bounds.x);
+                                                    }
+                                                    else 
+                                                    {
+                                                        contactNormal = (Vector2){ -1.0f, 0.0f };
+                                                        penetrationDepth = fabs(physicBodies[k]->collider.bounds.x + physicBodies[k]->collider.bounds.width - physicBodies[i]->transform.position.x - physicBodies[i]->collider.radius);
+                                                    }
+                                                }
+                                            }
+                                        }
+                                    } break;
+                                    case COLLIDER_CIRCLE:
+                                    {
+                                        // Check if colliders are overlapped
+                                        if (CheckCollisionCircles(physicBodies[i]->transform.position, physicBodies[i]->collider.radius, physicBodies[k]->transform.position, physicBodies[k]->collider.radius))
+                                        {
+                                            // Calculate direction vector between circles
+                                            direction.x = physicBodies[k]->transform.position.x - physicBodies[i]->transform.position.x;
+                                            direction.y = physicBodies[k]->transform.position.y - physicBodies[i]->transform.position.y;
+                                            
+                                            // Calculate distance between circles
+                                            float distance = Vector2Length(direction);
+                                            
+                                            // Check if circles are not completely overlapped
+                                            if (distance != 0.0f)
+                                            {                                                    
+                                                // Calculate contact normal direction (Y axis needs to be flipped)
+                                                contactNormal.x = direction.x/distance;
+                                                contactNormal.y = -direction.y/distance;
+                                            }
+                                            else contactNormal = (Vector2){ 1.0f, 0.0f };   // Choose random (but consistent) values
+                                        }
+                                    } break;
+                                    default: break;
+                                }
+                            } break;
+                            default: break;
+                        }
+                        
+                        // Update rigidbody grounded state
+                        if (physicBodies[i]->rigidbody.enabled) physicBodies[i]->rigidbody.isGrounded = (contactNormal.y < 0.0f);
+                        
+                        // 2. Calculate collision impulse
+                        // -------------------------------------------------------------------------------------------------------------------------------------
+                        
+                        // Calculate relative velocity
+                        Vector2 relVelocity = { 0.0f, 0.0f };
+                        relVelocity.x = physicBodies[k]->rigidbody.velocity.x - physicBodies[i]->rigidbody.velocity.x;
+                        relVelocity.y = physicBodies[k]->rigidbody.velocity.y - physicBodies[i]->rigidbody.velocity.y;
+
+                        // Calculate relative velocity in terms of the normal direction
+                        float velAlongNormal = Vector2DotProduct(relVelocity, contactNormal);
+                    
+                        // Dot not resolve if velocities are separating
+                        if (velAlongNormal <= 0.0f)
+                        {
+                            // Calculate minimum bounciness value from both objects
+                            float e = fminf(physicBodies[i]->rigidbody.bounciness, physicBodies[k]->rigidbody.bounciness);
+                            
+                            // Calculate impulse scalar value
+                            float j = -(1.0f + e)*velAlongNormal;
+                            j /= 1.0f/physicBodies[i]->rigidbody.mass + 1.0f/physicBodies[k]->rigidbody.mass;
+                            
+                            // Calculate final impulse vector
+                            Vector2 impulse = { j*contactNormal.x, j*contactNormal.y };
+                            
+                            // Calculate collision mass ration
+                            float massSum = physicBodies[i]->rigidbody.mass + physicBodies[k]->rigidbody.mass;
+                            float ratio = 0.0f;
+                            
+                            // Apply impulse to current rigidbodies velocities if they are enabled
+                            if (physicBodies[i]->rigidbody.enabled) 
+                            {
+                                // Calculate inverted mass ration
+                                ratio = physicBodies[i]->rigidbody.mass/massSum;
+                                
+                                // Apply impulse direction to velocity
+                                physicBodies[i]->rigidbody.velocity.x -= impulse.x*ratio*(1.0f+physicBodies[i]->rigidbody.bounciness);
+                                physicBodies[i]->rigidbody.velocity.y -= impulse.y*ratio*(1.0f+physicBodies[i]->rigidbody.bounciness);
+                            }
+                            
+                            if (physicBodies[k]->rigidbody.enabled) 
+                            {
+                                // Calculate inverted mass ration
+                                ratio = physicBodies[k]->rigidbody.mass/massSum;
+                                
+                                // Apply impulse direction to velocity
+                                physicBodies[k]->rigidbody.velocity.x += impulse.x*ratio*(1.0f+physicBodies[i]->rigidbody.bounciness);
+                                physicBodies[k]->rigidbody.velocity.y += impulse.y*ratio*(1.0f+physicBodies[i]->rigidbody.bounciness);
+                            }
+                            
+                            // 3. Correct colliders overlaping (transform position)
+                            // ---------------------------------------------------------------------------------------------------------------------------------
+                            
+                            // Calculate transform position penetration correction
+                            Vector2 posCorrection;
+                            posCorrection.x = penetrationDepth/((1.0f/physicBodies[i]->rigidbody.mass) + (1.0f/physicBodies[k]->rigidbody.mass))*PHYSICS_ERRORPERCENT*contactNormal.x;
+                            posCorrection.y = penetrationDepth/((1.0f/physicBodies[i]->rigidbody.mass) + (1.0f/physicBodies[k]->rigidbody.mass))*PHYSICS_ERRORPERCENT*contactNormal.y;
+                            
+                            // Fix transform positions
+                            if (physicBodies[i]->rigidbody.enabled)
+                            {                                        
+                                // Fix physic objects transform position
+                                physicBodies[i]->transform.position.x -= 1.0f/physicBodies[i]->rigidbody.mass*posCorrection.x;
+                                physicBodies[i]->transform.position.y += 1.0f/physicBodies[i]->rigidbody.mass*posCorrection.y;
+                                
+                                // Update collider bounds
+                                physicBodies[i]->collider.bounds = TransformToRectangle(physicBodies[i]->transform);
+                                
+                                if (physicBodies[k]->rigidbody.enabled)
+                                {
+                                    // Fix physic objects transform position
+                                    physicBodies[k]->transform.position.x += 1.0f/physicBodies[k]->rigidbody.mass*posCorrection.x;
+                                    physicBodies[k]->transform.position.y -= 1.0f/physicBodies[k]->rigidbody.mass*posCorrection.y;
+                                    
+                                    // Update collider bounds
+                                    physicBodies[k]->collider.bounds = TransformToRectangle(physicBodies[k]->transform);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+#endif  // PHYSAC_IMPLEMENTATION

+ 0 - 1138
src/raygui.c

@@ -1,1138 +0,0 @@
-/**********************************************************************************************
-*
-*   raygui - raylib IMGUI system (Immedite Mode GUI)
-*
-*   Initial design by Kevin Gato and Daniel Nicolás
-*   Reviewed by Albert Martos, Ian Eito, Sergio Martinez and 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.
-*
-**********************************************************************************************/
-
-//#define RAYGUI_STANDALONE     // To use the raygui module as standalone lib, just uncomment this line
-                              // NOTE: Some external funtions are required for drawing and input management
-
-#if !defined(RAYGUI_STANDALONE)
-    #include "raylib.h"
-#endif
-
-#include "raygui.h"
-
-#include <stdio.h>      // Required for: FILE, fopen(), fclose(), fprintf(), feof(), fscanf()
-                        // NOTE: Those functions are only used in SaveGuiStyle() and LoadGuiStyle()
-                        
-#include <stdlib.h>     // Required for: malloc(), free()
-#include <string.h>     // Required for: strcmp()
-#include <stdarg.h>     // Required for: va_list, va_start(), vfprintf(), va_end()
-
-//----------------------------------------------------------------------------------
-// Defines and Macros
-//----------------------------------------------------------------------------------
-#if defined(RAYGUI_STANDALONE)
-    #define KEY_LEFT            263
-    #define KEY_RIGHT           262
-    #define MOUSE_LEFT_BUTTON     0
-#endif
-
-//----------------------------------------------------------------------------------
-// Types and Structures Definition
-//----------------------------------------------------------------------------------
-
-// GUI elements states
-typedef enum { BUTTON_DEFAULT, BUTTON_HOVER, BUTTON_PRESSED, BUTTON_CLICKED } ButtonState;
-typedef enum { TOGGLE_UNACTIVE, TOGGLE_HOVER, TOGGLE_PRESSED, TOGGLE_ACTIVE } ToggleState;
-typedef enum { COMBOBOX_UNACTIVE, COMBOBOX_HOVER, COMBOBOX_PRESSED, COMBOBOX_ACTIVE } ComboBoxState;
-typedef enum { SPINNER_DEFAULT, SPINNER_HOVER, SPINNER_PRESSED } SpinnerState;
-typedef enum { CHECKBOX_STATUS, CHECKBOX_HOVER, CHECKBOX_PRESSED } CheckBoxState;
-typedef enum { SLIDER_DEFAULT, SLIDER_HOVER, SLIDER_ACTIVE } SliderState;
-
-//----------------------------------------------------------------------------------
-// Global Variables Definition
-//----------------------------------------------------------------------------------
-
-// Current GUI style (default light)
-static int style[NUM_PROPERTIES] = {
-    0xf5f5f5ff,         // GLOBAL_BASE_COLOR,
-    0xf5f5f5ff,         // GLOBAL_BORDER_COLOR,
-    0xf5f5f5ff,         // GLOBAL_TEXT_COLOR,
-    10,                 // GLOBAL_TEXT_FONTSIZE
-    1,                  // GLOBAL_BORDER_WIDTH
-    0xf5f5f5ff,         // BACKGROUND_COLOR
-    1,                  // LABEL_BORDER_WIDTH
-    0x4d4d4dff,         // LABEL_TEXT_COLOR
-    20,                 // LABEL_TEXT_PADDING
-    2,                  // BUTTON_BORDER_WIDTH
-    20,                 // BUTTON_TEXT_PADDING
-    0x828282ff,         // BUTTON_DEFAULT_BORDER_COLOR
-    0xc8c8c8ff,         // BUTTON_DEFAULT_INSIDE_COLOR
-    0x4d4d4dff,         // BUTTON_DEFAULT_TEXT_COLOR
-    0xc8c8c8ff,         // BUTTON_HOVER_BORDER_COLOR
-    0xffffffff,         // BUTTON_HOVER_INSIDE_COLOR
-    0x353535ff,         // BUTTON_HOVER_TEXT_COLOR
-    0x7bb0d6ff,         // BUTTON_PRESSED_BORDER_COLOR
-    0xbcecffff,         // BUTTON_PRESSED_INSIDE_COLOR
-    0x5f9aa7ff,         // BUTTON_PRESSED_TEXT_COLOR
-    20,                 // TOGGLE_TEXT_PADDING
-    1,                  // TOGGLE_BORDER_WIDTH
-    0x828282ff,         // TOGGLE_DEFAULT_BORDER_COLOR
-    0xc8c8c8ff,         // TOGGLE_DEFAULT_INSIDE_COLOR
-    0x828282ff,         // TOGGLE_DEFAULT_TEXT_COLOR
-    0xc8c8c8ff,         // TOGGLE_HOVER_BORDER_COLOR
-    0xffffffff,         // TOGGLE_HOVER_INSIDE_COLOR
-    0x828282ff,         // TOGGLE_HOVER_TEXT_COLOR
-    0xbdd7eaff,         // TOGGLE_PRESSED_BORDER_COLOR
-    0xddf5ffff,         // TOGGLE_PRESSED_INSIDE_COLOR
-    0xafccd3ff,         // TOGGLE_PRESSED_TEXT_COLOR
-    0x7bb0d6ff,         // TOGGLE_ACTIVE_BORDER_COLOR
-    0xbcecffff,         // TOGGLE_ACTIVE_INSIDE_COLOR
-    0x5f9aa7ff,         // TOGGLE_ACTIVE_TEXT_COLOR
-    3,                  // TOGGLEGROUP_PADDING
-    1,                  // SLIDER_BORDER_WIDTH
-    1,                  // SLIDER_BUTTON_BORDER_WIDTH
-    0x828282ff,         // SLIDER_BORDER_COLOR
-    0xc8c8c8ff,         // SLIDER_INSIDE_COLOR
-    0xbcecffff,         // SLIDER_DEFAULT_COLOR
-    0xffffffff,         // SLIDER_HOVER_COLOR
-    0xddf5ffff,         // SLIDER_ACTIVE_COLOR
-    0x828282ff,         // SLIDERBAR_BORDER_COLOR
-    0xc8c8c8ff,         // SLIDERBAR_INSIDE_COLOR
-    0xbcecffff,         // SLIDERBAR_DEFAULT_COLOR
-    0xffffffff,         // SLIDERBAR_HOVER_COLOR
-    0xddf5ffff,         // SLIDERBAR_ACTIVE_COLOR
-    0x828282ff,         // SLIDERBAR_ZERO_LINE_COLOR
-    0x828282ff,         // PROGRESSBAR_BORDER_COLOR
-    0xc8c8c8ff,         // PROGRESSBAR_INSIDE_COLOR
-    0xbcecffff,         // PROGRESSBAR_PROGRESS_COLOR
-    2,                  // PROGRESSBAR_BORDER_WIDTH
-    0x828282ff,         // SPINNER_LABEL_BORDER_COLOR
-    0xc8c8c8ff,         // SPINNER_LABEL_INSIDE_COLOR
-    0x828282ff,         // SPINNER_DEFAULT_BUTTON_BORDER_COLOR
-    0xc8c8c8ff,         // SPINNER_DEFAULT_BUTTON_INSIDE_COLOR
-    0x000000ff,         // SPINNER_DEFAULT_SYMBOL_COLOR
-    0x000000ff,         // SPINNER_DEFAULT_TEXT_COLOR
-    0xc8c8c8ff,         // SPINNER_HOVER_BUTTON_BORDER_COLOR
-    0xffffffff,         // SPINNER_HOVER_BUTTON_INSIDE_COLOR
-    0x000000ff,         // SPINNER_HOVER_SYMBOL_COLOR
-    0x000000ff,         // SPINNER_HOVER_TEXT_COLOR
-    0x7bb0d6ff,         // SPINNER_PRESSED_BUTTON_BORDER_COLOR
-    0xbcecffff,         // SPINNER_PRESSED_BUTTON_INSIDE_COLOR
-    0x5f9aa7ff,         // SPINNER_PRESSED_SYMBOL_COLOR
-    0x000000ff,         // SPINNER_PRESSED_TEXT_COLOR
-    1,                  // COMBOBOX_PADDING
-    30,                 // COMBOBOX_BUTTON_WIDTH
-    20,                 // COMBOBOX_BUTTON_HEIGHT
-    1,                  // COMBOBOX_BORDER_WIDTH
-    0x828282ff,         // COMBOBOX_DEFAULT_BORDER_COLOR
-    0xc8c8c8ff,         // COMBOBOX_DEFAULT_INSIDE_COLOR
-    0x828282ff,         // COMBOBOX_DEFAULT_TEXT_COLOR
-    0x828282ff,         // COMBOBOX_DEFAULT_LIST_TEXT_COLOR
-    0xc8c8c8ff,         // COMBOBOX_HOVER_BORDER_COLOR
-    0xffffffff,         // COMBOBOX_HOVER_INSIDE_COLOR
-    0x828282ff,         // COMBOBOX_HOVER_TEXT_COLOR
-    0x828282ff,         // COMBOBOX_HOVER_LIST_TEXT_COLOR
-    0x7bb0d6ff,         // COMBOBOX_PRESSED_BORDER_COLOR
-    0xbcecffff,         // COMBOBOX_PRESSED_INSIDE_COLOR
-    0x5f9aa7ff,         // COMBOBOX_PRESSED_TEXT_COLOR
-    0x0078acff,         // COMBOBOX_PRESSED_LIST_BORDER_COLOR
-    0x66e7ffff,         // COMBOBOX_PRESSED_LIST_INSIDE_COLOR
-    0x0078acff,         // COMBOBOX_PRESSED_LIST_TEXT_COLOR
-    0x828282ff,         // CHECKBOX_DEFAULT_BORDER_COLOR
-    0xffffffff,         // CHECKBOX_DEFAULT_INSIDE_COLOR
-    0xc8c8c8ff,         // CHECKBOX_HOVER_BORDER_COLOR
-    0xffffffff,         // CHECKBOX_HOVER_INSIDE_COLOR
-    0x66e7ffff,         // CHECKBOX_CLICK_BORDER_COLOR
-    0xddf5ffff,         // CHECKBOX_CLICK_INSIDE_COLOR
-    0x7bb0d6ff,         // CHECKBOX_STATUS_ACTIVE_COLOR
-    4,                  // CHECKBOX_INSIDE_WIDTH
-    1,                  // TEXTBOX_BORDER_WIDTH
-    0x828282ff,         // TEXTBOX_BORDER_COLOR
-    0xf5f5f5ff,         // TEXTBOX_INSIDE_COLOR
-    0x000000ff,         // TEXTBOX_TEXT_COLOR
-    0x000000ff,         // TEXTBOX_LINE_COLOR
-    10                  // TEXTBOX_TEXT_FONTSIZE
-};
-
-//----------------------------------------------------------------------------------
-// Module specific Functions Declaration
-//----------------------------------------------------------------------------------
-static Color ColorMultiply(Color baseColor, float value);
-
-#if defined RAYGUI_STANDALONE
-static Color GetColor(int hexValue);   // Returns a Color struct from hexadecimal value
-static int GetHexValue(Color color);   // Returns hexadecimal value for a Color
-static bool CheckCollisionPointRec(Vector2 point, Rectangle rec);  // Check if point is inside rectangle
-static const char *FormatText(const char *text, ...);   // Formatting of text with variables to 'embed'
-
-// NOTE: raygui depend on some raylib input and drawing functions
-// TODO: Replace by your own functions
-static Vector2 GetMousePosition() { return (Vector2){ 0.0f, 0.0f }; }
-static int IsMouseButtonDown(int button) { return 0; }
-static int IsMouseButtonPressed(int button) { return 0; }
-static int IsMouseButtonReleased(int button) { return 0; }
-static int IsMouseButtonUp(int button) { return 0; }
-
-static int GetKeyPressed(void) { return 0; }    // NOTE: Only used by GuiTextBox()
-static int IsKeyDown(int key) { return 0; }     // NOTE: Only used by GuiSpinner()
-
-static int MeasureText(const char *text, int fontSize) { return 0; }
-static void DrawText(const char *text, int posX, int posY, int fontSize, Color color) { }
-static void DrawRectangleRec(Rectangle rec, Color color) { }
-static void DrawRectangle(int posX, int posY, int width, int height, Color color) { DrawRectangleRec((Rectangle){ posX, posY, width, height }, color); }
-#endif
-
-//----------------------------------------------------------------------------------
-// Module Functions Definition
-//----------------------------------------------------------------------------------
-
-// Label element, show text
-void GuiLabel(Rectangle bounds, const char *text)
-{
-    #define BLANK (Color){ 0, 0, 0, 0 } // Blank (Transparent)
-
-    GuiLabelEx(bounds, text, GetColor(style[LABEL_TEXT_COLOR]), BLANK, BLANK);
-}
-
-// Label element extended, configurable colors
-void GuiLabelEx(Rectangle bounds, const char *text, Color textColor, Color border, Color inner)
-{
-    // Update control
-    //--------------------------------------------------------------------
-    int textWidth = MeasureText(text, style[GLOBAL_TEXT_FONTSIZE]);
-    int textHeight = style[GLOBAL_TEXT_FONTSIZE];
-
-    if (bounds.width < textWidth) bounds.width = textWidth + style[LABEL_TEXT_PADDING];
-    if (bounds.height < textHeight) bounds.height = textHeight + style[LABEL_TEXT_PADDING]/2;
-    //--------------------------------------------------------------------
-    
-    // Draw control
-    //--------------------------------------------------------------------
-    DrawRectangleRec(bounds, border);
-    DrawRectangle(bounds.x + style[LABEL_BORDER_WIDTH], bounds.y + style[LABEL_BORDER_WIDTH], bounds.width - (2 * style[LABEL_BORDER_WIDTH]), bounds.height - (2 * style[LABEL_BORDER_WIDTH]), inner);
-    DrawText(text, bounds.x + ((bounds.width/2) - (textWidth/2)), bounds.y + ((bounds.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], textColor);
-    //--------------------------------------------------------------------
-}
-
-// Button element, returns true when clicked
-bool GuiButton(Rectangle bounds, const char *text)
-{
-    ButtonState buttonState = BUTTON_DEFAULT;
-    Vector2 mousePoint = GetMousePosition();
-    
-    int textWidth = MeasureText(text, style[GLOBAL_TEXT_FONTSIZE]);
-    int textHeight = style[GLOBAL_TEXT_FONTSIZE];
-    
-    // Update control
-    //--------------------------------------------------------------------
-    if (bounds.width < textWidth) bounds.width = textWidth + style[BUTTON_TEXT_PADDING];
-    if (bounds.height < textHeight) bounds.height = textHeight + style[BUTTON_TEXT_PADDING]/2;
-    
-    if (CheckCollisionPointRec(mousePoint, bounds))
-    {
-        if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) buttonState = BUTTON_PRESSED;
-        else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) buttonState = BUTTON_CLICKED;
-        else buttonState = BUTTON_HOVER;
-    }
-    //--------------------------------------------------------------------
-    
-    // Draw control
-    //--------------------------------------------------------------------
-    switch (buttonState)
-    {
-        case BUTTON_DEFAULT:
-        {
-            DrawRectangleRec(bounds, GetColor(style[BUTTON_DEFAULT_BORDER_COLOR]));
-            DrawRectangle((int)(bounds.x + style[BUTTON_BORDER_WIDTH]), (int)(bounds.y + style[BUTTON_BORDER_WIDTH]) , (int)(bounds.width - (2 * style[BUTTON_BORDER_WIDTH])), (int)(bounds.height - (2 * style[BUTTON_BORDER_WIDTH])), GetColor(style[BUTTON_DEFAULT_INSIDE_COLOR]));
-            DrawText(text, bounds.x + ((bounds.width/2) - (MeasureText(text, style[GLOBAL_TEXT_FONTSIZE])/2)), bounds.y + ((bounds.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[BUTTON_DEFAULT_TEXT_COLOR]));
-        } break;
-        case BUTTON_HOVER:
-        {
-            DrawRectangleRec(bounds, GetColor(style[BUTTON_HOVER_BORDER_COLOR]));
-            DrawRectangle((int)(bounds.x + style[BUTTON_BORDER_WIDTH]), (int)(bounds.y + style[BUTTON_BORDER_WIDTH]) , (int)(bounds.width - (2 * style[BUTTON_BORDER_WIDTH])), (int)(bounds.height - (2 * style[BUTTON_BORDER_WIDTH])), GetColor(style[BUTTON_HOVER_INSIDE_COLOR]));
-            DrawText(text, bounds.x + ((bounds.width/2) - (MeasureText(text, style[GLOBAL_TEXT_FONTSIZE])/2)), bounds.y + ((bounds.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[BUTTON_HOVER_TEXT_COLOR]));
-        } break;
-        case BUTTON_PRESSED:
-        {
-            DrawRectangleRec(bounds, GetColor(style[BUTTON_PRESSED_BORDER_COLOR]));
-            DrawRectangle((int)(bounds.x + style[BUTTON_BORDER_WIDTH]), (int)(bounds.y + style[BUTTON_BORDER_WIDTH]) , (int)(bounds.width - (2 * style[BUTTON_BORDER_WIDTH])), (int)(bounds.height - (2 * style[BUTTON_BORDER_WIDTH])), GetColor(style[BUTTON_PRESSED_INSIDE_COLOR]));
-            DrawText(text, bounds.x + ((bounds.width/2) - (MeasureText(text, style[GLOBAL_TEXT_FONTSIZE])/2)), bounds.y + ((bounds.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[BUTTON_PRESSED_TEXT_COLOR]));
-        } break;
-        case BUTTON_CLICKED:
-        {
-            DrawRectangleRec(bounds, GetColor(style[BUTTON_PRESSED_BORDER_COLOR]));
-            DrawRectangle((int)(bounds.x + style[BUTTON_BORDER_WIDTH]), (int)(bounds.y + style[BUTTON_BORDER_WIDTH]) , (int)(bounds.width - (2 * style[BUTTON_BORDER_WIDTH])), (int)(bounds.height - (2 * style[BUTTON_BORDER_WIDTH])), GetColor(style[BUTTON_PRESSED_INSIDE_COLOR]));
-        } break;
-        default: break;
-    }
-    //------------------------------------------------------------------
-    
-    if (buttonState == BUTTON_CLICKED) return true;
-    else return false;
-}
-
-// Toggle Button element, returns true when active
-bool GuiToggleButton(Rectangle bounds, const char *text, bool toggle)
-{
-    ToggleState toggleState = TOGGLE_UNACTIVE;
-    Rectangle toggleButton = bounds;
-    Vector2 mousePoint = GetMousePosition();
-    
-    int textWidth = MeasureText(text, style[GLOBAL_TEXT_FONTSIZE]);
-    int textHeight = style[GLOBAL_TEXT_FONTSIZE];
-    
-    // Update control
-    //--------------------------------------------------------------------   
-    if (toggleButton.width < textWidth) toggleButton.width = textWidth + style[TOGGLE_TEXT_PADDING];
-    if (toggleButton.height < textHeight) toggleButton.height = textHeight + style[TOGGLE_TEXT_PADDING]/2;
-    
-    if (toggle) toggleState = TOGGLE_ACTIVE;
-    else toggleState = TOGGLE_UNACTIVE;
-    
-    if (CheckCollisionPointRec(mousePoint, toggleButton))
-    {
-        if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) toggleState = TOGGLE_PRESSED;
-        else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON))
-        {
-            if (toggle)
-            {
-                toggle = false;
-                toggleState = TOGGLE_UNACTIVE;
-            }
-            else
-            {
-                toggle = true;
-                toggleState = TOGGLE_ACTIVE;
-            }
-        }
-        else toggleState = TOGGLE_HOVER;
-    }
-    //--------------------------------------------------------------------   
-    
-    // Draw control
-    //--------------------------------------------------------------------
-    switch (toggleState)
-    {
-        case TOGGLE_UNACTIVE:
-        {
-            DrawRectangleRec(toggleButton, GetColor(style[TOGGLE_DEFAULT_BORDER_COLOR]));
-            DrawRectangle((int)(toggleButton.x + style[TOGGLE_BORDER_WIDTH]), (int)(toggleButton.y + style[TOGGLE_BORDER_WIDTH]) , (int)(toggleButton.width - (2 * style[TOGGLE_BORDER_WIDTH])), (int)(toggleButton.height - (2 * style[TOGGLE_BORDER_WIDTH])), GetColor(style[TOGGLE_DEFAULT_INSIDE_COLOR]));
-            DrawText(text, toggleButton.x + ((toggleButton.width/2) - (MeasureText(text, style[GLOBAL_TEXT_FONTSIZE])/2)), toggleButton.y + ((toggleButton.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[TOGGLE_DEFAULT_TEXT_COLOR]));
-        } break;
-        case TOGGLE_HOVER:
-        {
-            DrawRectangleRec(toggleButton, GetColor(style[TOGGLE_HOVER_BORDER_COLOR]));
-            DrawRectangle((int)(toggleButton.x + style[TOGGLE_BORDER_WIDTH]), (int)(toggleButton.y + style[TOGGLE_BORDER_WIDTH]) , (int)(toggleButton.width - (2 * style[TOGGLE_BORDER_WIDTH])), (int)(toggleButton.height - (2 * style[TOGGLE_BORDER_WIDTH])), GetColor(style[TOGGLE_HOVER_INSIDE_COLOR]));
-            DrawText(text, toggleButton.x + ((toggleButton.width/2) - (MeasureText(text, style[GLOBAL_TEXT_FONTSIZE])/2)), toggleButton.y + ((toggleButton.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[TOGGLE_HOVER_TEXT_COLOR]));
-        } break;
-        case TOGGLE_PRESSED:
-        {
-            DrawRectangleRec(toggleButton, GetColor(style[TOGGLE_PRESSED_BORDER_COLOR]));
-            DrawRectangle((int)(toggleButton.x + style[TOGGLE_BORDER_WIDTH]), (int)(toggleButton.y + style[TOGGLE_BORDER_WIDTH]) , (int)(toggleButton.width - (2 * style[TOGGLE_BORDER_WIDTH])), (int)(toggleButton.height - (2 * style[TOGGLE_BORDER_WIDTH])), GetColor(style[TOGGLE_PRESSED_INSIDE_COLOR]));
-            DrawText(text, toggleButton.x + ((toggleButton.width/2) - (MeasureText(text, style[GLOBAL_TEXT_FONTSIZE])/2)), toggleButton.y + ((toggleButton.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[TOGGLE_PRESSED_TEXT_COLOR]));
-        } break;
-        case TOGGLE_ACTIVE:
-        {
-            DrawRectangleRec(toggleButton, GetColor(style[TOGGLE_ACTIVE_BORDER_COLOR]));
-            DrawRectangle((int)(toggleButton.x + style[TOGGLE_BORDER_WIDTH]), (int)(toggleButton.y + style[TOGGLE_BORDER_WIDTH]) , (int)(toggleButton.width - (2 * style[TOGGLE_BORDER_WIDTH])), (int)(toggleButton.height - (2 * style[TOGGLE_BORDER_WIDTH])), GetColor(style[TOGGLE_ACTIVE_INSIDE_COLOR]));
-            DrawText(text, toggleButton.x + ((toggleButton.width/2) - (MeasureText(text, style[GLOBAL_TEXT_FONTSIZE])/2)), toggleButton.y + ((toggleButton.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[TOGGLE_ACTIVE_TEXT_COLOR]));
-        } break;
-        default: break;
-    }
-    //-------------------------------------------------------------------- 
-    
-    return toggle;
-}
-
-// Toggle Group element, returns toggled button index
-int GuiToggleGroup(Rectangle bounds, int toggleNum, char **toggleText, int toggleActive)
-{ 
-    for (int i = 0; i < toggleNum; i++)
-    {
-        if (i == toggleActive) GuiToggleButton((Rectangle){bounds.x + i*(bounds.width + style[TOGGLEGROUP_PADDING]),bounds.y,bounds.width,bounds.height}, toggleText[i], true);      
-        else if (GuiToggleButton((Rectangle){bounds.x + i*(bounds.width + style[TOGGLEGROUP_PADDING]),bounds.y,bounds.width,bounds.height}, toggleText[i], false) == true) toggleActive = i;
-    }
-    
-    return toggleActive;
-}
-
-// Combo Box element, returns selected item index
-int GuiComboBox(Rectangle bounds, int comboNum, char **comboText, int comboActive)
-{
-    ComboBoxState comboBoxState = COMBOBOX_UNACTIVE;
-    Rectangle comboBoxButton = bounds;
-    Rectangle click = { bounds.x + bounds.width + style[COMBOBOX_PADDING], bounds.y, style[COMBOBOX_BUTTON_WIDTH], style[COMBOBOX_BUTTON_HEIGHT] };
-    Vector2 mousePoint = GetMousePosition();
-
-    int textHeight = style[GLOBAL_TEXT_FONTSIZE];
-     
-    for (int i = 0; i < comboNum; i++)
-    {
-        if (i == comboActive)
-        {
-		    // Update control
-    		//-------------------------------------------------------------------- 
-            int textWidth = MeasureText(comboText[i], style[GLOBAL_TEXT_FONTSIZE]);
-                
-            if (comboBoxButton.width < textWidth) comboBoxButton.width = textWidth + style[TOGGLE_TEXT_PADDING];
-            if (comboBoxButton.height < textHeight) comboBoxButton.height = textHeight + style[TOGGLE_TEXT_PADDING]/2;
-            
-            if (CheckCollisionPointRec(mousePoint, comboBoxButton) || CheckCollisionPointRec(mousePoint, click))
-            {
-                if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) comboBoxState = COMBOBOX_PRESSED;
-                else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) comboBoxState = COMBOBOX_ACTIVE;
-                else comboBoxState = COMBOBOX_HOVER;
-            }
-    		//--------------------------------------------------------------------   
-            
-            // Draw control
-            //--------------------------------------------------------------------
-            switch (comboBoxState)
-            {
-                case COMBOBOX_UNACTIVE:
-                {
-                    DrawRectangleRec(comboBoxButton, GetColor(style[COMBOBOX_DEFAULT_BORDER_COLOR]));
-                    DrawRectangle((int)(comboBoxButton.x + style[COMBOBOX_BORDER_WIDTH]), (int)(comboBoxButton.y + style[COMBOBOX_BORDER_WIDTH]), (int)(comboBoxButton.width - (2 * style[COMBOBOX_BORDER_WIDTH])), (int)(comboBoxButton.height - (2*style[COMBOBOX_BORDER_WIDTH])), GetColor(style[COMBOBOX_DEFAULT_INSIDE_COLOR]));
-                
-                    DrawRectangleRec(click, GetColor(style[COMBOBOX_DEFAULT_BORDER_COLOR]));
-                    DrawRectangle((int)(click.x + style[COMBOBOX_BORDER_WIDTH]), (int)(click.y + style[COMBOBOX_BORDER_WIDTH]) , (int)(click.width - (2*style[COMBOBOX_BORDER_WIDTH])), (int)(click.height - (2*style[COMBOBOX_BORDER_WIDTH])), GetColor(style[COMBOBOX_DEFAULT_INSIDE_COLOR]));
-                    DrawText(FormatText("%i/%i", comboActive + 1, comboNum), click.x + ((click.width/2) - (MeasureText(FormatText("%i/%i", comboActive + 1, comboNum), style[GLOBAL_TEXT_FONTSIZE])/2)), click.y + ((click.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[COMBOBOX_DEFAULT_LIST_TEXT_COLOR]));
-                    DrawText(comboText[i], comboBoxButton.x + ((comboBoxButton.width/2) - (MeasureText(comboText[i], style[GLOBAL_TEXT_FONTSIZE])/2)), comboBoxButton.y + ((comboBoxButton.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[COMBOBOX_DEFAULT_TEXT_COLOR]));
-                } break;
-                case COMBOBOX_HOVER:
-                {
-                    DrawRectangleRec(comboBoxButton, GetColor(style[COMBOBOX_HOVER_BORDER_COLOR]));
-                    DrawRectangle((int)(comboBoxButton.x + style[COMBOBOX_BORDER_WIDTH]), (int)(comboBoxButton.y + style[COMBOBOX_BORDER_WIDTH]), (int)(comboBoxButton.width - (2 * style[COMBOBOX_BORDER_WIDTH])), (int)(comboBoxButton.height - (2*style[COMBOBOX_BORDER_WIDTH])), GetColor(style[COMBOBOX_HOVER_INSIDE_COLOR]));
-                    
-                    DrawRectangleRec(click, GetColor(style[COMBOBOX_HOVER_BORDER_COLOR]));
-                    DrawRectangle((int)(click.x + style[COMBOBOX_BORDER_WIDTH]), (int)(click.y + style[COMBOBOX_BORDER_WIDTH]) , (int)(click.width - (2*style[COMBOBOX_BORDER_WIDTH])), (int)(click.height - (2*style[COMBOBOX_BORDER_WIDTH])), GetColor(style[COMBOBOX_HOVER_INSIDE_COLOR]));
-                    DrawText(FormatText("%i/%i", comboActive + 1, comboNum), click.x + ((click.width/2) - (MeasureText(FormatText("%i/%i", comboActive + 1, comboNum), style[GLOBAL_TEXT_FONTSIZE])/2)), click.y + ((click.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[COMBOBOX_HOVER_LIST_TEXT_COLOR]));
-                    DrawText(comboText[i], comboBoxButton.x + ((comboBoxButton.width/2) - (MeasureText(comboText[i], style[GLOBAL_TEXT_FONTSIZE])/2)), comboBoxButton.y + ((comboBoxButton.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[COMBOBOX_HOVER_TEXT_COLOR]));
-                } break;
-                case COMBOBOX_PRESSED:
-                {
-                    DrawRectangleRec(comboBoxButton, GetColor(style[COMBOBOX_PRESSED_BORDER_COLOR]));
-                    DrawRectangle((int)(comboBoxButton.x + style[COMBOBOX_BORDER_WIDTH]), (int)(comboBoxButton.y + style[COMBOBOX_BORDER_WIDTH]), (int)(comboBoxButton.width - (2 * style[COMBOBOX_BORDER_WIDTH])), (int)(comboBoxButton.height - (2*style[COMBOBOX_BORDER_WIDTH])), GetColor(style[COMBOBOX_PRESSED_INSIDE_COLOR]));
-                
-                    DrawRectangleRec(click, GetColor(style[COMBOBOX_PRESSED_LIST_BORDER_COLOR]));
-                    DrawRectangle((int)(click.x + style[COMBOBOX_BORDER_WIDTH]), (int)(click.y + style[COMBOBOX_BORDER_WIDTH]) , (int)(click.width - (2*style[COMBOBOX_BORDER_WIDTH])), (int)(click.height - (2*style[COMBOBOX_BORDER_WIDTH])), GetColor(style[COMBOBOX_PRESSED_LIST_INSIDE_COLOR]));
-                    DrawText(FormatText("%i/%i", comboActive + 1, comboNum), click.x + ((click.width/2) - (MeasureText(FormatText("%i/%i", comboActive + 1, comboNum), style[GLOBAL_TEXT_FONTSIZE])/2)), click.y + ((click.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[COMBOBOX_PRESSED_LIST_TEXT_COLOR]));
-                    DrawText(comboText[i], comboBoxButton.x + ((comboBoxButton.width/2) - (MeasureText(comboText[i], style[GLOBAL_TEXT_FONTSIZE])/2)), comboBoxButton.y + ((comboBoxButton.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[COMBOBOX_PRESSED_TEXT_COLOR]));
-                } break;
-                case COMBOBOX_ACTIVE:
-                {
-                    DrawRectangleRec(comboBoxButton, GetColor(style[COMBOBOX_PRESSED_BORDER_COLOR]));
-                    DrawRectangle((int)(comboBoxButton.x + style[COMBOBOX_BORDER_WIDTH]), (int)(comboBoxButton.y + style[COMBOBOX_BORDER_WIDTH]), (int)(comboBoxButton.width - (2 * style[COMBOBOX_BORDER_WIDTH])), (int)(comboBoxButton.height - (2*style[COMBOBOX_BORDER_WIDTH])), GetColor(style[COMBOBOX_PRESSED_INSIDE_COLOR]));
-                
-                    DrawRectangleRec(click, GetColor(style[COMBOBOX_PRESSED_LIST_BORDER_COLOR]));
-                    DrawRectangle((int)(click.x + style[COMBOBOX_BORDER_WIDTH]), (int)(click.y + style[COMBOBOX_BORDER_WIDTH]) , (int)(click.width - (2*style[COMBOBOX_BORDER_WIDTH])), (int)(click.height - (2*style[COMBOBOX_BORDER_WIDTH])), GetColor(style[COMBOBOX_PRESSED_LIST_INSIDE_COLOR]));
-                    DrawText(FormatText("%i/%i", comboActive + 1, comboNum), click.x + ((click.width/2) - (MeasureText(FormatText("%i/%i", comboActive + 1, comboNum), style[GLOBAL_TEXT_FONTSIZE])/2)), click.y + ((click.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[COMBOBOX_PRESSED_LIST_TEXT_COLOR]));
-                    DrawText(comboText[i], comboBoxButton.x + ((comboBoxButton.width/2) - (MeasureText(comboText[i], style[GLOBAL_TEXT_FONTSIZE])/2)), comboBoxButton.y + ((comboBoxButton.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[COMBOBOX_PRESSED_TEXT_COLOR]));
-                } break;
-                default: break;
-            }
-            
-            //DrawText(comboText[i], comboBoxButton.x + ((comboBoxButton.width/2) - (MeasureText(comboText[i], style[]globalTextFontSize)/2)), comboBoxButton.y + ((comboBoxButton.height/2) - (style[]globalTextFontSize/2)), style[]globalTextFontSize, COMBOBOX_PRESSED_TEXT_COLOR);            
-            //-------------------------------------------------------------------- 
-        }
-    }
-    
-    if (CheckCollisionPointRec(GetMousePosition(), bounds) || CheckCollisionPointRec(GetMousePosition(), click))
-    {
-        if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) 
-        {
-           comboActive += 1; 
-           if(comboActive >= comboNum) comboActive = 0;
-        }
-    } 
-
-    return comboActive;
-}
-
-// Check Box element, returns true when active
-bool GuiCheckBox(Rectangle checkBoxBounds, const char *text, bool checked)
-{
-    CheckBoxState checkBoxState = CHECKBOX_STATUS;
-    Vector2 mousePoint = GetMousePosition();
-    
-    // Update control
-    //-------------------------------------------------------------------- 
-    if (CheckCollisionPointRec(mousePoint, checkBoxBounds))
-    {
-        if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) checkBoxState = CHECKBOX_PRESSED;
-        else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON))
-        {
-            checkBoxState = CHECKBOX_STATUS;
-            checked = !checked;
-        } 
-        else checkBoxState = CHECKBOX_HOVER;
-    }
-    //-------------------------------------------------------------------- 
-    
-    // Draw control
-    //--------------------------------------------------------------------
-    switch (checkBoxState)
-    {
-        case CHECKBOX_HOVER:
-        {
-            DrawRectangleRec(checkBoxBounds, GetColor(style[CHECKBOX_HOVER_BORDER_COLOR]));
-            DrawRectangle((int)(checkBoxBounds.x + style[TOGGLE_BORDER_WIDTH]), (int)(checkBoxBounds.y + style[TOGGLE_BORDER_WIDTH]), (int)(checkBoxBounds.width - (2*style[TOGGLE_BORDER_WIDTH])), (int)(checkBoxBounds.height - (2*style[TOGGLE_BORDER_WIDTH])), GetColor(style[CHECKBOX_HOVER_INSIDE_COLOR]));        
-        } break;
-        case CHECKBOX_STATUS:
-        { 
-            DrawRectangleRec(checkBoxBounds, GetColor(style[CHECKBOX_DEFAULT_BORDER_COLOR]));
-            DrawRectangle((int)(checkBoxBounds.x + style[TOGGLE_BORDER_WIDTH]), (int)(checkBoxBounds.y + style[TOGGLE_BORDER_WIDTH]), (int)(checkBoxBounds.width - (2*style[TOGGLE_BORDER_WIDTH])), (int)(checkBoxBounds.height - (2*style[TOGGLE_BORDER_WIDTH])), GetColor(style[CHECKBOX_DEFAULT_INSIDE_COLOR]));
-        } break; 
-        case CHECKBOX_PRESSED:
-        {
-            DrawRectangleRec(checkBoxBounds, GetColor(style[CHECKBOX_CLICK_BORDER_COLOR]));
-            DrawRectangle((int)(checkBoxBounds.x + style[TOGGLE_BORDER_WIDTH]), (int)(checkBoxBounds.y + style[TOGGLE_BORDER_WIDTH]), (int)(checkBoxBounds.width - (2*style[TOGGLE_BORDER_WIDTH])), (int)(checkBoxBounds.height - (2*style[TOGGLE_BORDER_WIDTH])), GetColor(style[CHECKBOX_CLICK_INSIDE_COLOR]));
-        } break;
-        default: break;               
-    }
-    
-    if (text != NULL) DrawText(text, checkBoxBounds.x + checkBoxBounds.width + 2, checkBoxBounds.y + ((checkBoxBounds.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2) + 1), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[LABEL_TEXT_COLOR]));
-
-    if (checked)
-    {
-        DrawRectangle((int)(checkBoxBounds.x + style[CHECKBOX_INSIDE_WIDTH]), (int)(checkBoxBounds.y + style[CHECKBOX_INSIDE_WIDTH]), (int)(checkBoxBounds.width - (2*style[CHECKBOX_INSIDE_WIDTH])), (int)(checkBoxBounds.height - (2*style[CHECKBOX_INSIDE_WIDTH])), GetColor(style[CHECKBOX_STATUS_ACTIVE_COLOR]));
-    }
-    //--------------------------------------------------------------------
-    
-    return checked;
-}
-
-// Slider element, returns selected value
-float GuiSlider(Rectangle bounds, float value, float minValue, float maxValue)
-{
-    SliderState sliderState = SLIDER_DEFAULT;
-    float buttonTravelDistance = 0;
-    float sliderPos = 0;
-    Vector2 mousePoint = GetMousePosition();
-    
-    // Update control
-    //--------------------------------------------------------------------     
-    if (value < minValue) value = minValue;
-    else if (value >= maxValue) value = maxValue;
-    
-    sliderPos = (value - minValue)/(maxValue - minValue);
-    
-    Rectangle sliderButton;
-    sliderButton.width = ((int)(bounds.width - (2 * style[SLIDER_BUTTON_BORDER_WIDTH]))/10 - 8);
-    sliderButton.height =((int)(bounds.height - ( 2 * style[SLIDER_BORDER_WIDTH] + 2 * style[SLIDER_BUTTON_BORDER_WIDTH])));
-    
-    float sliderButtonMinPos = bounds.x + style[SLIDER_BORDER_WIDTH] + style[SLIDER_BUTTON_BORDER_WIDTH];
-    float sliderButtonMaxPos = bounds.x + bounds.width - (style[SLIDER_BORDER_WIDTH] + style[SLIDER_BUTTON_BORDER_WIDTH] + sliderButton.width);
-    
-    buttonTravelDistance = sliderButtonMaxPos - sliderButtonMinPos;
-    
-    sliderButton.x = ((int)(bounds.x + style[SLIDER_BORDER_WIDTH] + style[SLIDER_BUTTON_BORDER_WIDTH]) + (sliderPos * buttonTravelDistance));
-    sliderButton.y = ((int)(bounds.y + style[SLIDER_BORDER_WIDTH] + style[SLIDER_BUTTON_BORDER_WIDTH]));
-    
-    if (CheckCollisionPointRec(mousePoint, bounds))
-    {
-        sliderState = SLIDER_HOVER;
-        
-        if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) sliderState = SLIDER_ACTIVE;
-        
-        if ((sliderState == SLIDER_ACTIVE) && (IsMouseButtonDown(MOUSE_LEFT_BUTTON)))
-        {
-            sliderButton.x = mousePoint.x - sliderButton.width / 2;
-            
-            if (sliderButton.x <= sliderButtonMinPos) sliderButton.x = sliderButtonMinPos;
-            else if (sliderButton.x >= sliderButtonMaxPos) sliderButton.x = sliderButtonMaxPos;
-            
-            sliderPos = (sliderButton.x - sliderButtonMinPos) / buttonTravelDistance;
-        }   
-    }
-    else sliderState = SLIDER_DEFAULT;
-    //-------------------------------------------------------------------- 
-    
-    // Draw control
-    //--------------------------------------------------------------------
-    DrawRectangleRec(bounds, GetColor(style[SLIDER_BORDER_COLOR]));
-    DrawRectangle((int)(bounds.x + style[SLIDER_BORDER_WIDTH]), (int)(bounds.y + style[SLIDER_BORDER_WIDTH]), (int)(bounds.width - (2*style[SLIDER_BORDER_WIDTH])), (int)(bounds.height - (2*style[SLIDER_BORDER_WIDTH])), GetColor(style[SLIDER_INSIDE_COLOR]));
-    
-    switch (sliderState)
-    {
-        case SLIDER_DEFAULT: DrawRectangleRec(sliderButton, GetColor(style[SLIDER_DEFAULT_COLOR])); break;
-        case SLIDER_HOVER: DrawRectangleRec(sliderButton, GetColor(style[SLIDER_HOVER_COLOR])); break;
-        case SLIDER_ACTIVE: DrawRectangleRec(sliderButton, GetColor(style[SLIDER_ACTIVE_COLOR])); break;
-        default: break;
-    } 
-    //--------------------------------------------------------------------
-    
-    return minValue + (maxValue - minValue)*sliderPos;
-}
-
-// Slider Bar element, returns selected value
-float GuiSliderBar(Rectangle bounds, float value, float minValue, float maxValue)
-{
-    SliderState sliderState = SLIDER_DEFAULT;
-    Vector2 mousePoint = GetMousePosition();
-    float fixedValue;
-    float fixedMinValue;
-    
-    fixedValue = value - minValue;
-    maxValue = maxValue - minValue;
-    fixedMinValue = 0;
-    
-    // Update control
-    //-------------------------------------------------------------------- 
-    if (fixedValue <= fixedMinValue) fixedValue = fixedMinValue;
-    else if (fixedValue >= maxValue) fixedValue = maxValue;
- 
-    Rectangle sliderBar;
-
-    sliderBar.x = bounds.x + style[SLIDER_BORDER_WIDTH];
-    sliderBar.y = bounds.y + style[SLIDER_BORDER_WIDTH];
-    sliderBar.width = ((fixedValue*((float)bounds.width - 2*style[SLIDER_BORDER_WIDTH]))/(maxValue - fixedMinValue));
-    sliderBar.height = bounds.height - 2*style[SLIDER_BORDER_WIDTH];
-
-    if (CheckCollisionPointRec(mousePoint, bounds))
-    {
-        sliderState = SLIDER_HOVER;
-        
-        if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) 
-        {
-            sliderState = SLIDER_ACTIVE;
-            
-            sliderBar.width = (mousePoint.x - bounds.x - style[SLIDER_BORDER_WIDTH]);
-            
-            if (mousePoint.x <= (bounds.x + style[SLIDER_BORDER_WIDTH])) sliderBar.width = 0;
-            else if (mousePoint.x >= (bounds.x + bounds.width - style[SLIDER_BORDER_WIDTH])) sliderBar.width = bounds.width - 2*style[SLIDER_BORDER_WIDTH];
-        }
-    }
-    else sliderState = SLIDER_DEFAULT;
-
-    fixedValue = ((float)sliderBar.width*(maxValue - fixedMinValue))/((float)bounds.width - 2*style[SLIDER_BORDER_WIDTH]);
-    //-------------------------------------------------------------------- 
-    
-    // Draw control
-    //--------------------------------------------------------------------
-    DrawRectangleRec(bounds, GetColor(style[SLIDERBAR_BORDER_COLOR]));
-    DrawRectangle((int)(bounds.x + style[SLIDER_BORDER_WIDTH]), (int)(bounds.y + style[SLIDER_BORDER_WIDTH]) , (int)(bounds.width - (2*style[SLIDER_BORDER_WIDTH])), (int)(bounds.height - (2*style[SLIDER_BORDER_WIDTH])), GetColor(style[SLIDERBAR_INSIDE_COLOR]));
-    
-    switch (sliderState)
-    {
-        case SLIDER_DEFAULT: DrawRectangleRec(sliderBar, GetColor(style[SLIDERBAR_DEFAULT_COLOR])); break;
-        case SLIDER_HOVER: DrawRectangleRec(sliderBar, GetColor(style[SLIDERBAR_HOVER_COLOR])); break;
-        case SLIDER_ACTIVE: DrawRectangleRec(sliderBar, GetColor(style[SLIDERBAR_ACTIVE_COLOR])); break;
-        default: break;
-    }
-    
-    if (minValue < 0 && maxValue > 0) DrawRectangle((bounds.x + style[SLIDER_BORDER_WIDTH]) - (minValue * ((bounds.width - (style[SLIDER_BORDER_WIDTH]*2))/maxValue)), sliderBar.y, 1, sliderBar.height, GetColor(style[SLIDERBAR_ZERO_LINE_COLOR]));
-    //--------------------------------------------------------------------
-
-    return fixedValue + minValue;
-}
-
-// Progress Bar element, shows current progress value
-void GuiProgressBar(Rectangle bounds, float value)
-{
-    if (value > 1.0f) value = 1.0f;
-    else if (value < 0.0f) value = 0.0f;
-
-    Rectangle progressBar = { bounds.x + style[PROGRESSBAR_BORDER_WIDTH], bounds.y + style[PROGRESSBAR_BORDER_WIDTH], bounds.width - (style[PROGRESSBAR_BORDER_WIDTH] * 2), bounds.height - (style[PROGRESSBAR_BORDER_WIDTH] * 2)};
-    Rectangle progressValue = { bounds.x + style[PROGRESSBAR_BORDER_WIDTH], bounds.y + style[PROGRESSBAR_BORDER_WIDTH], value * (bounds.width - (style[PROGRESSBAR_BORDER_WIDTH] * 2)), bounds.height - (style[PROGRESSBAR_BORDER_WIDTH] * 2)};
-
-    // Draw control
-    //--------------------------------------------------------------------
-    DrawRectangleRec(bounds, GetColor(style[PROGRESSBAR_BORDER_COLOR]));
-    DrawRectangleRec(progressBar, GetColor(style[PROGRESSBAR_INSIDE_COLOR]));
-    DrawRectangleRec(progressValue, GetColor(style[PROGRESSBAR_PROGRESS_COLOR]));
-    //--------------------------------------------------------------------
-}
-
-// Spinner element, returns selected value
-// NOTE: Requires static variables: framesCounter, valueSpeed - ERROR!
-int GuiSpinner(Rectangle bounds, int value, int minValue, int maxValue)
-{
-    SpinnerState spinnerState = SPINNER_DEFAULT;
-    Rectangle labelBoxBound = { bounds.x + bounds.width/4 + 1, bounds.y, bounds.width/2, bounds.height };
-    Rectangle leftButtonBound = { bounds.x, bounds.y, bounds.width/4, bounds.height };
-    Rectangle rightButtonBound = { bounds.x + bounds.width - bounds.width/4 + 1, bounds.y, bounds.width/4, bounds.height };
-    Vector2 mousePoint = GetMousePosition();
-
-    int textWidth = MeasureText(FormatText("%i", value), style[GLOBAL_TEXT_FONTSIZE]);
-    //int textHeight = style[GLOBAL_TEXT_FONTSIZE];     // Unused variable
-    
-    int buttonSide = 0;
-    
-    static int framesCounter = 0;
-    static bool valueSpeed = false;;
-    
-    //if (comboBoxButton.width < textWidth) comboBoxButton.width = textWidth + style[TOGGLE_TEXT_PADDING];
-    //if (comboBoxButton.height < textHeight) comboBoxButton.height = textHeight + style[TOGGLE_TEXT_PADDING]/2;
-    
-    // Update control
-    //-------------------------------------------------------------------- 
-    if (CheckCollisionPointRec(mousePoint, leftButtonBound) || CheckCollisionPointRec(mousePoint, rightButtonBound) || CheckCollisionPointRec(mousePoint, labelBoxBound))
-    {
-        if (IsKeyDown(KEY_LEFT))
-        {
-            spinnerState = SPINNER_PRESSED;
-            buttonSide = 1;
-            
-            if (value > minValue) value -= 1;
-        }
-        else if (IsKeyDown(KEY_RIGHT))
-        {
-            spinnerState = SPINNER_PRESSED;
-            buttonSide = 2;
-            
-            if (value < maxValue) value += 1;
-        }
-    }
-    
-    if (CheckCollisionPointRec(mousePoint, leftButtonBound))
-    {
-       buttonSide = 1;
-       spinnerState = SPINNER_HOVER;
-       
-       if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
-       {
-            if (!valueSpeed) 
-            {
-                if (value > minValue) value--;
-                valueSpeed = true;
-            }
-            else framesCounter++;
-            
-            spinnerState = SPINNER_PRESSED;
-            
-            if (value > minValue) 
-            {
-                if (framesCounter >= 30) value -= 1;
-            }
-       }
-    }
-    else if (CheckCollisionPointRec(mousePoint, rightButtonBound))
-    {
-        buttonSide = 2;
-        spinnerState = SPINNER_HOVER;
-        
-        if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) 
-       {
-            if (!valueSpeed) 
-            {
-                if (value < maxValue) value++;
-                valueSpeed = true;
-            }
-            else framesCounter++;
-            
-            spinnerState = SPINNER_PRESSED;
-            
-            if (value < maxValue) 
-            {
-                if (framesCounter >= 30) value += 1;
-            }
-       }
-    }
-    else if (!CheckCollisionPointRec(mousePoint, labelBoxBound)) buttonSide = 0;
-    
-    if (IsMouseButtonUp(MOUSE_LEFT_BUTTON))
-    {
-        valueSpeed = false;
-        framesCounter = 0;
-    }
-    //-------------------------------------------------------------------- 
-    
-    // Draw control
-    //--------------------------------------------------------------------
-    switch (spinnerState)
-    {
-        case SPINNER_DEFAULT:
-        {
-            DrawRectangleRec(leftButtonBound, GetColor(style[SPINNER_DEFAULT_BUTTON_BORDER_COLOR]));
-            DrawRectangle(leftButtonBound.x + 2, leftButtonBound.y + 2, leftButtonBound.width - 4, leftButtonBound.height - 4, GetColor(style[SPINNER_DEFAULT_BUTTON_INSIDE_COLOR]));
-            
-            DrawRectangleRec(rightButtonBound, GetColor(style[SPINNER_DEFAULT_BUTTON_BORDER_COLOR]));
-            DrawRectangle(rightButtonBound.x + 2, rightButtonBound.y + 2, rightButtonBound.width - 4, rightButtonBound.height - 4, GetColor(style[SPINNER_DEFAULT_BUTTON_INSIDE_COLOR]));
-            
-            DrawText(FormatText("-"), leftButtonBound.x + (leftButtonBound.width/2 - (MeasureText(FormatText("+"), style[GLOBAL_TEXT_FONTSIZE]))/2), leftButtonBound.y + (leftButtonBound.height/2 - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_DEFAULT_SYMBOL_COLOR])); 
-            DrawText(FormatText("+"), rightButtonBound.x + (rightButtonBound.width/2 - (MeasureText(FormatText("-"), style[GLOBAL_TEXT_FONTSIZE]))/2), rightButtonBound.y + (rightButtonBound.height/2 - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_DEFAULT_SYMBOL_COLOR])); 
-            
-            DrawRectangleRec(labelBoxBound, GetColor(style[SPINNER_LABEL_BORDER_COLOR]));
-            DrawRectangle(labelBoxBound.x + 1, labelBoxBound.y + 1, labelBoxBound.width - 2, labelBoxBound.height - 2, GetColor(style[SPINNER_LABEL_INSIDE_COLOR]));
-            
-            DrawText(FormatText("%i", value), labelBoxBound.x + (labelBoxBound.width/2 - textWidth/2), labelBoxBound.y + (labelBoxBound.height/2 - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_DEFAULT_TEXT_COLOR]));
-        } break;
-        case SPINNER_HOVER:
-        {
-            if (buttonSide == 1)
-            {
-                DrawRectangleRec(leftButtonBound, GetColor(style[SPINNER_HOVER_BUTTON_BORDER_COLOR]));
-                DrawRectangle(leftButtonBound.x + 2, leftButtonBound.y + 2, leftButtonBound.width - 4, leftButtonBound.height - 4, GetColor(style[SPINNER_HOVER_BUTTON_INSIDE_COLOR]));
-                
-                DrawRectangleRec(rightButtonBound, GetColor(style[SPINNER_DEFAULT_BUTTON_BORDER_COLOR]));
-                DrawRectangle(rightButtonBound.x + 2, rightButtonBound.y + 2, rightButtonBound.width - 4, rightButtonBound.height - 4, GetColor(style[SPINNER_DEFAULT_BUTTON_INSIDE_COLOR]));
-                
-                DrawText(FormatText("-"), leftButtonBound.x + (leftButtonBound.width/2 - (MeasureText(FormatText("+"), style[GLOBAL_TEXT_FONTSIZE]))/2), leftButtonBound.y + (leftButtonBound.height/2 - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_HOVER_SYMBOL_COLOR])); 
-                DrawText(FormatText("+"), rightButtonBound.x + (rightButtonBound.width/2 - (MeasureText(FormatText("-"), style[GLOBAL_TEXT_FONTSIZE]))/2), rightButtonBound.y + (rightButtonBound.height/2 - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_DEFAULT_SYMBOL_COLOR])); 
-            }                
-            else if (buttonSide == 2)
-            {
-                DrawRectangleRec(leftButtonBound, GetColor(style[SPINNER_DEFAULT_BUTTON_BORDER_COLOR]));
-                DrawRectangle(leftButtonBound.x + 2, leftButtonBound.y + 2, leftButtonBound.width - 4, leftButtonBound.height - 4, GetColor(style[SPINNER_DEFAULT_BUTTON_INSIDE_COLOR]));
-                
-                DrawRectangleRec(rightButtonBound, GetColor(style[SPINNER_HOVER_BUTTON_BORDER_COLOR]));
-                DrawRectangle(rightButtonBound.x + 2, rightButtonBound.y + 2, rightButtonBound.width - 4, rightButtonBound.height - 4, GetColor(style[SPINNER_HOVER_BUTTON_INSIDE_COLOR]));
-                
-                DrawText(FormatText("-"), leftButtonBound.x + (leftButtonBound.width/2 - (MeasureText(FormatText("+"), style[GLOBAL_TEXT_FONTSIZE]))/2), leftButtonBound.y + (leftButtonBound.height/2 - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_DEFAULT_SYMBOL_COLOR])); 
-                DrawText(FormatText("+"), rightButtonBound.x + (rightButtonBound.width/2 - (MeasureText(FormatText("-"), style[GLOBAL_TEXT_FONTSIZE]))/2), rightButtonBound.y + (rightButtonBound.height/2 - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_HOVER_SYMBOL_COLOR])); 
-            }
-            
-            DrawRectangleRec(labelBoxBound, GetColor(style[SPINNER_LABEL_BORDER_COLOR]));
-            DrawRectangle(labelBoxBound.x + 1, labelBoxBound.y + 1, labelBoxBound.width - 2, labelBoxBound.height - 2, GetColor(style[SPINNER_LABEL_INSIDE_COLOR]));
-            
-            DrawText(FormatText("%i", value), labelBoxBound.x + (labelBoxBound.width/2 - textWidth/2), labelBoxBound.y + (labelBoxBound.height/2 - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_HOVER_TEXT_COLOR]));  
-        } break;
-        case SPINNER_PRESSED:
-        {
-            if (buttonSide == 1)
-            {
-                DrawRectangleRec(leftButtonBound, GetColor(style[SPINNER_PRESSED_BUTTON_BORDER_COLOR]));
-                DrawRectangle(leftButtonBound.x + 2, leftButtonBound.y + 2, leftButtonBound.width - 4, leftButtonBound.height - 4, GetColor(style[SPINNER_PRESSED_BUTTON_INSIDE_COLOR]));
-                
-                DrawRectangleRec(rightButtonBound, GetColor(style[SPINNER_DEFAULT_BUTTON_BORDER_COLOR]));
-                DrawRectangle(rightButtonBound.x + 2, rightButtonBound.y + 2, rightButtonBound.width - 4, rightButtonBound.height - 4, GetColor(style[SPINNER_DEFAULT_BUTTON_INSIDE_COLOR]));
-                
-                DrawText(FormatText("-"), leftButtonBound.x + (leftButtonBound.width/2 - (MeasureText(FormatText("+"), style[GLOBAL_TEXT_FONTSIZE]))/2), leftButtonBound.y + (leftButtonBound.height/2 - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_PRESSED_SYMBOL_COLOR])); 
-                DrawText(FormatText("+"), rightButtonBound.x + (rightButtonBound.width/2 - (MeasureText(FormatText("-"), style[GLOBAL_TEXT_FONTSIZE]))/2), rightButtonBound.y + (rightButtonBound.height/2 - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_DEFAULT_SYMBOL_COLOR])); 
-            }
-            else if (buttonSide == 2)
-            {
-                DrawRectangleRec(leftButtonBound, GetColor(style[SPINNER_DEFAULT_BUTTON_BORDER_COLOR]));
-                DrawRectangle(leftButtonBound.x + 2, leftButtonBound.y + 2, leftButtonBound.width - 4, leftButtonBound.height - 4, GetColor(style[SPINNER_DEFAULT_BUTTON_INSIDE_COLOR]));
-                
-                DrawRectangleRec(rightButtonBound, GetColor(style[SPINNER_PRESSED_BUTTON_BORDER_COLOR]));
-                DrawRectangle(rightButtonBound.x + 2, rightButtonBound.y + 2, rightButtonBound.width - 4, rightButtonBound.height - 4, GetColor(style[SPINNER_PRESSED_BUTTON_INSIDE_COLOR]));
-                
-                DrawText(FormatText("-"), leftButtonBound.x + (leftButtonBound.width/2 - (MeasureText(FormatText("+"), style[GLOBAL_TEXT_FONTSIZE]))/2), leftButtonBound.y + (leftButtonBound.height/2 - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_DEFAULT_SYMBOL_COLOR])); 
-                DrawText(FormatText("+"), rightButtonBound.x + (rightButtonBound.width/2 - (MeasureText(FormatText("-"), style[GLOBAL_TEXT_FONTSIZE]))/2), rightButtonBound.y + (rightButtonBound.height/2 - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_PRESSED_SYMBOL_COLOR])); 
-            }
-            
-            DrawRectangleRec(labelBoxBound, GetColor(style[SPINNER_LABEL_BORDER_COLOR]));
-            DrawRectangle(labelBoxBound.x + 1, labelBoxBound.y + 1, labelBoxBound.width - 2, labelBoxBound.height - 2, GetColor(style[SPINNER_LABEL_INSIDE_COLOR]));
-            
-            DrawText(FormatText("%i", value), labelBoxBound.x + (labelBoxBound.width/2 - textWidth/2), labelBoxBound.y + (labelBoxBound.height/2 - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_PRESSED_TEXT_COLOR]));  
-        } break;
-        default: break;
-    }
-    
-    return value;
-}
-
-// Text Box element, returns input text
-// NOTE: Requires static variables: framesCounter - ERROR!
-char *GuiTextBox(Rectangle bounds, char *text)
-{
-    #define MAX_CHARS_LENGTH  	 20
-    #define KEY_BACKSPACE_TEXT  259     // GLFW BACKSPACE: 3 + 256
-    
-    int initPos = bounds.x + 4;
-    int letter = -1;
-    static int framesCounter = 0;
-    Vector2 mousePoint = GetMousePosition();
-    
-    // Update control
-    //-------------------------------------------------------------------- 
-    framesCounter++;
-    
-    letter = GetKeyPressed();
-  
-    if (CheckCollisionPointRec(mousePoint, bounds)) 
-    {        
-        if (letter != -1)
-        {
-            if (letter == KEY_BACKSPACE_TEXT)
-            {
-                for (int i = 0; i < MAX_CHARS_LENGTH; i++)
-                {
-                    if ((text[i] == '\0') && (i > 0))
-                    {
-                        text[i - 1] = '\0';
-                        break;
-                    }
-                }
-                
-                text[MAX_CHARS_LENGTH - 1] = '\0';
-            }
-            else
-            {
-                if ((letter >= 32) && (letter < 127))
-                {
-                    for (int i = 0; i < MAX_CHARS_LENGTH; i++)
-                    {
-                        if (text[i] == '\0')
-                        {
-                            text[i] = (char)letter;
-                            break;
-                        }
-                    }
-                }
-            }
-        }
-    }
-    //-------------------------------------------------------------------- 
-
-    // Draw control
-    //--------------------------------------------------------------------
-    if (CheckCollisionPointRec(mousePoint, bounds)) DrawRectangleRec(bounds, GetColor(style[TOGGLE_ACTIVE_BORDER_COLOR]));
-    else DrawRectangleRec(bounds, GetColor(style[TEXTBOX_BORDER_COLOR]));
-    
-    DrawRectangle(bounds.x + style[TEXTBOX_BORDER_WIDTH], bounds.y + style[TEXTBOX_BORDER_WIDTH], bounds.width - (style[TEXTBOX_BORDER_WIDTH] * 2), bounds.height - (style[TEXTBOX_BORDER_WIDTH] * 2), GetColor(style[TEXTBOX_INSIDE_COLOR]));
-    
-    for (int i = 0; i < MAX_CHARS_LENGTH; i++)
-    {
-        if (text[i] == '\0') break;
-        
-        DrawText(FormatText("%c", text[i]), initPos, bounds.y + style[TEXTBOX_TEXT_FONTSIZE], style[TEXTBOX_TEXT_FONTSIZE], GetColor(style[TEXTBOX_TEXT_COLOR]));
-        
-        initPos += (MeasureText(FormatText("%c", text[i]), style[GLOBAL_TEXT_FONTSIZE]) + 2);
-        //initPos += ((GetDefaultFont().charRecs[(int)text[i] - 32].width + 2));
-    }
-
-    if ((framesCounter/20)%2 && CheckCollisionPointRec(mousePoint, bounds)) DrawRectangle(initPos + 2, bounds.y + 5, 1, 20, GetColor(style[TEXTBOX_LINE_COLOR]));
-    //--------------------------------------------------------------------    
-
-    return text;
-}
-
-// Save current GUI style into a text file
-void SaveGuiStyle(const char *fileName)
-{
-    FILE *styleFile = fopen(fileName, "wt");
-    
-    for (int i = 0; i < NUM_PROPERTIES; i++) fprintf(styleFile, "%-40s0x%x\n", guiPropertyName[i], GetStyleProperty(i));
-    
-    fclose(styleFile);
-}
-
-// Load GUI style from a text file
-void LoadGuiStyle(const char *fileName)
-{
-    #define MAX_STYLE_PROPERTIES    128
-    
-    typedef struct {
-        char id[64];
-        int value;
-    } StyleProperty;
-    
-    StyleProperty *styleProp = (StyleProperty *)malloc(MAX_STYLE_PROPERTIES*sizeof(StyleProperty));; 
-    int counter = 0;
-    
-    FILE *styleFile = fopen(fileName, "rt");
-
-    while (!feof(styleFile))
-    {
-        fscanf(styleFile, "%s %i\n", styleProp[counter].id, &styleProp[counter].value);
-        counter++;
-    }
-
-    fclose(styleFile);
-
-    for (int i = 0; i < counter; i++)
-    {
-        for (int j = 0; j < NUM_PROPERTIES; j++)
-        {
-            if (strcmp(styleProp[i].id, guiPropertyName[j]) == 0)
-            {
-                // Assign correct property to style
-                style[j] = styleProp[i].value;
-            }
-        }
-    }
-    
-    free(styleProp);
-}
-
-// Set one style property value
-void SetStyleProperty(int guiProperty, int value) 
-{
-    #define NUM_COLOR_SAMPLES   10
-    
-    if (guiProperty == GLOBAL_BASE_COLOR)
-    {
-        Color baseColor = GetColor(value);
-        Color fadeColor[NUM_COLOR_SAMPLES];
-        
-        for (int i = 0; i < NUM_COLOR_SAMPLES; i++) fadeColor[i] = ColorMultiply(baseColor, 1.0f - (float)i/(NUM_COLOR_SAMPLES - 1));
-        
-        style[GLOBAL_BASE_COLOR] = value;
-        style[BACKGROUND_COLOR] = GetHexValue(fadeColor[3]);
-        style[BUTTON_DEFAULT_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
-        style[BUTTON_HOVER_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
-        style[BUTTON_PRESSED_INSIDE_COLOR] = GetHexValue(fadeColor[5]);
-        style[TOGGLE_DEFAULT_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
-        style[TOGGLE_HOVER_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
-        style[TOGGLE_PRESSED_INSIDE_COLOR] = GetHexValue(fadeColor[5]);
-        style[TOGGLE_ACTIVE_INSIDE_COLOR] = GetHexValue(fadeColor[8]);
-        style[SLIDER_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
-        style[SLIDER_DEFAULT_COLOR] = GetHexValue(fadeColor[6]);
-        style[SLIDER_HOVER_COLOR] = GetHexValue(fadeColor[7]);
-        style[SLIDER_ACTIVE_COLOR] = GetHexValue(fadeColor[9]);
-        style[SLIDERBAR_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
-        style[SLIDERBAR_DEFAULT_COLOR] = GetHexValue(fadeColor[6]);
-        style[SLIDERBAR_HOVER_COLOR] = GetHexValue(fadeColor[7]);
-        style[SLIDERBAR_ACTIVE_COLOR] = GetHexValue(fadeColor[9]);
-        style[SLIDERBAR_ZERO_LINE_COLOR] = GetHexValue(fadeColor[8]);
-        style[PROGRESSBAR_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
-        style[PROGRESSBAR_PROGRESS_COLOR] = GetHexValue(fadeColor[6]);
-        style[SPINNER_LABEL_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
-        style[SPINNER_DEFAULT_BUTTON_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
-        style[SPINNER_HOVER_BUTTON_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
-        style[SPINNER_PRESSED_BUTTON_INSIDE_COLOR] = GetHexValue(fadeColor[5]);
-        style[COMBOBOX_DEFAULT_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
-        style[COMBOBOX_HOVER_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
-        style[COMBOBOX_PRESSED_INSIDE_COLOR] = GetHexValue(fadeColor[8]);
-        style[COMBOBOX_PRESSED_LIST_INSIDE_COLOR] = GetHexValue(fadeColor[8]);
-        style[CHECKBOX_DEFAULT_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
-        style[CHECKBOX_CLICK_INSIDE_COLOR] = GetHexValue(fadeColor[6]);
-        style[CHECKBOX_STATUS_ACTIVE_COLOR] = GetHexValue(fadeColor[8]);
-        style[TEXTBOX_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
-    }
-    else if (guiProperty == GLOBAL_BORDER_COLOR)
-    {
-        Color baseColor = GetColor(value);
-        Color fadeColor[NUM_COLOR_SAMPLES];
-        
-        for (int i = 0; i < NUM_COLOR_SAMPLES; i++) fadeColor[i] = ColorMultiply(baseColor, 1.0f - (float)i/(NUM_COLOR_SAMPLES - 1));
-        
-        style[GLOBAL_BORDER_COLOR] = value;
-        style[BUTTON_DEFAULT_BORDER_COLOR] = GetHexValue(fadeColor[7]);
-        style[BUTTON_HOVER_BORDER_COLOR] = GetHexValue(fadeColor[8]);
-        style[BUTTON_PRESSED_BORDER_COLOR] = GetHexValue(fadeColor[9]);
-        style[TOGGLE_DEFAULT_BORDER_COLOR] = GetHexValue(fadeColor[7]);
-        style[TOGGLE_HOVER_BORDER_COLOR] = GetHexValue(fadeColor[8]);
-        style[TOGGLE_PRESSED_BORDER_COLOR] = GetHexValue(fadeColor[9]);
-        style[TOGGLE_ACTIVE_BORDER_COLOR] = GetHexValue(fadeColor[9]);
-        style[SLIDER_BORDER_COLOR] = GetHexValue(fadeColor[7]);
-        style[SLIDERBAR_BORDER_COLOR] = GetHexValue(fadeColor[7]);
-        style[PROGRESSBAR_BORDER_COLOR] = GetHexValue(fadeColor[7]);
-        style[SPINNER_LABEL_BORDER_COLOR] = GetHexValue(fadeColor[7]);
-        style[SPINNER_DEFAULT_BUTTON_BORDER_COLOR] = GetHexValue(fadeColor[7]);
-        style[SPINNER_HOVER_BUTTON_BORDER_COLOR] = GetHexValue(fadeColor[8]);
-        style[SPINNER_PRESSED_BUTTON_BORDER_COLOR] = GetHexValue(fadeColor[9]);
-        style[COMBOBOX_DEFAULT_BORDER_COLOR] = GetHexValue(fadeColor[7]);
-        style[COMBOBOX_HOVER_BORDER_COLOR] = GetHexValue(fadeColor[8]);
-        style[COMBOBOX_PRESSED_BORDER_COLOR] = GetHexValue(fadeColor[9]);
-        style[COMBOBOX_PRESSED_LIST_BORDER_COLOR] = GetHexValue(fadeColor[9]);
-        style[CHECKBOX_DEFAULT_BORDER_COLOR] = GetHexValue(fadeColor[7]);
-        style[CHECKBOX_HOVER_BORDER_COLOR] = GetHexValue(fadeColor[8]);
-        style[CHECKBOX_CLICK_BORDER_COLOR] = GetHexValue(fadeColor[9]);
-        style[TEXTBOX_BORDER_COLOR] = GetHexValue(fadeColor[7]);
-    }
-    else if (guiProperty == GLOBAL_TEXT_COLOR)
-    {
-        Color baseColor = GetColor(value);
-        Color fadeColor[NUM_COLOR_SAMPLES];
-        
-        for (int i = 0; i < NUM_COLOR_SAMPLES; i++) fadeColor[i] = ColorMultiply(baseColor, 1.0f - (float)i/(NUM_COLOR_SAMPLES - 1));
-        
-        style[GLOBAL_TEXT_COLOR] = value;
-        style[LABEL_TEXT_COLOR] = GetHexValue(fadeColor[9]);
-        style[BUTTON_DEFAULT_TEXT_COLOR] = GetHexValue(fadeColor[9]);
-        style[BUTTON_HOVER_TEXT_COLOR] = GetHexValue(fadeColor[8]);
-        style[BUTTON_PRESSED_TEXT_COLOR] = GetHexValue(fadeColor[5]);
-        style[TOGGLE_DEFAULT_TEXT_COLOR] = GetHexValue(fadeColor[9]);
-        style[TOGGLE_HOVER_TEXT_COLOR] = GetHexValue(fadeColor[8]);
-        style[TOGGLE_PRESSED_TEXT_COLOR] = GetHexValue(fadeColor[5]);
-        style[TOGGLE_ACTIVE_TEXT_COLOR] = GetHexValue(fadeColor[5]);
-        style[SPINNER_DEFAULT_SYMBOL_COLOR] = GetHexValue(fadeColor[9]);
-        style[SPINNER_DEFAULT_TEXT_COLOR] = GetHexValue(fadeColor[9]);
-        style[SPINNER_HOVER_SYMBOL_COLOR] = GetHexValue(fadeColor[8]);
-        style[SPINNER_HOVER_TEXT_COLOR] = GetHexValue(fadeColor[8]);
-        style[SPINNER_PRESSED_SYMBOL_COLOR] = GetHexValue(fadeColor[5]);
-        style[SPINNER_PRESSED_TEXT_COLOR] = GetHexValue(fadeColor[5]);
-        style[COMBOBOX_DEFAULT_TEXT_COLOR] = GetHexValue(fadeColor[9]);
-        style[COMBOBOX_DEFAULT_LIST_TEXT_COLOR] = GetHexValue(fadeColor[9]);
-        style[COMBOBOX_HOVER_TEXT_COLOR] = GetHexValue(fadeColor[8]);
-        style[COMBOBOX_HOVER_LIST_TEXT_COLOR] = GetHexValue(fadeColor[8]);
-        style[COMBOBOX_PRESSED_TEXT_COLOR] = GetHexValue(fadeColor[4]);
-        style[COMBOBOX_PRESSED_LIST_TEXT_COLOR] = GetHexValue(fadeColor[4]);
-        style[TEXTBOX_TEXT_COLOR] = GetHexValue(fadeColor[9]);
-        style[TEXTBOX_LINE_COLOR] = GetHexValue(fadeColor[6]);
-    }
-    else style[guiProperty] = value; 
-
-}
-
-// Get one style property value
-int GetStyleProperty(int guiProperty) { return style[guiProperty]; }
-
-//----------------------------------------------------------------------------------
-// Module specific Functions Definition
-//----------------------------------------------------------------------------------
-
-static Color ColorMultiply(Color baseColor, float value)
-{
-    Color multColor = baseColor;
-
-    if (value > 1.0f) value = 1.0f;
-    else if (value < 0.0f) value = 0.0f;
-    
-    multColor.r += (255 - multColor.r)*value;
-    multColor.g += (255 - multColor.g)*value;
-    multColor.b += (255 - multColor.b)*value;
-    
-    return multColor;
-}
-
-#if defined (RAYGUI_STANDALONE)
-// Returns a Color struct from hexadecimal value
-static Color GetColor(int hexValue)
-{
-    Color color;
-
-    color.r = (unsigned char)(hexValue >> 24) & 0xFF;
-    color.g = (unsigned char)(hexValue >> 16) & 0xFF;
-    color.b = (unsigned char)(hexValue >> 8) & 0xFF;
-    color.a = (unsigned char)hexValue & 0xFF;
-
-    return color;
-}
-
-// Returns hexadecimal value for a Color
-static int GetHexValue(Color color)
-{
-    return (((int)color.r << 24) | ((int)color.g << 16) | ((int)color.b << 8) | (int)color.a);
-}
-
-// Check if point is inside rectangle
-static bool CheckCollisionPointRec(Vector2 point, Rectangle rec)
-{
-    bool collision = false;
-
-    if ((point.x >= rec.x) && (point.x <= (rec.x + rec.width)) && (point.y >= rec.y) && (point.y <= (rec.y + rec.height))) collision = true;
-
-    return collision;
-}
-
-// Formatting of text with variables to 'embed'
-static const char *FormatText(const char *text, ...)
-{
-    #define MAX_FORMATTEXT_LENGTH   64
-    
-    static char buffer[MAX_FORMATTEXT_LENGTH];
-
-    va_list args;
-    va_start(args, text);
-    vsprintf(buffer, text, args);
-    va_end(args);
-
-    return buffer;
-}
-#endif

+ 1222 - 27
src/raygui.h

@@ -1,8 +1,66 @@
 /*******************************************************************************************
 *
-*   raygui - raylib IMGUI system (Immedite Mode GUI)
+*   raygui 1.0 - IMGUI (Immedite Mode GUI) library for raylib (https://github.com/raysan5/raylib)
 *
-*   Copyright (c) 2015 Kevin Gato, Daniel Nicolás, Sergio Martinez and Ramon Santamaria
+*   raygui is a library for creating simple IMGUI interfaces using raylib. 
+*   It provides a set of basic components:
+*
+*       - Label
+*       - Button
+*       - ToggleButton
+*       - ToggleGroup
+*       - ComboBox
+*       - CheckBox
+*       - Slider
+*       - SliderBar
+*       - ProgressBar
+*       - Spinner
+*       - TextBox
+*
+*   It also provides a set of functions for styling the components based on its properties (size, color).
+* 
+*   CONFIGURATION:
+*   
+*   #define RAYGUI_IMPLEMENTATION
+*       Generates the implementation of the library into the included file.
+*       If not defined, the library is in header only mode and can be included in other headers 
+*       or source files without problems. But only ONE file should hold the implementation.
+*
+*   #define RAYGUI_STATIC (defined by default)
+*       The generated implementation will stay private inside implementation file and all 
+*       internal symbols and functions will only be visible inside that file.
+*
+*   #define RAYGUI_STANDALONE
+*       Avoid raylib.h header inclusion in this file. Data types defined on raylib are defined
+*       internally in the library and input management and drawing functions must be provided by
+*       the user (check library implementation for further details).
+*
+*   #define RAYGUI_MALLOC()
+*   #define RAYGUI_FREE()
+*       You can define your own malloc/free implementation replacing stdlib.h malloc()/free() functions.
+*       Otherwise it will include stdlib.h and use the C standard library malloc()/free() function.
+*       
+*   LIMITATIONS: 
+*
+*       // TODO.
+*
+*   VERSIONS:
+*
+*   1.0 (07-Jun-2016) Converted to header-only by Ramon Santamaria.
+*   0.9 (07-Mar-2016) Reviewed and tested by Albert Martos, Ian Eito, Sergio Martinez and Ramon Santamaria.
+*   0.8 (27-Aug-2015) Initial release. Implemented by Kevin Gato, Daniel Nicolás and Ramon Santamaria.
+*
+*   CONTRIBUTORS:
+*       Ramon Santamaria: Functions design and naming conventions.
+*       Kevin Gato: Initial implementation of basic components.
+*       Daniel Nicolas: Initial implementation of basic components.
+*       Albert Martos: Review and testing of library.
+*       Ian Eito: Review and testing of the library.
+*       Sergio Martinez: Review and testing of the library.
+*
+*   LICENSE: zlib/libpng
+*
+*   Copyright (c) 2015-2016 emegeme (@emegemegames)
 *
 *   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.
@@ -20,10 +78,24 @@
 *     3. This notice may not be removed or altered from any source distribution.
 *
 **********************************************************************************************/
+
 #ifndef RAYGUI_H
 #define RAYGUI_H
 
-//#include "raylib.h"
+#if !defined(RAYGUI_STANDALONE)
+    #include "raylib.h"
+#endif
+
+#define RAYGUI_STATIC
+#ifdef RAYGUI_STATIC
+    #define RAYGUIDEF static            // Functions just visible to module including this file
+#else
+    #ifdef __cplusplus
+        #define RAYGUIDEF extern "C"    // Functions visible from other files (no name mangling of functions in C++)
+    #else
+        #define RAYGUIDEF extern        // Functions visible from other files
+    #endif
+#endif
 
 //----------------------------------------------------------------------------------
 // Defines and Macros
@@ -167,13 +239,186 @@ typedef enum GuiProperty {
     TEXTBOX_TEXT_FONTSIZE
 } GuiProperty;
 
-#ifdef __cplusplus
-extern "C" {            // Prevents name mangling of functions
+//----------------------------------------------------------------------------------
+// Global Variables Definition
+//----------------------------------------------------------------------------------
+// ...
+
+//----------------------------------------------------------------------------------
+// Module Functions Declaration
+//----------------------------------------------------------------------------------
+RAYGUIDEF void GuiLabel(Rectangle bounds, const char *text);                                                  // Label element, show text
+RAYGUIDEF void GuiLabelEx(Rectangle bounds, const char *text, Color textColor, Color border, Color inner);    // Label element extended, configurable colors
+RAYGUIDEF bool GuiButton(Rectangle bounds, const char *text);                                                 // Button element, returns true when clicked
+RAYGUIDEF bool GuiToggleButton(Rectangle bounds, const char *text, bool toggle);                              // Toggle Button element, returns true when active
+RAYGUIDEF int GuiToggleGroup(Rectangle bounds, int toggleNum, char **toggleText, int toggleActive);           // Toggle Group element, returns toggled button index
+RAYGUIDEF int GuiComboBox(Rectangle bounds, int comboNum, char **comboText, int comboActive);                 // Combo Box element, returns selected item index
+RAYGUIDEF bool GuiCheckBox(Rectangle bounds, const char *text, bool checked);                                 // Check Box element, returns true when active
+RAYGUIDEF float GuiSlider(Rectangle bounds, float value, float minValue, float maxValue);                     // Slider element, returns selected value
+RAYGUIDEF float GuiSliderBar(Rectangle bounds, float value, float minValue, float maxValue);                  // Slider Bar element, returns selected value
+RAYGUIDEF void GuiProgressBar(Rectangle bounds, float value);                                                 // Progress Bar element, shows current progress value
+RAYGUIDEF int GuiSpinner(Rectangle bounds, int value, int minValue, int maxValue);                            // Spinner element, returns selected value
+RAYGUIDEF char *GuiTextBox(Rectangle bounds, char *text);                                                     // Text Box element, returns input text
+
+RAYGUIDEF void SaveGuiStyle(const char *fileName);                        // Save GUI style file
+RAYGUIDEF void LoadGuiStyle(const char *fileName);                        // Load GUI style file
+
+RAYGUIDEF void SetStyleProperty(int guiProperty, int value);              // Set one style property
+RAYGUIDEF int GetStyleProperty(int guiProperty);                          // Get one style property
+
+#endif // RAYGUI_H
+
+
+/***********************************************************************************
+*
+*   RAYGUI IMPLEMENTATION
+*
+************************************************************************************/
+
+#if defined(RAYGUI_IMPLEMENTATION)
+
+#include <stdio.h>          // Required for: FILE, fopen(), fclose(), fprintf(), feof(), fscanf()
+                            // NOTE: Those functions are only used in SaveGuiStyle() and LoadGuiStyle()
+                        
+// Check if custom malloc/free functions defined, if not, using standard ones
+#if !defined(RAYGUI_MALLOC)
+    #include <stdlib.h>     // Required for: malloc(), free() [Used only on LoadGuiStyle()]
+    
+    #define RAYGUI_MALLOC(size)  malloc(size)
+    #define RAYGUI_FREE(ptr)     free(ptr)
 #endif
 
+#include <string.h>         // Required for: strcmp() [Used only on LoadGuiStyle()]
+#include <stdarg.h>         // Required for: va_list, va_start(), vfprintf(), va_end()
+
+//----------------------------------------------------------------------------------
+// Defines and Macros
+//----------------------------------------------------------------------------------
+#if defined(RAYGUI_STANDALONE)
+    #define KEY_LEFT            263
+    #define KEY_RIGHT           262
+    #define MOUSE_LEFT_BUTTON     0
+#endif
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+
+// GUI elements states
+typedef enum { BUTTON_DEFAULT, BUTTON_HOVER, BUTTON_PRESSED, BUTTON_CLICKED } ButtonState;
+typedef enum { TOGGLE_UNACTIVE, TOGGLE_HOVER, TOGGLE_PRESSED, TOGGLE_ACTIVE } ToggleState;
+typedef enum { COMBOBOX_UNACTIVE, COMBOBOX_HOVER, COMBOBOX_PRESSED, COMBOBOX_ACTIVE } ComboBoxState;
+typedef enum { SPINNER_DEFAULT, SPINNER_HOVER, SPINNER_PRESSED } SpinnerState;
+typedef enum { CHECKBOX_STATUS, CHECKBOX_HOVER, CHECKBOX_PRESSED } CheckBoxState;
+typedef enum { SLIDER_DEFAULT, SLIDER_HOVER, SLIDER_ACTIVE } SliderState;
+
 //----------------------------------------------------------------------------------
 // Global Variables Definition
 //----------------------------------------------------------------------------------
+
+// Current GUI style (default light)
+static int style[NUM_PROPERTIES] = {
+    0xf5f5f5ff,         // GLOBAL_BASE_COLOR,
+    0xf5f5f5ff,         // GLOBAL_BORDER_COLOR,
+    0xf5f5f5ff,         // GLOBAL_TEXT_COLOR,
+    10,                 // GLOBAL_TEXT_FONTSIZE
+    1,                  // GLOBAL_BORDER_WIDTH
+    0xf5f5f5ff,         // BACKGROUND_COLOR
+    1,                  // LABEL_BORDER_WIDTH
+    0x4d4d4dff,         // LABEL_TEXT_COLOR
+    20,                 // LABEL_TEXT_PADDING
+    2,                  // BUTTON_BORDER_WIDTH
+    20,                 // BUTTON_TEXT_PADDING
+    0x828282ff,         // BUTTON_DEFAULT_BORDER_COLOR
+    0xc8c8c8ff,         // BUTTON_DEFAULT_INSIDE_COLOR
+    0x4d4d4dff,         // BUTTON_DEFAULT_TEXT_COLOR
+    0xc8c8c8ff,         // BUTTON_HOVER_BORDER_COLOR
+    0xffffffff,         // BUTTON_HOVER_INSIDE_COLOR
+    0x353535ff,         // BUTTON_HOVER_TEXT_COLOR
+    0x7bb0d6ff,         // BUTTON_PRESSED_BORDER_COLOR
+    0xbcecffff,         // BUTTON_PRESSED_INSIDE_COLOR
+    0x5f9aa7ff,         // BUTTON_PRESSED_TEXT_COLOR
+    20,                 // TOGGLE_TEXT_PADDING
+    1,                  // TOGGLE_BORDER_WIDTH
+    0x828282ff,         // TOGGLE_DEFAULT_BORDER_COLOR
+    0xc8c8c8ff,         // TOGGLE_DEFAULT_INSIDE_COLOR
+    0x828282ff,         // TOGGLE_DEFAULT_TEXT_COLOR
+    0xc8c8c8ff,         // TOGGLE_HOVER_BORDER_COLOR
+    0xffffffff,         // TOGGLE_HOVER_INSIDE_COLOR
+    0x828282ff,         // TOGGLE_HOVER_TEXT_COLOR
+    0xbdd7eaff,         // TOGGLE_PRESSED_BORDER_COLOR
+    0xddf5ffff,         // TOGGLE_PRESSED_INSIDE_COLOR
+    0xafccd3ff,         // TOGGLE_PRESSED_TEXT_COLOR
+    0x7bb0d6ff,         // TOGGLE_ACTIVE_BORDER_COLOR
+    0xbcecffff,         // TOGGLE_ACTIVE_INSIDE_COLOR
+    0x5f9aa7ff,         // TOGGLE_ACTIVE_TEXT_COLOR
+    3,                  // TOGGLEGROUP_PADDING
+    1,                  // SLIDER_BORDER_WIDTH
+    1,                  // SLIDER_BUTTON_BORDER_WIDTH
+    0x828282ff,         // SLIDER_BORDER_COLOR
+    0xc8c8c8ff,         // SLIDER_INSIDE_COLOR
+    0xbcecffff,         // SLIDER_DEFAULT_COLOR
+    0xffffffff,         // SLIDER_HOVER_COLOR
+    0xddf5ffff,         // SLIDER_ACTIVE_COLOR
+    0x828282ff,         // SLIDERBAR_BORDER_COLOR
+    0xc8c8c8ff,         // SLIDERBAR_INSIDE_COLOR
+    0xbcecffff,         // SLIDERBAR_DEFAULT_COLOR
+    0xffffffff,         // SLIDERBAR_HOVER_COLOR
+    0xddf5ffff,         // SLIDERBAR_ACTIVE_COLOR
+    0x828282ff,         // SLIDERBAR_ZERO_LINE_COLOR
+    0x828282ff,         // PROGRESSBAR_BORDER_COLOR
+    0xc8c8c8ff,         // PROGRESSBAR_INSIDE_COLOR
+    0xbcecffff,         // PROGRESSBAR_PROGRESS_COLOR
+    2,                  // PROGRESSBAR_BORDER_WIDTH
+    0x828282ff,         // SPINNER_LABEL_BORDER_COLOR
+    0xc8c8c8ff,         // SPINNER_LABEL_INSIDE_COLOR
+    0x828282ff,         // SPINNER_DEFAULT_BUTTON_BORDER_COLOR
+    0xc8c8c8ff,         // SPINNER_DEFAULT_BUTTON_INSIDE_COLOR
+    0x000000ff,         // SPINNER_DEFAULT_SYMBOL_COLOR
+    0x000000ff,         // SPINNER_DEFAULT_TEXT_COLOR
+    0xc8c8c8ff,         // SPINNER_HOVER_BUTTON_BORDER_COLOR
+    0xffffffff,         // SPINNER_HOVER_BUTTON_INSIDE_COLOR
+    0x000000ff,         // SPINNER_HOVER_SYMBOL_COLOR
+    0x000000ff,         // SPINNER_HOVER_TEXT_COLOR
+    0x7bb0d6ff,         // SPINNER_PRESSED_BUTTON_BORDER_COLOR
+    0xbcecffff,         // SPINNER_PRESSED_BUTTON_INSIDE_COLOR
+    0x5f9aa7ff,         // SPINNER_PRESSED_SYMBOL_COLOR
+    0x000000ff,         // SPINNER_PRESSED_TEXT_COLOR
+    1,                  // COMBOBOX_PADDING
+    30,                 // COMBOBOX_BUTTON_WIDTH
+    20,                 // COMBOBOX_BUTTON_HEIGHT
+    1,                  // COMBOBOX_BORDER_WIDTH
+    0x828282ff,         // COMBOBOX_DEFAULT_BORDER_COLOR
+    0xc8c8c8ff,         // COMBOBOX_DEFAULT_INSIDE_COLOR
+    0x828282ff,         // COMBOBOX_DEFAULT_TEXT_COLOR
+    0x828282ff,         // COMBOBOX_DEFAULT_LIST_TEXT_COLOR
+    0xc8c8c8ff,         // COMBOBOX_HOVER_BORDER_COLOR
+    0xffffffff,         // COMBOBOX_HOVER_INSIDE_COLOR
+    0x828282ff,         // COMBOBOX_HOVER_TEXT_COLOR
+    0x828282ff,         // COMBOBOX_HOVER_LIST_TEXT_COLOR
+    0x7bb0d6ff,         // COMBOBOX_PRESSED_BORDER_COLOR
+    0xbcecffff,         // COMBOBOX_PRESSED_INSIDE_COLOR
+    0x5f9aa7ff,         // COMBOBOX_PRESSED_TEXT_COLOR
+    0x0078acff,         // COMBOBOX_PRESSED_LIST_BORDER_COLOR
+    0x66e7ffff,         // COMBOBOX_PRESSED_LIST_INSIDE_COLOR
+    0x0078acff,         // COMBOBOX_PRESSED_LIST_TEXT_COLOR
+    0x828282ff,         // CHECKBOX_DEFAULT_BORDER_COLOR
+    0xffffffff,         // CHECKBOX_DEFAULT_INSIDE_COLOR
+    0xc8c8c8ff,         // CHECKBOX_HOVER_BORDER_COLOR
+    0xffffffff,         // CHECKBOX_HOVER_INSIDE_COLOR
+    0x66e7ffff,         // CHECKBOX_CLICK_BORDER_COLOR
+    0xddf5ffff,         // CHECKBOX_CLICK_INSIDE_COLOR
+    0x7bb0d6ff,         // CHECKBOX_STATUS_ACTIVE_COLOR
+    4,                  // CHECKBOX_INSIDE_WIDTH
+    1,                  // TEXTBOX_BORDER_WIDTH
+    0x828282ff,         // TEXTBOX_BORDER_COLOR
+    0xf5f5f5ff,         // TEXTBOX_INSIDE_COLOR
+    0x000000ff,         // TEXTBOX_TEXT_COLOR
+    0x000000ff,         // TEXTBOX_LINE_COLOR
+    10                  // TEXTBOX_TEXT_FONTSIZE
+};
+
+// GUI property names (to read/write style text files)
 static const char *guiPropertyName[] = {
     "GLOBAL_BASE_COLOR",
     "GLOBAL_BORDER_COLOR",
@@ -276,29 +521,979 @@ static const char *guiPropertyName[] = {
 };
 
 //----------------------------------------------------------------------------------
-// Module Functions Declaration
+// Module specific Functions Declaration
 //----------------------------------------------------------------------------------
-void GuiLabel(Rectangle bounds, const char *text);                                                  // Label element, show text
-void GuiLabelEx(Rectangle bounds, const char *text, Color textColor, Color border, Color inner);    // Label element extended, configurable colors
-bool GuiButton(Rectangle bounds, const char *text);                                                 // Button element, returns true when clicked
-bool GuiToggleButton(Rectangle bounds, const char *text, bool toggle);                              // Toggle Button element, returns true when active
-int GuiToggleGroup(Rectangle bounds, int toggleNum, char **toggleText, int toggleActive);           // Toggle Group element, returns toggled button index
-int GuiComboBox(Rectangle bounds, int comboNum, char **comboText, int comboActive);                 // Combo Box element, returns selected item index
-bool GuiCheckBox(Rectangle bounds, const char *text, bool checked);                                 // Check Box element, returns true when active
-float GuiSlider(Rectangle bounds, float value, float minValue, float maxValue);                     // Slider element, returns selected value
-float GuiSliderBar(Rectangle bounds, float value, float minValue, float maxValue);                  // Slider Bar element, returns selected value
-void GuiProgressBar(Rectangle bounds, float value);                                                 // Progress Bar element, shows current progress value
-int GuiSpinner(Rectangle bounds, int value, int minValue, int maxValue);                            // Spinner element, returns selected value
-char *GuiTextBox(Rectangle bounds, char *text);                                                     // Text Box element, returns input text
-
-void SaveGuiStyle(const char *fileName);                        // Save GUI style file
-void LoadGuiStyle(const char *fileName);                        // Load GUI style file
-
-void SetStyleProperty(int guiProperty, int value);              // Set one style property
-int GetStyleProperty(int guiProperty);                          // Get one style property
-
-#ifdef __cplusplus
+static Color ColorMultiply(Color baseColor, float value);
+
+#if defined RAYGUI_STANDALONE
+static Color GetColor(int hexValue);   // Returns a Color struct from hexadecimal value
+static int GetHexValue(Color color);   // Returns hexadecimal value for a Color
+static bool CheckCollisionPointRec(Vector2 point, Rectangle rec);  // Check if point is inside rectangle
+static const char *FormatText(const char *text, ...);   // Formatting of text with variables to 'embed'
+
+// NOTE: raygui depend on some raylib input and drawing functions
+// TODO: To use raygui as standalone library, those functions must be overwrite by custom ones
+
+// Input management functions
+static Vector2 GetMousePosition() { return (Vector2){ 0.0f, 0.0f }; }
+static int IsMouseButtonDown(int button) { return 0; }
+static int IsMouseButtonPressed(int button) { return 0; }
+static int IsMouseButtonReleased(int button) { return 0; }
+static int IsMouseButtonUp(int button) { return 0; }
+
+static int GetKeyPressed(void) { return 0; }    // NOTE: Only used by GuiTextBox()
+static int IsKeyDown(int key) { return 0; }     // NOTE: Only used by GuiSpinner()
+
+// Drawing related functions
+static int MeasureText(const char *text, int fontSize) { return 0; }
+static void DrawText(const char *text, int posX, int posY, int fontSize, Color color) { }
+static void DrawRectangleRec(Rectangle rec, Color color) { }
+static void DrawRectangle(int posX, int posY, int width, int height, Color color) { DrawRectangleRec((Rectangle){ posX, posY, width, height }, color); }
+#endif
+
+//----------------------------------------------------------------------------------
+// Module Functions Definition
+//----------------------------------------------------------------------------------
+
+// Label element, show text
+RAYGUIDEF void GuiLabel(Rectangle bounds, const char *text)
+{
+    #define BLANK (Color){ 0, 0, 0, 0 } // Blank (Transparent)
+
+    GuiLabelEx(bounds, text, GetColor(style[LABEL_TEXT_COLOR]), BLANK, BLANK);
+}
+
+// Label element extended, configurable colors
+RAYGUIDEF void GuiLabelEx(Rectangle bounds, const char *text, Color textColor, Color border, Color inner)
+{
+    // Update control
+    //--------------------------------------------------------------------
+    int textWidth = MeasureText(text, style[GLOBAL_TEXT_FONTSIZE]);
+    int textHeight = style[GLOBAL_TEXT_FONTSIZE];
+
+    if (bounds.width < textWidth) bounds.width = textWidth + style[LABEL_TEXT_PADDING];
+    if (bounds.height < textHeight) bounds.height = textHeight + style[LABEL_TEXT_PADDING]/2;
+    //--------------------------------------------------------------------
+    
+    // Draw control
+    //--------------------------------------------------------------------
+    DrawRectangleRec(bounds, border);
+    DrawRectangle(bounds.x + style[LABEL_BORDER_WIDTH], bounds.y + style[LABEL_BORDER_WIDTH], bounds.width - (2 * style[LABEL_BORDER_WIDTH]), bounds.height - (2 * style[LABEL_BORDER_WIDTH]), inner);
+    DrawText(text, bounds.x + ((bounds.width/2) - (textWidth/2)), bounds.y + ((bounds.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], textColor);
+    //--------------------------------------------------------------------
+}
+
+// Button element, returns true when clicked
+RAYGUIDEF bool GuiButton(Rectangle bounds, const char *text)
+{
+    ButtonState buttonState = BUTTON_DEFAULT;
+    Vector2 mousePoint = GetMousePosition();
+    
+    int textWidth = MeasureText(text, style[GLOBAL_TEXT_FONTSIZE]);
+    int textHeight = style[GLOBAL_TEXT_FONTSIZE];
+    
+    // Update control
+    //--------------------------------------------------------------------
+    if (bounds.width < textWidth) bounds.width = textWidth + style[BUTTON_TEXT_PADDING];
+    if (bounds.height < textHeight) bounds.height = textHeight + style[BUTTON_TEXT_PADDING]/2;
+    
+    if (CheckCollisionPointRec(mousePoint, bounds))
+    {
+        if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) buttonState = BUTTON_PRESSED;
+        else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) buttonState = BUTTON_CLICKED;
+        else buttonState = BUTTON_HOVER;
+    }
+    //--------------------------------------------------------------------
+    
+    // Draw control
+    //--------------------------------------------------------------------
+    switch (buttonState)
+    {
+        case BUTTON_DEFAULT:
+        {
+            DrawRectangleRec(bounds, GetColor(style[BUTTON_DEFAULT_BORDER_COLOR]));
+            DrawRectangle((int)(bounds.x + style[BUTTON_BORDER_WIDTH]), (int)(bounds.y + style[BUTTON_BORDER_WIDTH]) , (int)(bounds.width - (2 * style[BUTTON_BORDER_WIDTH])), (int)(bounds.height - (2 * style[BUTTON_BORDER_WIDTH])), GetColor(style[BUTTON_DEFAULT_INSIDE_COLOR]));
+            DrawText(text, bounds.x + ((bounds.width/2) - (MeasureText(text, style[GLOBAL_TEXT_FONTSIZE])/2)), bounds.y + ((bounds.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[BUTTON_DEFAULT_TEXT_COLOR]));
+        } break;
+        case BUTTON_HOVER:
+        {
+            DrawRectangleRec(bounds, GetColor(style[BUTTON_HOVER_BORDER_COLOR]));
+            DrawRectangle((int)(bounds.x + style[BUTTON_BORDER_WIDTH]), (int)(bounds.y + style[BUTTON_BORDER_WIDTH]) , (int)(bounds.width - (2 * style[BUTTON_BORDER_WIDTH])), (int)(bounds.height - (2 * style[BUTTON_BORDER_WIDTH])), GetColor(style[BUTTON_HOVER_INSIDE_COLOR]));
+            DrawText(text, bounds.x + ((bounds.width/2) - (MeasureText(text, style[GLOBAL_TEXT_FONTSIZE])/2)), bounds.y + ((bounds.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[BUTTON_HOVER_TEXT_COLOR]));
+        } break;
+        case BUTTON_PRESSED:
+        {
+            DrawRectangleRec(bounds, GetColor(style[BUTTON_PRESSED_BORDER_COLOR]));
+            DrawRectangle((int)(bounds.x + style[BUTTON_BORDER_WIDTH]), (int)(bounds.y + style[BUTTON_BORDER_WIDTH]) , (int)(bounds.width - (2 * style[BUTTON_BORDER_WIDTH])), (int)(bounds.height - (2 * style[BUTTON_BORDER_WIDTH])), GetColor(style[BUTTON_PRESSED_INSIDE_COLOR]));
+            DrawText(text, bounds.x + ((bounds.width/2) - (MeasureText(text, style[GLOBAL_TEXT_FONTSIZE])/2)), bounds.y + ((bounds.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[BUTTON_PRESSED_TEXT_COLOR]));
+        } break;
+        case BUTTON_CLICKED:
+        {
+            DrawRectangleRec(bounds, GetColor(style[BUTTON_PRESSED_BORDER_COLOR]));
+            DrawRectangle((int)(bounds.x + style[BUTTON_BORDER_WIDTH]), (int)(bounds.y + style[BUTTON_BORDER_WIDTH]) , (int)(bounds.width - (2 * style[BUTTON_BORDER_WIDTH])), (int)(bounds.height - (2 * style[BUTTON_BORDER_WIDTH])), GetColor(style[BUTTON_PRESSED_INSIDE_COLOR]));
+        } break;
+        default: break;
+    }
+    //------------------------------------------------------------------
+    
+    if (buttonState == BUTTON_CLICKED) return true;
+    else return false;
+}
+
+// Toggle Button element, returns true when active
+RAYGUIDEF bool GuiToggleButton(Rectangle bounds, const char *text, bool toggle)
+{
+    ToggleState toggleState = TOGGLE_UNACTIVE;
+    Rectangle toggleButton = bounds;
+    Vector2 mousePoint = GetMousePosition();
+    
+    int textWidth = MeasureText(text, style[GLOBAL_TEXT_FONTSIZE]);
+    int textHeight = style[GLOBAL_TEXT_FONTSIZE];
+    
+    // Update control
+    //--------------------------------------------------------------------   
+    if (toggleButton.width < textWidth) toggleButton.width = textWidth + style[TOGGLE_TEXT_PADDING];
+    if (toggleButton.height < textHeight) toggleButton.height = textHeight + style[TOGGLE_TEXT_PADDING]/2;
+    
+    if (toggle) toggleState = TOGGLE_ACTIVE;
+    else toggleState = TOGGLE_UNACTIVE;
+    
+    if (CheckCollisionPointRec(mousePoint, toggleButton))
+    {
+        if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) toggleState = TOGGLE_PRESSED;
+        else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON))
+        {
+            if (toggle)
+            {
+                toggle = false;
+                toggleState = TOGGLE_UNACTIVE;
+            }
+            else
+            {
+                toggle = true;
+                toggleState = TOGGLE_ACTIVE;
+            }
+        }
+        else toggleState = TOGGLE_HOVER;
+    }
+    //--------------------------------------------------------------------   
+    
+    // Draw control
+    //--------------------------------------------------------------------
+    switch (toggleState)
+    {
+        case TOGGLE_UNACTIVE:
+        {
+            DrawRectangleRec(toggleButton, GetColor(style[TOGGLE_DEFAULT_BORDER_COLOR]));
+            DrawRectangle((int)(toggleButton.x + style[TOGGLE_BORDER_WIDTH]), (int)(toggleButton.y + style[TOGGLE_BORDER_WIDTH]) , (int)(toggleButton.width - (2 * style[TOGGLE_BORDER_WIDTH])), (int)(toggleButton.height - (2 * style[TOGGLE_BORDER_WIDTH])), GetColor(style[TOGGLE_DEFAULT_INSIDE_COLOR]));
+            DrawText(text, toggleButton.x + ((toggleButton.width/2) - (MeasureText(text, style[GLOBAL_TEXT_FONTSIZE])/2)), toggleButton.y + ((toggleButton.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[TOGGLE_DEFAULT_TEXT_COLOR]));
+        } break;
+        case TOGGLE_HOVER:
+        {
+            DrawRectangleRec(toggleButton, GetColor(style[TOGGLE_HOVER_BORDER_COLOR]));
+            DrawRectangle((int)(toggleButton.x + style[TOGGLE_BORDER_WIDTH]), (int)(toggleButton.y + style[TOGGLE_BORDER_WIDTH]) , (int)(toggleButton.width - (2 * style[TOGGLE_BORDER_WIDTH])), (int)(toggleButton.height - (2 * style[TOGGLE_BORDER_WIDTH])), GetColor(style[TOGGLE_HOVER_INSIDE_COLOR]));
+            DrawText(text, toggleButton.x + ((toggleButton.width/2) - (MeasureText(text, style[GLOBAL_TEXT_FONTSIZE])/2)), toggleButton.y + ((toggleButton.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[TOGGLE_HOVER_TEXT_COLOR]));
+        } break;
+        case TOGGLE_PRESSED:
+        {
+            DrawRectangleRec(toggleButton, GetColor(style[TOGGLE_PRESSED_BORDER_COLOR]));
+            DrawRectangle((int)(toggleButton.x + style[TOGGLE_BORDER_WIDTH]), (int)(toggleButton.y + style[TOGGLE_BORDER_WIDTH]) , (int)(toggleButton.width - (2 * style[TOGGLE_BORDER_WIDTH])), (int)(toggleButton.height - (2 * style[TOGGLE_BORDER_WIDTH])), GetColor(style[TOGGLE_PRESSED_INSIDE_COLOR]));
+            DrawText(text, toggleButton.x + ((toggleButton.width/2) - (MeasureText(text, style[GLOBAL_TEXT_FONTSIZE])/2)), toggleButton.y + ((toggleButton.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[TOGGLE_PRESSED_TEXT_COLOR]));
+        } break;
+        case TOGGLE_ACTIVE:
+        {
+            DrawRectangleRec(toggleButton, GetColor(style[TOGGLE_ACTIVE_BORDER_COLOR]));
+            DrawRectangle((int)(toggleButton.x + style[TOGGLE_BORDER_WIDTH]), (int)(toggleButton.y + style[TOGGLE_BORDER_WIDTH]) , (int)(toggleButton.width - (2 * style[TOGGLE_BORDER_WIDTH])), (int)(toggleButton.height - (2 * style[TOGGLE_BORDER_WIDTH])), GetColor(style[TOGGLE_ACTIVE_INSIDE_COLOR]));
+            DrawText(text, toggleButton.x + ((toggleButton.width/2) - (MeasureText(text, style[GLOBAL_TEXT_FONTSIZE])/2)), toggleButton.y + ((toggleButton.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[TOGGLE_ACTIVE_TEXT_COLOR]));
+        } break;
+        default: break;
+    }
+    //-------------------------------------------------------------------- 
+    
+    return toggle;
+}
+
+// Toggle Group element, returns toggled button index
+RAYGUIDEF int GuiToggleGroup(Rectangle bounds, int toggleNum, char **toggleText, int toggleActive)
+{ 
+    for (int i = 0; i < toggleNum; i++)
+    {
+        if (i == toggleActive) GuiToggleButton((Rectangle){bounds.x + i*(bounds.width + style[TOGGLEGROUP_PADDING]),bounds.y,bounds.width,bounds.height}, toggleText[i], true);      
+        else if (GuiToggleButton((Rectangle){bounds.x + i*(bounds.width + style[TOGGLEGROUP_PADDING]),bounds.y,bounds.width,bounds.height}, toggleText[i], false) == true) toggleActive = i;
+    }
+    
+    return toggleActive;
+}
+
+// Combo Box element, returns selected item index
+RAYGUIDEF int GuiComboBox(Rectangle bounds, int comboNum, char **comboText, int comboActive)
+{
+    ComboBoxState comboBoxState = COMBOBOX_UNACTIVE;
+    Rectangle comboBoxButton = bounds;
+    Rectangle click = { bounds.x + bounds.width + style[COMBOBOX_PADDING], bounds.y, style[COMBOBOX_BUTTON_WIDTH], style[COMBOBOX_BUTTON_HEIGHT] };
+    Vector2 mousePoint = GetMousePosition();
+
+    int textHeight = style[GLOBAL_TEXT_FONTSIZE];
+     
+    for (int i = 0; i < comboNum; i++)
+    {
+        if (i == comboActive)
+        {
+		    // Update control
+    		//-------------------------------------------------------------------- 
+            int textWidth = MeasureText(comboText[i], style[GLOBAL_TEXT_FONTSIZE]);
+                
+            if (comboBoxButton.width < textWidth) comboBoxButton.width = textWidth + style[TOGGLE_TEXT_PADDING];
+            if (comboBoxButton.height < textHeight) comboBoxButton.height = textHeight + style[TOGGLE_TEXT_PADDING]/2;
+            
+            if (CheckCollisionPointRec(mousePoint, comboBoxButton) || CheckCollisionPointRec(mousePoint, click))
+            {
+                if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) comboBoxState = COMBOBOX_PRESSED;
+                else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) comboBoxState = COMBOBOX_ACTIVE;
+                else comboBoxState = COMBOBOX_HOVER;
+            }
+    		//--------------------------------------------------------------------   
+            
+            // Draw control
+            //--------------------------------------------------------------------
+            switch (comboBoxState)
+            {
+                case COMBOBOX_UNACTIVE:
+                {
+                    DrawRectangleRec(comboBoxButton, GetColor(style[COMBOBOX_DEFAULT_BORDER_COLOR]));
+                    DrawRectangle((int)(comboBoxButton.x + style[COMBOBOX_BORDER_WIDTH]), (int)(comboBoxButton.y + style[COMBOBOX_BORDER_WIDTH]), (int)(comboBoxButton.width - (2 * style[COMBOBOX_BORDER_WIDTH])), (int)(comboBoxButton.height - (2*style[COMBOBOX_BORDER_WIDTH])), GetColor(style[COMBOBOX_DEFAULT_INSIDE_COLOR]));
+                
+                    DrawRectangleRec(click, GetColor(style[COMBOBOX_DEFAULT_BORDER_COLOR]));
+                    DrawRectangle((int)(click.x + style[COMBOBOX_BORDER_WIDTH]), (int)(click.y + style[COMBOBOX_BORDER_WIDTH]) , (int)(click.width - (2*style[COMBOBOX_BORDER_WIDTH])), (int)(click.height - (2*style[COMBOBOX_BORDER_WIDTH])), GetColor(style[COMBOBOX_DEFAULT_INSIDE_COLOR]));
+                    DrawText(FormatText("%i/%i", comboActive + 1, comboNum), click.x + ((click.width/2) - (MeasureText(FormatText("%i/%i", comboActive + 1, comboNum), style[GLOBAL_TEXT_FONTSIZE])/2)), click.y + ((click.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[COMBOBOX_DEFAULT_LIST_TEXT_COLOR]));
+                    DrawText(comboText[i], comboBoxButton.x + ((comboBoxButton.width/2) - (MeasureText(comboText[i], style[GLOBAL_TEXT_FONTSIZE])/2)), comboBoxButton.y + ((comboBoxButton.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[COMBOBOX_DEFAULT_TEXT_COLOR]));
+                } break;
+                case COMBOBOX_HOVER:
+                {
+                    DrawRectangleRec(comboBoxButton, GetColor(style[COMBOBOX_HOVER_BORDER_COLOR]));
+                    DrawRectangle((int)(comboBoxButton.x + style[COMBOBOX_BORDER_WIDTH]), (int)(comboBoxButton.y + style[COMBOBOX_BORDER_WIDTH]), (int)(comboBoxButton.width - (2 * style[COMBOBOX_BORDER_WIDTH])), (int)(comboBoxButton.height - (2*style[COMBOBOX_BORDER_WIDTH])), GetColor(style[COMBOBOX_HOVER_INSIDE_COLOR]));
+                    
+                    DrawRectangleRec(click, GetColor(style[COMBOBOX_HOVER_BORDER_COLOR]));
+                    DrawRectangle((int)(click.x + style[COMBOBOX_BORDER_WIDTH]), (int)(click.y + style[COMBOBOX_BORDER_WIDTH]) , (int)(click.width - (2*style[COMBOBOX_BORDER_WIDTH])), (int)(click.height - (2*style[COMBOBOX_BORDER_WIDTH])), GetColor(style[COMBOBOX_HOVER_INSIDE_COLOR]));
+                    DrawText(FormatText("%i/%i", comboActive + 1, comboNum), click.x + ((click.width/2) - (MeasureText(FormatText("%i/%i", comboActive + 1, comboNum), style[GLOBAL_TEXT_FONTSIZE])/2)), click.y + ((click.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[COMBOBOX_HOVER_LIST_TEXT_COLOR]));
+                    DrawText(comboText[i], comboBoxButton.x + ((comboBoxButton.width/2) - (MeasureText(comboText[i], style[GLOBAL_TEXT_FONTSIZE])/2)), comboBoxButton.y + ((comboBoxButton.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[COMBOBOX_HOVER_TEXT_COLOR]));
+                } break;
+                case COMBOBOX_PRESSED:
+                {
+                    DrawRectangleRec(comboBoxButton, GetColor(style[COMBOBOX_PRESSED_BORDER_COLOR]));
+                    DrawRectangle((int)(comboBoxButton.x + style[COMBOBOX_BORDER_WIDTH]), (int)(comboBoxButton.y + style[COMBOBOX_BORDER_WIDTH]), (int)(comboBoxButton.width - (2 * style[COMBOBOX_BORDER_WIDTH])), (int)(comboBoxButton.height - (2*style[COMBOBOX_BORDER_WIDTH])), GetColor(style[COMBOBOX_PRESSED_INSIDE_COLOR]));
+                
+                    DrawRectangleRec(click, GetColor(style[COMBOBOX_PRESSED_LIST_BORDER_COLOR]));
+                    DrawRectangle((int)(click.x + style[COMBOBOX_BORDER_WIDTH]), (int)(click.y + style[COMBOBOX_BORDER_WIDTH]) , (int)(click.width - (2*style[COMBOBOX_BORDER_WIDTH])), (int)(click.height - (2*style[COMBOBOX_BORDER_WIDTH])), GetColor(style[COMBOBOX_PRESSED_LIST_INSIDE_COLOR]));
+                    DrawText(FormatText("%i/%i", comboActive + 1, comboNum), click.x + ((click.width/2) - (MeasureText(FormatText("%i/%i", comboActive + 1, comboNum), style[GLOBAL_TEXT_FONTSIZE])/2)), click.y + ((click.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[COMBOBOX_PRESSED_LIST_TEXT_COLOR]));
+                    DrawText(comboText[i], comboBoxButton.x + ((comboBoxButton.width/2) - (MeasureText(comboText[i], style[GLOBAL_TEXT_FONTSIZE])/2)), comboBoxButton.y + ((comboBoxButton.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[COMBOBOX_PRESSED_TEXT_COLOR]));
+                } break;
+                case COMBOBOX_ACTIVE:
+                {
+                    DrawRectangleRec(comboBoxButton, GetColor(style[COMBOBOX_PRESSED_BORDER_COLOR]));
+                    DrawRectangle((int)(comboBoxButton.x + style[COMBOBOX_BORDER_WIDTH]), (int)(comboBoxButton.y + style[COMBOBOX_BORDER_WIDTH]), (int)(comboBoxButton.width - (2 * style[COMBOBOX_BORDER_WIDTH])), (int)(comboBoxButton.height - (2*style[COMBOBOX_BORDER_WIDTH])), GetColor(style[COMBOBOX_PRESSED_INSIDE_COLOR]));
+                
+                    DrawRectangleRec(click, GetColor(style[COMBOBOX_PRESSED_LIST_BORDER_COLOR]));
+                    DrawRectangle((int)(click.x + style[COMBOBOX_BORDER_WIDTH]), (int)(click.y + style[COMBOBOX_BORDER_WIDTH]) , (int)(click.width - (2*style[COMBOBOX_BORDER_WIDTH])), (int)(click.height - (2*style[COMBOBOX_BORDER_WIDTH])), GetColor(style[COMBOBOX_PRESSED_LIST_INSIDE_COLOR]));
+                    DrawText(FormatText("%i/%i", comboActive + 1, comboNum), click.x + ((click.width/2) - (MeasureText(FormatText("%i/%i", comboActive + 1, comboNum), style[GLOBAL_TEXT_FONTSIZE])/2)), click.y + ((click.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[COMBOBOX_PRESSED_LIST_TEXT_COLOR]));
+                    DrawText(comboText[i], comboBoxButton.x + ((comboBoxButton.width/2) - (MeasureText(comboText[i], style[GLOBAL_TEXT_FONTSIZE])/2)), comboBoxButton.y + ((comboBoxButton.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[COMBOBOX_PRESSED_TEXT_COLOR]));
+                } break;
+                default: break;
+            }
+            
+            //DrawText(comboText[i], comboBoxButton.x + ((comboBoxButton.width/2) - (MeasureText(comboText[i], style[]globalTextFontSize)/2)), comboBoxButton.y + ((comboBoxButton.height/2) - (style[]globalTextFontSize/2)), style[]globalTextFontSize, COMBOBOX_PRESSED_TEXT_COLOR);            
+            //-------------------------------------------------------------------- 
+        }
+    }
+    
+    if (CheckCollisionPointRec(GetMousePosition(), bounds) || CheckCollisionPointRec(GetMousePosition(), click))
+    {
+        if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) 
+        {
+           comboActive += 1; 
+           if(comboActive >= comboNum) comboActive = 0;
+        }
+    } 
+
+    return comboActive;
+}
+
+// Check Box element, returns true when active
+RAYGUIDEF bool GuiCheckBox(Rectangle checkBoxBounds, const char *text, bool checked)
+{
+    CheckBoxState checkBoxState = CHECKBOX_STATUS;
+    Vector2 mousePoint = GetMousePosition();
+    
+    // Update control
+    //-------------------------------------------------------------------- 
+    if (CheckCollisionPointRec(mousePoint, checkBoxBounds))
+    {
+        if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) checkBoxState = CHECKBOX_PRESSED;
+        else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON))
+        {
+            checkBoxState = CHECKBOX_STATUS;
+            checked = !checked;
+        } 
+        else checkBoxState = CHECKBOX_HOVER;
+    }
+    //-------------------------------------------------------------------- 
+    
+    // Draw control
+    //--------------------------------------------------------------------
+    switch (checkBoxState)
+    {
+        case CHECKBOX_HOVER:
+        {
+            DrawRectangleRec(checkBoxBounds, GetColor(style[CHECKBOX_HOVER_BORDER_COLOR]));
+            DrawRectangle((int)(checkBoxBounds.x + style[TOGGLE_BORDER_WIDTH]), (int)(checkBoxBounds.y + style[TOGGLE_BORDER_WIDTH]), (int)(checkBoxBounds.width - (2*style[TOGGLE_BORDER_WIDTH])), (int)(checkBoxBounds.height - (2*style[TOGGLE_BORDER_WIDTH])), GetColor(style[CHECKBOX_HOVER_INSIDE_COLOR]));        
+        } break;
+        case CHECKBOX_STATUS:
+        { 
+            DrawRectangleRec(checkBoxBounds, GetColor(style[CHECKBOX_DEFAULT_BORDER_COLOR]));
+            DrawRectangle((int)(checkBoxBounds.x + style[TOGGLE_BORDER_WIDTH]), (int)(checkBoxBounds.y + style[TOGGLE_BORDER_WIDTH]), (int)(checkBoxBounds.width - (2*style[TOGGLE_BORDER_WIDTH])), (int)(checkBoxBounds.height - (2*style[TOGGLE_BORDER_WIDTH])), GetColor(style[CHECKBOX_DEFAULT_INSIDE_COLOR]));
+        } break; 
+        case CHECKBOX_PRESSED:
+        {
+            DrawRectangleRec(checkBoxBounds, GetColor(style[CHECKBOX_CLICK_BORDER_COLOR]));
+            DrawRectangle((int)(checkBoxBounds.x + style[TOGGLE_BORDER_WIDTH]), (int)(checkBoxBounds.y + style[TOGGLE_BORDER_WIDTH]), (int)(checkBoxBounds.width - (2*style[TOGGLE_BORDER_WIDTH])), (int)(checkBoxBounds.height - (2*style[TOGGLE_BORDER_WIDTH])), GetColor(style[CHECKBOX_CLICK_INSIDE_COLOR]));
+        } break;
+        default: break;               
+    }
+    
+    if (text != NULL) DrawText(text, checkBoxBounds.x + checkBoxBounds.width + 2, checkBoxBounds.y + ((checkBoxBounds.height/2) - (style[GLOBAL_TEXT_FONTSIZE]/2) + 1), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[LABEL_TEXT_COLOR]));
+
+    if (checked)
+    {
+        DrawRectangle((int)(checkBoxBounds.x + style[CHECKBOX_INSIDE_WIDTH]), (int)(checkBoxBounds.y + style[CHECKBOX_INSIDE_WIDTH]), (int)(checkBoxBounds.width - (2*style[CHECKBOX_INSIDE_WIDTH])), (int)(checkBoxBounds.height - (2*style[CHECKBOX_INSIDE_WIDTH])), GetColor(style[CHECKBOX_STATUS_ACTIVE_COLOR]));
+    }
+    //--------------------------------------------------------------------
+    
+    return checked;
+}
+
+// Slider element, returns selected value
+RAYGUIDEF float GuiSlider(Rectangle bounds, float value, float minValue, float maxValue)
+{
+    SliderState sliderState = SLIDER_DEFAULT;
+    float buttonTravelDistance = 0;
+    float sliderPos = 0;
+    Vector2 mousePoint = GetMousePosition();
+    
+    // Update control
+    //--------------------------------------------------------------------     
+    if (value < minValue) value = minValue;
+    else if (value >= maxValue) value = maxValue;
+    
+    sliderPos = (value - minValue)/(maxValue - minValue);
+    
+    Rectangle sliderButton;
+    sliderButton.width = ((int)(bounds.width - (2 * style[SLIDER_BUTTON_BORDER_WIDTH]))/10 - 8);
+    sliderButton.height =((int)(bounds.height - ( 2 * style[SLIDER_BORDER_WIDTH] + 2 * style[SLIDER_BUTTON_BORDER_WIDTH])));
+    
+    float sliderButtonMinPos = bounds.x + style[SLIDER_BORDER_WIDTH] + style[SLIDER_BUTTON_BORDER_WIDTH];
+    float sliderButtonMaxPos = bounds.x + bounds.width - (style[SLIDER_BORDER_WIDTH] + style[SLIDER_BUTTON_BORDER_WIDTH] + sliderButton.width);
+    
+    buttonTravelDistance = sliderButtonMaxPos - sliderButtonMinPos;
+    
+    sliderButton.x = ((int)(bounds.x + style[SLIDER_BORDER_WIDTH] + style[SLIDER_BUTTON_BORDER_WIDTH]) + (sliderPos * buttonTravelDistance));
+    sliderButton.y = ((int)(bounds.y + style[SLIDER_BORDER_WIDTH] + style[SLIDER_BUTTON_BORDER_WIDTH]));
+    
+    if (CheckCollisionPointRec(mousePoint, bounds))
+    {
+        sliderState = SLIDER_HOVER;
+        
+        if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) sliderState = SLIDER_ACTIVE;
+        
+        if ((sliderState == SLIDER_ACTIVE) && (IsMouseButtonDown(MOUSE_LEFT_BUTTON)))
+        {
+            sliderButton.x = mousePoint.x - sliderButton.width / 2;
+            
+            if (sliderButton.x <= sliderButtonMinPos) sliderButton.x = sliderButtonMinPos;
+            else if (sliderButton.x >= sliderButtonMaxPos) sliderButton.x = sliderButtonMaxPos;
+            
+            sliderPos = (sliderButton.x - sliderButtonMinPos) / buttonTravelDistance;
+        }   
+    }
+    else sliderState = SLIDER_DEFAULT;
+    //-------------------------------------------------------------------- 
+    
+    // Draw control
+    //--------------------------------------------------------------------
+    DrawRectangleRec(bounds, GetColor(style[SLIDER_BORDER_COLOR]));
+    DrawRectangle((int)(bounds.x + style[SLIDER_BORDER_WIDTH]), (int)(bounds.y + style[SLIDER_BORDER_WIDTH]), (int)(bounds.width - (2*style[SLIDER_BORDER_WIDTH])), (int)(bounds.height - (2*style[SLIDER_BORDER_WIDTH])), GetColor(style[SLIDER_INSIDE_COLOR]));
+    
+    switch (sliderState)
+    {
+        case SLIDER_DEFAULT: DrawRectangleRec(sliderButton, GetColor(style[SLIDER_DEFAULT_COLOR])); break;
+        case SLIDER_HOVER: DrawRectangleRec(sliderButton, GetColor(style[SLIDER_HOVER_COLOR])); break;
+        case SLIDER_ACTIVE: DrawRectangleRec(sliderButton, GetColor(style[SLIDER_ACTIVE_COLOR])); break;
+        default: break;
+    } 
+    //--------------------------------------------------------------------
+    
+    return minValue + (maxValue - minValue)*sliderPos;
+}
+
+// Slider Bar element, returns selected value
+RAYGUIDEF float GuiSliderBar(Rectangle bounds, float value, float minValue, float maxValue)
+{
+    SliderState sliderState = SLIDER_DEFAULT;
+    Vector2 mousePoint = GetMousePosition();
+    float fixedValue;
+    float fixedMinValue;
+    
+    fixedValue = value - minValue;
+    maxValue = maxValue - minValue;
+    fixedMinValue = 0;
+    
+    // Update control
+    //-------------------------------------------------------------------- 
+    if (fixedValue <= fixedMinValue) fixedValue = fixedMinValue;
+    else if (fixedValue >= maxValue) fixedValue = maxValue;
+ 
+    Rectangle sliderBar;
+
+    sliderBar.x = bounds.x + style[SLIDER_BORDER_WIDTH];
+    sliderBar.y = bounds.y + style[SLIDER_BORDER_WIDTH];
+    sliderBar.width = ((fixedValue*((float)bounds.width - 2*style[SLIDER_BORDER_WIDTH]))/(maxValue - fixedMinValue));
+    sliderBar.height = bounds.height - 2*style[SLIDER_BORDER_WIDTH];
+
+    if (CheckCollisionPointRec(mousePoint, bounds))
+    {
+        sliderState = SLIDER_HOVER;
+        
+        if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) 
+        {
+            sliderState = SLIDER_ACTIVE;
+            
+            sliderBar.width = (mousePoint.x - bounds.x - style[SLIDER_BORDER_WIDTH]);
+            
+            if (mousePoint.x <= (bounds.x + style[SLIDER_BORDER_WIDTH])) sliderBar.width = 0;
+            else if (mousePoint.x >= (bounds.x + bounds.width - style[SLIDER_BORDER_WIDTH])) sliderBar.width = bounds.width - 2*style[SLIDER_BORDER_WIDTH];
+        }
+    }
+    else sliderState = SLIDER_DEFAULT;
+
+    fixedValue = ((float)sliderBar.width*(maxValue - fixedMinValue))/((float)bounds.width - 2*style[SLIDER_BORDER_WIDTH]);
+    //-------------------------------------------------------------------- 
+    
+    // Draw control
+    //--------------------------------------------------------------------
+    DrawRectangleRec(bounds, GetColor(style[SLIDERBAR_BORDER_COLOR]));
+    DrawRectangle((int)(bounds.x + style[SLIDER_BORDER_WIDTH]), (int)(bounds.y + style[SLIDER_BORDER_WIDTH]) , (int)(bounds.width - (2*style[SLIDER_BORDER_WIDTH])), (int)(bounds.height - (2*style[SLIDER_BORDER_WIDTH])), GetColor(style[SLIDERBAR_INSIDE_COLOR]));
+    
+    switch (sliderState)
+    {
+        case SLIDER_DEFAULT: DrawRectangleRec(sliderBar, GetColor(style[SLIDERBAR_DEFAULT_COLOR])); break;
+        case SLIDER_HOVER: DrawRectangleRec(sliderBar, GetColor(style[SLIDERBAR_HOVER_COLOR])); break;
+        case SLIDER_ACTIVE: DrawRectangleRec(sliderBar, GetColor(style[SLIDERBAR_ACTIVE_COLOR])); break;
+        default: break;
+    }
+    
+    if (minValue < 0 && maxValue > 0) DrawRectangle((bounds.x + style[SLIDER_BORDER_WIDTH]) - (minValue * ((bounds.width - (style[SLIDER_BORDER_WIDTH]*2))/maxValue)), sliderBar.y, 1, sliderBar.height, GetColor(style[SLIDERBAR_ZERO_LINE_COLOR]));
+    //--------------------------------------------------------------------
+
+    return fixedValue + minValue;
+}
+
+// Progress Bar element, shows current progress value
+RAYGUIDEF void GuiProgressBar(Rectangle bounds, float value)
+{
+    if (value > 1.0f) value = 1.0f;
+    else if (value < 0.0f) value = 0.0f;
+
+    Rectangle progressBar = { bounds.x + style[PROGRESSBAR_BORDER_WIDTH], bounds.y + style[PROGRESSBAR_BORDER_WIDTH], bounds.width - (style[PROGRESSBAR_BORDER_WIDTH] * 2), bounds.height - (style[PROGRESSBAR_BORDER_WIDTH] * 2)};
+    Rectangle progressValue = { bounds.x + style[PROGRESSBAR_BORDER_WIDTH], bounds.y + style[PROGRESSBAR_BORDER_WIDTH], value * (bounds.width - (style[PROGRESSBAR_BORDER_WIDTH] * 2)), bounds.height - (style[PROGRESSBAR_BORDER_WIDTH] * 2)};
+
+    // Draw control
+    //--------------------------------------------------------------------
+    DrawRectangleRec(bounds, GetColor(style[PROGRESSBAR_BORDER_COLOR]));
+    DrawRectangleRec(progressBar, GetColor(style[PROGRESSBAR_INSIDE_COLOR]));
+    DrawRectangleRec(progressValue, GetColor(style[PROGRESSBAR_PROGRESS_COLOR]));
+    //--------------------------------------------------------------------
+}
+
+// Spinner element, returns selected value
+// NOTE: Requires static variables: framesCounter, valueSpeed - ERROR!
+RAYGUIDEF int GuiSpinner(Rectangle bounds, int value, int minValue, int maxValue)
+{
+    SpinnerState spinnerState = SPINNER_DEFAULT;
+    Rectangle labelBoxBound = { bounds.x + bounds.width/4 + 1, bounds.y, bounds.width/2, bounds.height };
+    Rectangle leftButtonBound = { bounds.x, bounds.y, bounds.width/4, bounds.height };
+    Rectangle rightButtonBound = { bounds.x + bounds.width - bounds.width/4 + 1, bounds.y, bounds.width/4, bounds.height };
+    Vector2 mousePoint = GetMousePosition();
+
+    int textWidth = MeasureText(FormatText("%i", value), style[GLOBAL_TEXT_FONTSIZE]);
+    //int textHeight = style[GLOBAL_TEXT_FONTSIZE];     // Unused variable
+    
+    int buttonSide = 0;
+    
+    static int framesCounter = 0;
+    static bool valueSpeed = false;;
+    
+    //if (comboBoxButton.width < textWidth) comboBoxButton.width = textWidth + style[TOGGLE_TEXT_PADDING];
+    //if (comboBoxButton.height < textHeight) comboBoxButton.height = textHeight + style[TOGGLE_TEXT_PADDING]/2;
+    
+    // Update control
+    //-------------------------------------------------------------------- 
+    if (CheckCollisionPointRec(mousePoint, leftButtonBound) || CheckCollisionPointRec(mousePoint, rightButtonBound) || CheckCollisionPointRec(mousePoint, labelBoxBound))
+    {
+        if (IsKeyDown(KEY_LEFT))
+        {
+            spinnerState = SPINNER_PRESSED;
+            buttonSide = 1;
+            
+            if (value > minValue) value -= 1;
+        }
+        else if (IsKeyDown(KEY_RIGHT))
+        {
+            spinnerState = SPINNER_PRESSED;
+            buttonSide = 2;
+            
+            if (value < maxValue) value += 1;
+        }
+    }
+    
+    if (CheckCollisionPointRec(mousePoint, leftButtonBound))
+    {
+       buttonSide = 1;
+       spinnerState = SPINNER_HOVER;
+       
+       if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
+       {
+            if (!valueSpeed) 
+            {
+                if (value > minValue) value--;
+                valueSpeed = true;
+            }
+            else framesCounter++;
+            
+            spinnerState = SPINNER_PRESSED;
+            
+            if (value > minValue) 
+            {
+                if (framesCounter >= 30) value -= 1;
+            }
+       }
+    }
+    else if (CheckCollisionPointRec(mousePoint, rightButtonBound))
+    {
+        buttonSide = 2;
+        spinnerState = SPINNER_HOVER;
+        
+        if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) 
+       {
+            if (!valueSpeed) 
+            {
+                if (value < maxValue) value++;
+                valueSpeed = true;
+            }
+            else framesCounter++;
+            
+            spinnerState = SPINNER_PRESSED;
+            
+            if (value < maxValue) 
+            {
+                if (framesCounter >= 30) value += 1;
+            }
+       }
+    }
+    else if (!CheckCollisionPointRec(mousePoint, labelBoxBound)) buttonSide = 0;
+    
+    if (IsMouseButtonUp(MOUSE_LEFT_BUTTON))
+    {
+        valueSpeed = false;
+        framesCounter = 0;
+    }
+    //-------------------------------------------------------------------- 
+    
+    // Draw control
+    //--------------------------------------------------------------------
+    switch (spinnerState)
+    {
+        case SPINNER_DEFAULT:
+        {
+            DrawRectangleRec(leftButtonBound, GetColor(style[SPINNER_DEFAULT_BUTTON_BORDER_COLOR]));
+            DrawRectangle(leftButtonBound.x + 2, leftButtonBound.y + 2, leftButtonBound.width - 4, leftButtonBound.height - 4, GetColor(style[SPINNER_DEFAULT_BUTTON_INSIDE_COLOR]));
+            
+            DrawRectangleRec(rightButtonBound, GetColor(style[SPINNER_DEFAULT_BUTTON_BORDER_COLOR]));
+            DrawRectangle(rightButtonBound.x + 2, rightButtonBound.y + 2, rightButtonBound.width - 4, rightButtonBound.height - 4, GetColor(style[SPINNER_DEFAULT_BUTTON_INSIDE_COLOR]));
+            
+            DrawText(FormatText("-"), leftButtonBound.x + (leftButtonBound.width/2 - (MeasureText(FormatText("+"), style[GLOBAL_TEXT_FONTSIZE]))/2), leftButtonBound.y + (leftButtonBound.height/2 - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_DEFAULT_SYMBOL_COLOR])); 
+            DrawText(FormatText("+"), rightButtonBound.x + (rightButtonBound.width/2 - (MeasureText(FormatText("-"), style[GLOBAL_TEXT_FONTSIZE]))/2), rightButtonBound.y + (rightButtonBound.height/2 - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_DEFAULT_SYMBOL_COLOR])); 
+            
+            DrawRectangleRec(labelBoxBound, GetColor(style[SPINNER_LABEL_BORDER_COLOR]));
+            DrawRectangle(labelBoxBound.x + 1, labelBoxBound.y + 1, labelBoxBound.width - 2, labelBoxBound.height - 2, GetColor(style[SPINNER_LABEL_INSIDE_COLOR]));
+            
+            DrawText(FormatText("%i", value), labelBoxBound.x + (labelBoxBound.width/2 - textWidth/2), labelBoxBound.y + (labelBoxBound.height/2 - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_DEFAULT_TEXT_COLOR]));
+        } break;
+        case SPINNER_HOVER:
+        {
+            if (buttonSide == 1)
+            {
+                DrawRectangleRec(leftButtonBound, GetColor(style[SPINNER_HOVER_BUTTON_BORDER_COLOR]));
+                DrawRectangle(leftButtonBound.x + 2, leftButtonBound.y + 2, leftButtonBound.width - 4, leftButtonBound.height - 4, GetColor(style[SPINNER_HOVER_BUTTON_INSIDE_COLOR]));
+                
+                DrawRectangleRec(rightButtonBound, GetColor(style[SPINNER_DEFAULT_BUTTON_BORDER_COLOR]));
+                DrawRectangle(rightButtonBound.x + 2, rightButtonBound.y + 2, rightButtonBound.width - 4, rightButtonBound.height - 4, GetColor(style[SPINNER_DEFAULT_BUTTON_INSIDE_COLOR]));
+                
+                DrawText(FormatText("-"), leftButtonBound.x + (leftButtonBound.width/2 - (MeasureText(FormatText("+"), style[GLOBAL_TEXT_FONTSIZE]))/2), leftButtonBound.y + (leftButtonBound.height/2 - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_HOVER_SYMBOL_COLOR])); 
+                DrawText(FormatText("+"), rightButtonBound.x + (rightButtonBound.width/2 - (MeasureText(FormatText("-"), style[GLOBAL_TEXT_FONTSIZE]))/2), rightButtonBound.y + (rightButtonBound.height/2 - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_DEFAULT_SYMBOL_COLOR])); 
+            }                
+            else if (buttonSide == 2)
+            {
+                DrawRectangleRec(leftButtonBound, GetColor(style[SPINNER_DEFAULT_BUTTON_BORDER_COLOR]));
+                DrawRectangle(leftButtonBound.x + 2, leftButtonBound.y + 2, leftButtonBound.width - 4, leftButtonBound.height - 4, GetColor(style[SPINNER_DEFAULT_BUTTON_INSIDE_COLOR]));
+                
+                DrawRectangleRec(rightButtonBound, GetColor(style[SPINNER_HOVER_BUTTON_BORDER_COLOR]));
+                DrawRectangle(rightButtonBound.x + 2, rightButtonBound.y + 2, rightButtonBound.width - 4, rightButtonBound.height - 4, GetColor(style[SPINNER_HOVER_BUTTON_INSIDE_COLOR]));
+                
+                DrawText(FormatText("-"), leftButtonBound.x + (leftButtonBound.width/2 - (MeasureText(FormatText("+"), style[GLOBAL_TEXT_FONTSIZE]))/2), leftButtonBound.y + (leftButtonBound.height/2 - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_DEFAULT_SYMBOL_COLOR])); 
+                DrawText(FormatText("+"), rightButtonBound.x + (rightButtonBound.width/2 - (MeasureText(FormatText("-"), style[GLOBAL_TEXT_FONTSIZE]))/2), rightButtonBound.y + (rightButtonBound.height/2 - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_HOVER_SYMBOL_COLOR])); 
+            }
+            
+            DrawRectangleRec(labelBoxBound, GetColor(style[SPINNER_LABEL_BORDER_COLOR]));
+            DrawRectangle(labelBoxBound.x + 1, labelBoxBound.y + 1, labelBoxBound.width - 2, labelBoxBound.height - 2, GetColor(style[SPINNER_LABEL_INSIDE_COLOR]));
+            
+            DrawText(FormatText("%i", value), labelBoxBound.x + (labelBoxBound.width/2 - textWidth/2), labelBoxBound.y + (labelBoxBound.height/2 - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_HOVER_TEXT_COLOR]));  
+        } break;
+        case SPINNER_PRESSED:
+        {
+            if (buttonSide == 1)
+            {
+                DrawRectangleRec(leftButtonBound, GetColor(style[SPINNER_PRESSED_BUTTON_BORDER_COLOR]));
+                DrawRectangle(leftButtonBound.x + 2, leftButtonBound.y + 2, leftButtonBound.width - 4, leftButtonBound.height - 4, GetColor(style[SPINNER_PRESSED_BUTTON_INSIDE_COLOR]));
+                
+                DrawRectangleRec(rightButtonBound, GetColor(style[SPINNER_DEFAULT_BUTTON_BORDER_COLOR]));
+                DrawRectangle(rightButtonBound.x + 2, rightButtonBound.y + 2, rightButtonBound.width - 4, rightButtonBound.height - 4, GetColor(style[SPINNER_DEFAULT_BUTTON_INSIDE_COLOR]));
+                
+                DrawText(FormatText("-"), leftButtonBound.x + (leftButtonBound.width/2 - (MeasureText(FormatText("+"), style[GLOBAL_TEXT_FONTSIZE]))/2), leftButtonBound.y + (leftButtonBound.height/2 - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_PRESSED_SYMBOL_COLOR])); 
+                DrawText(FormatText("+"), rightButtonBound.x + (rightButtonBound.width/2 - (MeasureText(FormatText("-"), style[GLOBAL_TEXT_FONTSIZE]))/2), rightButtonBound.y + (rightButtonBound.height/2 - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_DEFAULT_SYMBOL_COLOR])); 
+            }
+            else if (buttonSide == 2)
+            {
+                DrawRectangleRec(leftButtonBound, GetColor(style[SPINNER_DEFAULT_BUTTON_BORDER_COLOR]));
+                DrawRectangle(leftButtonBound.x + 2, leftButtonBound.y + 2, leftButtonBound.width - 4, leftButtonBound.height - 4, GetColor(style[SPINNER_DEFAULT_BUTTON_INSIDE_COLOR]));
+                
+                DrawRectangleRec(rightButtonBound, GetColor(style[SPINNER_PRESSED_BUTTON_BORDER_COLOR]));
+                DrawRectangle(rightButtonBound.x + 2, rightButtonBound.y + 2, rightButtonBound.width - 4, rightButtonBound.height - 4, GetColor(style[SPINNER_PRESSED_BUTTON_INSIDE_COLOR]));
+                
+                DrawText(FormatText("-"), leftButtonBound.x + (leftButtonBound.width/2 - (MeasureText(FormatText("+"), style[GLOBAL_TEXT_FONTSIZE]))/2), leftButtonBound.y + (leftButtonBound.height/2 - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_DEFAULT_SYMBOL_COLOR])); 
+                DrawText(FormatText("+"), rightButtonBound.x + (rightButtonBound.width/2 - (MeasureText(FormatText("-"), style[GLOBAL_TEXT_FONTSIZE]))/2), rightButtonBound.y + (rightButtonBound.height/2 - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_PRESSED_SYMBOL_COLOR])); 
+            }
+            
+            DrawRectangleRec(labelBoxBound, GetColor(style[SPINNER_LABEL_BORDER_COLOR]));
+            DrawRectangle(labelBoxBound.x + 1, labelBoxBound.y + 1, labelBoxBound.width - 2, labelBoxBound.height - 2, GetColor(style[SPINNER_LABEL_INSIDE_COLOR]));
+            
+            DrawText(FormatText("%i", value), labelBoxBound.x + (labelBoxBound.width/2 - textWidth/2), labelBoxBound.y + (labelBoxBound.height/2 - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_PRESSED_TEXT_COLOR]));  
+        } break;
+        default: break;
+    }
+    
+    return value;
+}
+
+// Text Box element, returns input text
+// NOTE: Requires static variables: framesCounter - ERROR!
+RAYGUIDEF char *GuiTextBox(Rectangle bounds, char *text)
+{
+    #define MAX_CHARS_LENGTH  	 20
+    #define KEY_BACKSPACE_TEXT  259     // GLFW BACKSPACE: 3 + 256
+    
+    int initPos = bounds.x + 4;
+    int letter = -1;
+    static int framesCounter = 0;
+    Vector2 mousePoint = GetMousePosition();
+    
+    // Update control
+    //-------------------------------------------------------------------- 
+    framesCounter++;
+    
+    letter = GetKeyPressed();
+  
+    if (CheckCollisionPointRec(mousePoint, bounds)) 
+    {        
+        if (letter != -1)
+        {
+            if (letter == KEY_BACKSPACE_TEXT)
+            {
+                for (int i = 0; i < MAX_CHARS_LENGTH; i++)
+                {
+                    if ((text[i] == '\0') && (i > 0))
+                    {
+                        text[i - 1] = '\0';
+                        break;
+                    }
+                }
+                
+                text[MAX_CHARS_LENGTH - 1] = '\0';
+            }
+            else
+            {
+                if ((letter >= 32) && (letter < 127))
+                {
+                    for (int i = 0; i < MAX_CHARS_LENGTH; i++)
+                    {
+                        if (text[i] == '\0')
+                        {
+                            text[i] = (char)letter;
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    //-------------------------------------------------------------------- 
+
+    // Draw control
+    //--------------------------------------------------------------------
+    if (CheckCollisionPointRec(mousePoint, bounds)) DrawRectangleRec(bounds, GetColor(style[TOGGLE_ACTIVE_BORDER_COLOR]));
+    else DrawRectangleRec(bounds, GetColor(style[TEXTBOX_BORDER_COLOR]));
+    
+    DrawRectangle(bounds.x + style[TEXTBOX_BORDER_WIDTH], bounds.y + style[TEXTBOX_BORDER_WIDTH], bounds.width - (style[TEXTBOX_BORDER_WIDTH] * 2), bounds.height - (style[TEXTBOX_BORDER_WIDTH] * 2), GetColor(style[TEXTBOX_INSIDE_COLOR]));
+    
+    for (int i = 0; i < MAX_CHARS_LENGTH; i++)
+    {
+        if (text[i] == '\0') break;
+        
+        DrawText(FormatText("%c", text[i]), initPos, bounds.y + style[TEXTBOX_TEXT_FONTSIZE], style[TEXTBOX_TEXT_FONTSIZE], GetColor(style[TEXTBOX_TEXT_COLOR]));
+        
+        initPos += (MeasureText(FormatText("%c", text[i]), style[GLOBAL_TEXT_FONTSIZE]) + 2);
+        //initPos += ((GetDefaultFont().charRecs[(int)text[i] - 32].width + 2));
+    }
+
+    if ((framesCounter/20)%2 && CheckCollisionPointRec(mousePoint, bounds)) DrawRectangle(initPos + 2, bounds.y + 5, 1, 20, GetColor(style[TEXTBOX_LINE_COLOR]));
+    //--------------------------------------------------------------------    
+
+    return text;
+}
+
+// Save current GUI style into a text file
+RAYGUIDEF void SaveGuiStyle(const char *fileName)
+{
+    FILE *styleFile = fopen(fileName, "wt");
+    
+    for (int i = 0; i < NUM_PROPERTIES; i++) fprintf(styleFile, "%-40s0x%x\n", guiPropertyName[i], GetStyleProperty(i));
+    
+    fclose(styleFile);
+}
+
+// Load GUI style from a text file
+RAYGUIDEF void LoadGuiStyle(const char *fileName)
+{
+    #define MAX_STYLE_PROPERTIES    128
+    
+    typedef struct {
+        char id[64];
+        int value;
+    } StyleProperty;
+    
+    StyleProperty *styleProp = (StyleProperty *)RAYGUI_MALLOC(MAX_STYLE_PROPERTIES*sizeof(StyleProperty));; 
+    int counter = 0;
+    
+    FILE *styleFile = fopen(fileName, "rt");
+
+    while (!feof(styleFile))
+    {
+        fscanf(styleFile, "%s %i\n", styleProp[counter].id, &styleProp[counter].value);
+        counter++;
+    }
+
+    fclose(styleFile);
+
+    for (int i = 0; i < counter; i++)
+    {
+        for (int j = 0; j < NUM_PROPERTIES; j++)
+        {
+            if (strcmp(styleProp[i].id, guiPropertyName[j]) == 0)
+            {
+                // Assign correct property to style
+                style[j] = styleProp[i].value;
+            }
+        }
+    }
+    
+    RAYGUI_FREE(styleProp);
+}
+
+// Set one style property value
+RAYGUIDEF void SetStyleProperty(int guiProperty, int value) 
+{
+    #define NUM_COLOR_SAMPLES   10
+    
+    if (guiProperty == GLOBAL_BASE_COLOR)
+    {
+        Color baseColor = GetColor(value);
+        Color fadeColor[NUM_COLOR_SAMPLES];
+        
+        for (int i = 0; i < NUM_COLOR_SAMPLES; i++) fadeColor[i] = ColorMultiply(baseColor, 1.0f - (float)i/(NUM_COLOR_SAMPLES - 1));
+        
+        style[GLOBAL_BASE_COLOR] = value;
+        style[BACKGROUND_COLOR] = GetHexValue(fadeColor[3]);
+        style[BUTTON_DEFAULT_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
+        style[BUTTON_HOVER_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
+        style[BUTTON_PRESSED_INSIDE_COLOR] = GetHexValue(fadeColor[5]);
+        style[TOGGLE_DEFAULT_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
+        style[TOGGLE_HOVER_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
+        style[TOGGLE_PRESSED_INSIDE_COLOR] = GetHexValue(fadeColor[5]);
+        style[TOGGLE_ACTIVE_INSIDE_COLOR] = GetHexValue(fadeColor[8]);
+        style[SLIDER_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
+        style[SLIDER_DEFAULT_COLOR] = GetHexValue(fadeColor[6]);
+        style[SLIDER_HOVER_COLOR] = GetHexValue(fadeColor[7]);
+        style[SLIDER_ACTIVE_COLOR] = GetHexValue(fadeColor[9]);
+        style[SLIDERBAR_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
+        style[SLIDERBAR_DEFAULT_COLOR] = GetHexValue(fadeColor[6]);
+        style[SLIDERBAR_HOVER_COLOR] = GetHexValue(fadeColor[7]);
+        style[SLIDERBAR_ACTIVE_COLOR] = GetHexValue(fadeColor[9]);
+        style[SLIDERBAR_ZERO_LINE_COLOR] = GetHexValue(fadeColor[8]);
+        style[PROGRESSBAR_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
+        style[PROGRESSBAR_PROGRESS_COLOR] = GetHexValue(fadeColor[6]);
+        style[SPINNER_LABEL_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
+        style[SPINNER_DEFAULT_BUTTON_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
+        style[SPINNER_HOVER_BUTTON_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
+        style[SPINNER_PRESSED_BUTTON_INSIDE_COLOR] = GetHexValue(fadeColor[5]);
+        style[COMBOBOX_DEFAULT_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
+        style[COMBOBOX_HOVER_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
+        style[COMBOBOX_PRESSED_INSIDE_COLOR] = GetHexValue(fadeColor[8]);
+        style[COMBOBOX_PRESSED_LIST_INSIDE_COLOR] = GetHexValue(fadeColor[8]);
+        style[CHECKBOX_DEFAULT_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
+        style[CHECKBOX_CLICK_INSIDE_COLOR] = GetHexValue(fadeColor[6]);
+        style[CHECKBOX_STATUS_ACTIVE_COLOR] = GetHexValue(fadeColor[8]);
+        style[TEXTBOX_INSIDE_COLOR] = GetHexValue(fadeColor[4]);
+    }
+    else if (guiProperty == GLOBAL_BORDER_COLOR)
+    {
+        Color baseColor = GetColor(value);
+        Color fadeColor[NUM_COLOR_SAMPLES];
+        
+        for (int i = 0; i < NUM_COLOR_SAMPLES; i++) fadeColor[i] = ColorMultiply(baseColor, 1.0f - (float)i/(NUM_COLOR_SAMPLES - 1));
+        
+        style[GLOBAL_BORDER_COLOR] = value;
+        style[BUTTON_DEFAULT_BORDER_COLOR] = GetHexValue(fadeColor[7]);
+        style[BUTTON_HOVER_BORDER_COLOR] = GetHexValue(fadeColor[8]);
+        style[BUTTON_PRESSED_BORDER_COLOR] = GetHexValue(fadeColor[9]);
+        style[TOGGLE_DEFAULT_BORDER_COLOR] = GetHexValue(fadeColor[7]);
+        style[TOGGLE_HOVER_BORDER_COLOR] = GetHexValue(fadeColor[8]);
+        style[TOGGLE_PRESSED_BORDER_COLOR] = GetHexValue(fadeColor[9]);
+        style[TOGGLE_ACTIVE_BORDER_COLOR] = GetHexValue(fadeColor[9]);
+        style[SLIDER_BORDER_COLOR] = GetHexValue(fadeColor[7]);
+        style[SLIDERBAR_BORDER_COLOR] = GetHexValue(fadeColor[7]);
+        style[PROGRESSBAR_BORDER_COLOR] = GetHexValue(fadeColor[7]);
+        style[SPINNER_LABEL_BORDER_COLOR] = GetHexValue(fadeColor[7]);
+        style[SPINNER_DEFAULT_BUTTON_BORDER_COLOR] = GetHexValue(fadeColor[7]);
+        style[SPINNER_HOVER_BUTTON_BORDER_COLOR] = GetHexValue(fadeColor[8]);
+        style[SPINNER_PRESSED_BUTTON_BORDER_COLOR] = GetHexValue(fadeColor[9]);
+        style[COMBOBOX_DEFAULT_BORDER_COLOR] = GetHexValue(fadeColor[7]);
+        style[COMBOBOX_HOVER_BORDER_COLOR] = GetHexValue(fadeColor[8]);
+        style[COMBOBOX_PRESSED_BORDER_COLOR] = GetHexValue(fadeColor[9]);
+        style[COMBOBOX_PRESSED_LIST_BORDER_COLOR] = GetHexValue(fadeColor[9]);
+        style[CHECKBOX_DEFAULT_BORDER_COLOR] = GetHexValue(fadeColor[7]);
+        style[CHECKBOX_HOVER_BORDER_COLOR] = GetHexValue(fadeColor[8]);
+        style[CHECKBOX_CLICK_BORDER_COLOR] = GetHexValue(fadeColor[9]);
+        style[TEXTBOX_BORDER_COLOR] = GetHexValue(fadeColor[7]);
+    }
+    else if (guiProperty == GLOBAL_TEXT_COLOR)
+    {
+        Color baseColor = GetColor(value);
+        Color fadeColor[NUM_COLOR_SAMPLES];
+        
+        for (int i = 0; i < NUM_COLOR_SAMPLES; i++) fadeColor[i] = ColorMultiply(baseColor, 1.0f - (float)i/(NUM_COLOR_SAMPLES - 1));
+        
+        style[GLOBAL_TEXT_COLOR] = value;
+        style[LABEL_TEXT_COLOR] = GetHexValue(fadeColor[9]);
+        style[BUTTON_DEFAULT_TEXT_COLOR] = GetHexValue(fadeColor[9]);
+        style[BUTTON_HOVER_TEXT_COLOR] = GetHexValue(fadeColor[8]);
+        style[BUTTON_PRESSED_TEXT_COLOR] = GetHexValue(fadeColor[5]);
+        style[TOGGLE_DEFAULT_TEXT_COLOR] = GetHexValue(fadeColor[9]);
+        style[TOGGLE_HOVER_TEXT_COLOR] = GetHexValue(fadeColor[8]);
+        style[TOGGLE_PRESSED_TEXT_COLOR] = GetHexValue(fadeColor[5]);
+        style[TOGGLE_ACTIVE_TEXT_COLOR] = GetHexValue(fadeColor[5]);
+        style[SPINNER_DEFAULT_SYMBOL_COLOR] = GetHexValue(fadeColor[9]);
+        style[SPINNER_DEFAULT_TEXT_COLOR] = GetHexValue(fadeColor[9]);
+        style[SPINNER_HOVER_SYMBOL_COLOR] = GetHexValue(fadeColor[8]);
+        style[SPINNER_HOVER_TEXT_COLOR] = GetHexValue(fadeColor[8]);
+        style[SPINNER_PRESSED_SYMBOL_COLOR] = GetHexValue(fadeColor[5]);
+        style[SPINNER_PRESSED_TEXT_COLOR] = GetHexValue(fadeColor[5]);
+        style[COMBOBOX_DEFAULT_TEXT_COLOR] = GetHexValue(fadeColor[9]);
+        style[COMBOBOX_DEFAULT_LIST_TEXT_COLOR] = GetHexValue(fadeColor[9]);
+        style[COMBOBOX_HOVER_TEXT_COLOR] = GetHexValue(fadeColor[8]);
+        style[COMBOBOX_HOVER_LIST_TEXT_COLOR] = GetHexValue(fadeColor[8]);
+        style[COMBOBOX_PRESSED_TEXT_COLOR] = GetHexValue(fadeColor[4]);
+        style[COMBOBOX_PRESSED_LIST_TEXT_COLOR] = GetHexValue(fadeColor[4]);
+        style[TEXTBOX_TEXT_COLOR] = GetHexValue(fadeColor[9]);
+        style[TEXTBOX_LINE_COLOR] = GetHexValue(fadeColor[6]);
+    }
+    else style[guiProperty] = value; 
+
+}
+
+// Get one style property value
+RAYGUIDEF int GetStyleProperty(int guiProperty) { return style[guiProperty]; }
+
+//----------------------------------------------------------------------------------
+// Module specific Functions Definition
+//----------------------------------------------------------------------------------
+
+static Color ColorMultiply(Color baseColor, float value)
+{
+    Color multColor = baseColor;
+
+    if (value > 1.0f) value = 1.0f;
+    else if (value < 0.0f) value = 0.0f;
+    
+    multColor.r += (255 - multColor.r)*value;
+    multColor.g += (255 - multColor.g)*value;
+    multColor.b += (255 - multColor.b)*value;
+    
+    return multColor;
+}
+
+#if defined (RAYGUI_STANDALONE)
+// Returns a Color struct from hexadecimal value
+static Color GetColor(int hexValue)
+{
+    Color color;
+
+    color.r = (unsigned char)(hexValue >> 24) & 0xFF;
+    color.g = (unsigned char)(hexValue >> 16) & 0xFF;
+    color.b = (unsigned char)(hexValue >> 8) & 0xFF;
+    color.a = (unsigned char)hexValue & 0xFF;
+
+    return color;
+}
+
+// Returns hexadecimal value for a Color
+static int GetHexValue(Color color)
+{
+    return (((int)color.r << 24) | ((int)color.g << 16) | ((int)color.b << 8) | (int)color.a);
+}
+
+// Check if point is inside rectangle
+static bool CheckCollisionPointRec(Vector2 point, Rectangle rec)
+{
+    bool collision = false;
+
+    if ((point.x >= rec.x) && (point.x <= (rec.x + rec.width)) && (point.y >= rec.y) && (point.y <= (rec.y + rec.height))) collision = true;
+
+    return collision;
+}
+
+// Formatting of text with variables to 'embed'
+static const char *FormatText(const char *text, ...)
+{
+    #define MAX_FORMATTEXT_LENGTH   64
+    
+    static char buffer[MAX_FORMATTEXT_LENGTH];
+
+    va_list args;
+    va_start(args, text);
+    vsprintf(buffer, text, args);
+    va_end(args);
+
+    return buffer;
 }
 #endif
 
-#endif // RAYGUI_H
+#endif // RAYGUI_IMPLEMENTATION
+

+ 31 - 71
src/raylib.h

@@ -64,7 +64,7 @@
 //#define PLATFORM_ANDROID      // Android device
 //#define PLATFORM_RPI          // Raspberry Pi
 //#define PLATFORM_WEB          // HTML5 (emscripten, asm.js)
-//#define PLATFORM_OCULUS       // Oculus Rift CV1
+//#define RLGL_OCULUS_SUPPORT   // Oculus Rift CV1 (complementary to PLATFORM_DESKTOP)
 
 // Security check in case no PLATFORM_* defined
 #if !defined(PLATFORM_DESKTOP) && !defined(PLATFORM_ANDROID) && !defined(PLATFORM_RPI) && !defined(PLATFORM_WEB)
@@ -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,39 +525,18 @@ typedef struct GestureEvent {
 // Camera system modes
 typedef enum { CAMERA_CUSTOM = 0, CAMERA_FREE, CAMERA_ORBITAL, CAMERA_FIRST_PERSON, CAMERA_THIRD_PERSON } CameraMode;
 
-typedef enum { COLLIDER_CIRCLE, COLLIDER_RECTANGLE } ColliderType;
-
-typedef struct Transform {
-    Vector2 position;
-    float rotation;         // Radians (not used)
-    Vector2 scale;          // Just for rectangle physic objects, for circle physic objects use collider radius and keep scale as { 0, 0 }
-} Transform;
-
-typedef struct Rigidbody {
-    bool enabled;           // Acts as kinematic state (collisions are calculated anyway)
-    float mass;
-    Vector2 acceleration;
-    Vector2 velocity;
-    bool applyGravity;
-    bool isGrounded;
-    float friction;         // Normalized value
-    float bounciness;
-} Rigidbody;
-
-typedef struct Collider {
-    bool enabled;
-    ColliderType type;
-    Rectangle bounds;       // Used for COLLIDER_RECTANGLE
-    int radius;             // Used for COLLIDER_CIRCLE
-} Collider;
-
-typedef struct PhysicObjectData {
-    unsigned int id;
-    Transform transform;
-    Rigidbody rigidbody;
-    Collider collider;
-    bool enabled;
-} PhysicObjectData, *PhysicObject;
+// 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
@@ -579,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)
@@ -678,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
@@ -834,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)
@@ -886,20 +856,17 @@ void EndBlendMode(void);                                            // End blend
 Light CreateLight(int type, Vector3 position, Color diffuse);       // Create a new light, initialize it and add to pool
 void DestroyLight(Light light);                                     // Destroy a light and take it out of the list
 
-//----------------------------------------------------------------------------------
-// Physics System Functions (Module: physac)
-//----------------------------------------------------------------------------------
-void InitPhysics(Vector2 gravity);                                                      // Initializes pointers array (just pointers, fixed size)
-void UpdatePhysics();                                                                   // Update physic objects, calculating physic behaviours and collisions detection
-void ClosePhysics();                                                                    // Unitialize all physic objects and empty the objects pool
-
-PhysicObject CreatePhysicObject(Vector2 position, float rotation, Vector2 scale);       // Create a new physic object dinamically, initialize it and add to pool
-void DestroyPhysicObject(PhysicObject pObj);                                            // Destroy a specific physic object and take it out of the list
-
-void ApplyForce(PhysicObject pObj, Vector2 force);                                      // Apply directional force to a physic object
-void ApplyForceAtPosition(Vector2 position, float force, float radius);                 // Apply radial force to all physic objects in range
-
-Rectangle TransformToRectangle(Transform transform);                                    // Convert Transform data type to Rectangle (position and scale)
+//------------------------------------------------------------------------------------
+// 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)
@@ -926,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
 }

+ 8 - 10
src/raymath.h

@@ -47,10 +47,16 @@
     #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 extern inline
+    #define RMDEF RMEXTERN inline   // Functions are embeded inline (compiler generated code)
 #else
-    #define RMDEF extern
+    #define RMDEF RMEXTERN
 #endif
 
 //----------------------------------------------------------------------------------
@@ -105,10 +111,6 @@ typedef struct Quaternion {
 
 #ifndef RAYMATH_EXTERN_INLINE
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 //------------------------------------------------------------------------------------
 // Functions Declaration to work with Vector3
 //------------------------------------------------------------------------------------
@@ -166,10 +168,6 @@ RMDEF Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle);  // Returns
 RMDEF void QuaternionToAxisAngle(Quaternion q, Vector3 *outAxis, float *outAngle); // Returns the rotation angle and axis for a given quaternion
 RMDEF void QuaternionTransform(Quaternion *q, Matrix mat);            // Transform a quaternion given a transformation matrix
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif  // notdef RAYMATH_EXTERN_INLINE
 
 #endif  // RAYMATH_H

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 607 - 160
src/rlgl.c


+ 27 - 8
src/rlgl.h

@@ -48,25 +48,31 @@
 
 // Choose opengl version here or just define it at compile time: -DGRAPHICS_API_OPENGL_33
 //#define GRAPHICS_API_OPENGL_11     // Only available on PLATFORM_DESKTOP
-//#define GRAPHICS_API_OPENGL_33     // Only available on PLATFORM_DESKTOP
+//#define GRAPHICS_API_OPENGL_33     // Only available on PLATFORM_DESKTOP and RLGL_OCULUS_SUPPORT
 //#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)
+#if !defined(GRAPHICS_API_OPENGL_11) && !defined(GRAPHICS_API_OPENGL_21) && !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_21)
+        #undef GRAPHICS_API_OPENGL_21
+    #endif
     #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
 
+#if defined(GRAPHICS_API_OPENGL_21)
+    #define GRAPHICS_API_OPENGL_33
+#endif
+
 //----------------------------------------------------------------------------------
 // Defines and Macros
 //----------------------------------------------------------------------------------
@@ -90,7 +96,7 @@ 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;
+typedef enum { OPENGL_11 = 1, OPENGL_21, OPENGL_33, OPENGL_ES_20 } GlVersion;
 
 #if defined(RLGL_STANDALONE)
     #ifndef __cplusplus
@@ -212,9 +218,9 @@ typedef enum { OPENGL_11 = 1, 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)
@@ -230,6 +236,9 @@ typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion;
 
     // 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
@@ -289,10 +298,10 @@ int rlGetVersion(void);                         // Returns current OpenGL versio
 //------------------------------------------------------------------------------------
 // Functions Declaration - rlgl functionality
 //------------------------------------------------------------------------------------
-void rlglInit(void);                            // Initialize rlgl (shaders, VAO, VBO...)
+void rlglInit(int width, int height);           // Initialize rlgl (buffers, shaders, textures, states)
 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)
@@ -339,6 +348,16 @@ 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
+
+void TraceLog(int msgType, const char *text, ...);
+
+void InitVrDevice(int hmdDevice);           // Init VR device
+void CloseVrDevice(void);                   // Close VR device
+void UpdateVrTracking(void);                // Update VR tracking (position and orientation)
+void BeginVrDrawing(void);                  // Begin VR drawing configuration
+void EndVrDrawing(void);                    // End VR drawing process (and desktop mirror)
+bool IsVrDeviceReady(void);                 // Detect if VR device (or simulator) is ready
+void ToggleVrMode(void);                    // Enable/Disable VR experience (device or simulator)
 #endif
 
 #ifdef __cplusplus

+ 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";

+ 173 - 0
src/shader_standard.h

@@ -0,0 +1,173 @@
+
+// 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 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 < maxLights; 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_ES2) || defined(GRAPHICS_API_OPENGL_21)
+"   gl_FragColor = vec4(texelColor.rgb*lighting*colDiffuse.rgb, texelColor.a*colDiffuse.a); \n"
+#elif defined(GRAPHICS_API_OPENGL_33)
+"   finalColor = vec4(texelColor.rgb*lighting*colDiffuse.rgb, texelColor.a*colDiffuse.a); \n"
+#endif
+"}\n";

+ 6 - 6
src/shapes.c

@@ -44,7 +44,7 @@
 //----------------------------------------------------------------------------------
 // Global Variables Definition
 //----------------------------------------------------------------------------------
-extern unsigned int whiteTexture;
+// ...
 
 //----------------------------------------------------------------------------------
 // Module specific Functions Declaration
@@ -135,9 +135,9 @@ void DrawCircleV(Vector2 center, float radius, Color color)
             }
         rlEnd();
     }
-    else if ((rlGetVersion() == OPENGL_33) || (rlGetVersion() == OPENGL_ES_20))
+    else if ((rlGetVersion() == OPENGL_21) || (rlGetVersion() == OPENGL_33) || (rlGetVersion() == OPENGL_ES_20))
     {
-        rlEnableTexture(whiteTexture); // Default white texture
+        rlEnableTexture(GetDefaultTexture().id); // Default white texture
 
         rlBegin(RL_QUADS);
             for (int i = 0; i < 360; i += 20)
@@ -218,9 +218,9 @@ void DrawRectangleV(Vector2 position, Vector2 size, Color color)
             rlVertex2i(position.x + size.x, position.y);
         rlEnd();
     }
-    else if ((rlGetVersion() == OPENGL_33) || (rlGetVersion() == OPENGL_ES_20))
+    else if ((rlGetVersion() == OPENGL_21) || (rlGetVersion() == OPENGL_33) || (rlGetVersion() == OPENGL_ES_20))
     {
-        rlEnableTexture(whiteTexture); // Default white texture
+        rlEnableTexture(GetDefaultTexture().id); // Default white texture
 
         rlBegin(RL_QUADS);
             rlColor4ub(color.r, color.g, color.b, color.a);
@@ -264,7 +264,7 @@ void DrawRectangleLines(int posX, int posY, int width, int height, Color color)
             rlVertex2i(posX + 1, posY + 1);
         rlEnd();
     }
-    else if ((rlGetVersion() == OPENGL_33) || (rlGetVersion() == OPENGL_ES_20))
+    else if ((rlGetVersion() == OPENGL_21) || (rlGetVersion() == OPENGL_33) || (rlGetVersion() == OPENGL_ES_20))
     {
         DrawRectangle(posX, posY, width, 1, color);
         DrawRectangle(posX + width - 1, posY + 1, 1, height - 2, 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();

+ 1 - 6
src/textures.c

@@ -422,12 +422,7 @@ void UnloadTexture(Texture2D texture)
 // Unload render texture from GPU memory
 void UnloadRenderTexture(RenderTexture2D target)
 {
-    if (target.id != 0)
-    {
-        rlDeleteRenderTextures(target);
-        
-        TraceLog(INFO, "[FBO ID %i] Unloaded render texture data from VRAM (GPU)", target.id);
-    }
+    if (target.id != 0) rlDeleteRenderTextures(target);
 }
 
 // Get pixel data from image in the form of Color struct array

+ 1 - 1
templates/android_project/jni/Android.mk

@@ -83,7 +83,7 @@ LOCAL_SRC_FILES  := basic_game.c
 LOCAL_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)/include
 
 # Required flags for compilation: defines PLATFORM_ANDROID
-LOCAL_CFLAGS     := -Wall -std=c99 -g -DPLATFORM_ANDROID
+LOCAL_CFLAGS     := -Wall -std=c99 -DPLATFORM_ANDROID
 
 # Linker required libraries (not many...)
 LOCAL_LDLIBS     := -llog -landroid -lEGL -lGLESv2 -lOpenSLES

+ 5 - 5
templates/android_project/jni/basic_game.c

@@ -43,7 +43,7 @@ void android_main(struct android_app *app)
 
     int framesCounter = 0;          // Used to count frames
     
-    PlayMusicStream("ambient.ogg");
+    PlayMusicStream(0, "ambient.ogg");
     
     SetTargetFPS(60);               // Not required on Android, already locked to 60 fps
     //--------------------------------------------------------------------------------------
@@ -53,7 +53,7 @@ void android_main(struct android_app *app)
     {
         // Update
         //----------------------------------------------------------------------------------
-        UpdateMusicStream();
+        UpdateMusicStream(0);
         
         switch(currentScreen) 
         {
@@ -74,7 +74,7 @@ void android_main(struct android_app *app)
                 // TODO: Update TITLE screen variables here!
 
                 // Press enter to change to GAMEPLAY screen
-                if (GetGestureType() == GESTURE_TAP)
+                if (IsGestureDetected(GESTURE_TAP))
                 {
                     PlaySound(fx);
                     currentScreen = GAMEPLAY;
@@ -85,7 +85,7 @@ void android_main(struct android_app *app)
                 // TODO: Update GAMEPLAY screen variables here!
 
                 // Press enter to change to ENDING screen
-                if (GetGestureType() == GESTURE_TAP)
+                if (IsGestureDetected(GESTURE_TAP))
                 {  
                     PlaySound(fx);
                     currentScreen = ENDING;
@@ -96,7 +96,7 @@ void android_main(struct android_app *app)
                 // TODO: Update ENDING screen variables here!
 
                 // Press enter to return to TITLE screen
-                if (GetGestureType() == GESTURE_TAP)
+                if (IsGestureDetected(GESTURE_TAP))
                 {
                     PlaySound(fx);
                     currentScreen = TITLE;

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است