Merge pull request #132 from raysan5/develop

Develop branch integration
This commit is contained in:
Ray 2016-07-15 19:44:18 +02:00 committed by GitHub
commit a2794379a0
91 changed files with 18349 additions and 22777 deletions

6
.gitignore vendored
View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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 - raysan@raysanweb.com)
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.

View File

@ -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:raysan5@gmail.com "Ramon Santamaria - Ray San"

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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
//--------------------------------------------------------------------------------------

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

View File

@ -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();
//----------------------------------------------------------------------------------

View File

@ -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

View File

@ -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

View File

@ -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

View File

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

View File

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

View File

@ -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);
#if defined(PLATFORM_OCULUS)
// 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);
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 };
#if defined(PLATFORM_OCULUS)
ovrResult result = ovr_Initialize(NULL);
if (OVR_FAILURE(result)) TraceLog(ERROR, "OVR: Could not initialize Oculus device");
result = ovr_Create(&session, &luid);
if (OVR_FAILURE(result))
{
TraceLog(WARNING, "OVR: Could not create Oculus session");
ovr_Shutdown();
}
hmdDesc = ovr_GetHmdDesc(session);
TraceLog(INFO, "OVR: Product Name: %s", hmdDesc.ProductName);
TraceLog(INFO, "OVR: Manufacturer: %s", hmdDesc.Manufacturer);
TraceLog(INFO, "OVR: Product ID: %i", hmdDesc.ProductId);
TraceLog(INFO, "OVR: Product Type: %i", hmdDesc.Type);
TraceLog(INFO, "OVR: Serian Number: %s", hmdDesc.SerialNumber);
TraceLog(INFO, "OVR: Resolution: %ix%i", hmdDesc.Resolution.w, hmdDesc.Resolution.h);
//screenWidth = hmdDesc.Resolution.w/2;
//screenHeight = hmdDesc.Resolution.h/2;
// Initialize Oculus Buffers
OculusLayer layer = InitOculusLayer(session);
OculusBuffer buffer = LoadOculusBuffer(session, layer.width, layer.height);
OculusMirror mirror = LoadOculusMirror(session, screenWidth, screenHeight);
layer.eyeLayer.ColorTexture[0] = buffer.textureChain; //SetOculusLayerTexture(eyeLayer, buffer.textureChain);
// Recenter OVR tracking origin
ovr_RecenterTrackingOrigin(session);
#endif
Camera camera;
camera.position = (Vector3){ 5.0f, 5.0f, 5.0f }; // Camera position
camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
camera.fovy = 45.0f; // Camera field-of-view Y
Vector3 cubePosition = { 0.0f, 0.0f, 0.0f };
//--------------------------------------------------------------------------------------
// Main game loop
@ -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);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 179 KiB

After

Width:  |  Height:  |  Size: 167 KiB

View File

@ -47,10 +47,16 @@
#include "raylib.h" // Required for structs: Vector3, Matrix
#endif
#if defined(RAYMATH_EXTERN_INLINE)
#define RMDEF extern inline
#ifdef __cplusplus
#define RMEXTERN extern "C" // Functions visible from other files (no name mangling of functions in C++)
#else
#define RMDEF extern
#define RMEXTERN extern // Functions visible from other files
#endif
#if defined(RAYMATH_EXTERN_INLINE)
#define RMDEF RMEXTERN inline // Functions are embeded inline (compiler generated code)
#else
#define RMDEF RMEXTERN
#endif
//----------------------------------------------------------------------------------
@ -105,10 +111,6 @@ typedef struct Quaternion {
#ifndef RAYMATH_EXTERN_INLINE
#ifdef __cplusplus
extern "C" {
#endif
//------------------------------------------------------------------------------------
// Functions Declaration to work with Vector3
//------------------------------------------------------------------------------------
@ -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
//----------------------------------------------------------------------------------

View File

@ -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");
Shader shader;
// Load standard shader (embeded in standard_shader.h)
shader.id = LoadShaderProgram(vStandardShaderStr, fStandardShaderStr);
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);
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);

View File

@ -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

View File

@ -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)
{

View File

@ -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();
}
}

View File

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

View File

@ -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
//--------------------------------------------------------------------------------------

View File

@ -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();
//----------------------------------------------------------------------------------

View File

@ -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;

View File

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

View File

@ -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));

View File

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

View File

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

View File

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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

Binary file not shown.

896
release/android/raylib.h Normal file
View File

@ -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 Normal file

Binary file not shown.

896
release/html5/raylib.h Normal file
View File

@ -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
release/linux/helpme! Normal file
View File

0
release/osx/helpme! Normal file
View File

Binary file not shown.

896
release/win32/raylib.h Normal file
View File

@ -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

View File

@ -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;

View File

@ -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
shaders/glsl100/standard.fs Normal file
View File

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

View File

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

View File

@ -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)

View File

@ -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)

View File

@ -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
else
{
lastAudioError = ERROR_RAW_CONTEXT_CREATION;
return -1;
}
}
void CloseRawAudioContext(RawAudioContext ctx)
{
if (mixChannels_g[ctx]) CloseMixChannel(mixChannels_g[ctx]);
}
// 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 (musicChannels_g[index].chipTune && musicChannels_g[index].xmctx)
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 (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);
}
}
// 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 (!GetMusicStreamCount()) musicEnabled_g = false;
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)
{

View File

@ -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);
int GetMusicStreamCount(void); // Get number of streams loaded
// used to output raw audio streams, returns negative numbers on error
// if floating point is false the data size is 16bit short, otherwise it is float 32bit
RawAudioContext InitRawAudioContext(int sampleRate, int channels, bool floatingPoint);
void CloseRawAudioContext(RawAudioContext ctx);
int BufferRawAudioContext(RawAudioContext ctx, void *data, unsigned short numberElements); // returns number of elements buffered
int InitRawMixChannel(int sampleRate, int channels, bool floatingPoint); // Initialize raw audio mix channel for audio buffering
int BufferRawMixChannel(int mixc, void *data, unsigned short numberElements); // Buffers data directly to raw mix channel
void CloseRawMixChannel(int mixc); // Closes and frees raw mix channel
#ifdef __cplusplus
}

View File

@ -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
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, ...)
// Display size-related data
static unsigned int displayWidth, displayHeight; // Display width and height (monitor, device-screen, LCD, ...)
static int screenWidth, screenHeight; // Screen width and height (used render area)
static int renderWidth, renderHeight; // Framebuffer width and height (render area)
// NOTE: Framebuffer could include black bars
static int renderWidth, renderHeight; // Framebuffer width and height (render area, including black bars if required)
static int renderOffsetX = 0; // Offset X from render area (must be divided by 2)
static int renderOffsetY = 0; // Offset Y from render area (must be divided by 2)
static bool fullscreen = false; // Fullscreen mode (useful only for PLATFORM_DESKTOP)
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)
{
// 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++)
{
if (modes[i].width >= screenWidth)
{
if (modes[i].height >= screenHeight)
{
displayWidth = modes[i].width;
displayHeight = modes[i].height;
break;
}
}
}
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);
// 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.
int count;
const GLFWvidmode *modes = glfwGetVideoModes(glfwGetPrimaryMonitor(), &count);
for (int i = 0; i < count; i++)
{
// TODO: Check modes[i]->width;
// TODO: Check modes[i]->height;
}
window = glfwCreateWindow(screenWidth, screenHeight, 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)

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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

Binary file not shown.

7684
src/external/glad.c vendored

File diff suppressed because one or more lines are too long

14368
src/external/glad.h vendored

File diff suppressed because one or more lines are too long

View File

@ -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 vendored Normal file

Binary file not shown.

View File

@ -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

View File

@ -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

Binary file not shown.

View File

@ -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))

View File

@ -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;
}

View File

@ -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;
#ifdef __cplusplus
extern "C" { // Prevents name mangling of functions
#endif
} PhysicBodyData, *PhysicBody;
//----------------------------------------------------------------------------------
// Module Functions Declaration
//----------------------------------------------------------------------------------
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
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
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
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
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
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
Rectangle TransformToRectangle(Transform transform); // Convert Transform data type to Rectangle (position and scale)
#ifdef __cplusplus
}
#endif
PHYSACDEF Rectangle TransformToRectangle(Transform transform); // Convert Transform data type to Rectangle (position and scale)
#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
//----------------------------------------------------------------------------------
// 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
//----------------------------------------------------------------------------------
// ...
//----------------------------------------------------------------------------------
// 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};
}
// 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;
// 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;
if (clock_gettime(CLOCK_MONOTONIC, &now) == 0) // Success
{
baseTime = (uint64_t)now.tv_sec*1000000000LLU + (uint64_t)now.tv_nsec;
}
#endif
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
#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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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
}

View File

@ -47,10 +47,16 @@
#include "raylib.h" // Required for structs: Vector3, Matrix
#endif
#if defined(RAYMATH_EXTERN_INLINE)
#define RMDEF extern inline
#ifdef __cplusplus
#define RMEXTERN extern "C" // Functions visible from other files (no name mangling of functions in C++)
#else
#define RMDEF extern
#define RMEXTERN extern // Functions visible from other files
#endif
#if defined(RAYMATH_EXTERN_INLINE)
#define RMDEF RMEXTERN inline // Functions are embeded inline (compiler generated code)
#else
#define RMDEF RMEXTERN
#endif
//----------------------------------------------------------------------------------
@ -105,10 +111,6 @@ typedef struct Quaternion {
#ifndef RAYMATH_EXTERN_INLINE
#ifdef __cplusplus
extern "C" {
#endif
//------------------------------------------------------------------------------------
// Functions Declaration to work with Vector3
//------------------------------------------------------------------------------------
@ -166,10 +168,6 @@ RMDEF Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle); // Returns
RMDEF void QuaternionToAxisAngle(Quaternion q, Vector3 *outAxis, float *outAngle); // Returns the rotation angle and axis for a given quaternion
RMDEF void QuaternionTransform(Quaternion *q, Matrix mat); // Transform a quaternion given a transformation matrix
#ifdef __cplusplus
}
#endif
#endif // notdef RAYMATH_EXTERN_INLINE
#endif // RAYMATH_H

1700
src/rlgl.c

File diff suppressed because it is too large Load Diff

View File

@ -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
src/shader_distortion.h Normal file
View File

@ -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
src/shader_standard.h Normal file
View File

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

View File

@ -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);

View File

@ -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();

View File

@ -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

View File

@ -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

View File

@ -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;