Merged master fixed conflict.

This commit is contained in:
raysan5 2015-08-27 16:32:06 +02:00
commit 3a9ed0e846
37 changed files with 56897 additions and 5735 deletions

View File

@ -1,11 +1,60 @@
changelog
---------
Current Release: raylib 1.2.2 (31 December 2014)
Current Release: raylib 1.3.0 (01 September 2015)
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.3.0 (01 September 2015)
-----------------------------------------------
NOTE:
This version supposed a big boost for raylib, new modules have been added with lots of features.
Most of the modules have been completely reviewed to accomodate to the new features.
BIG changes:
[camera] NEW MODULE: Set of cameras for 3d view: Free, Orbital, 1st person, 3rd person
[gestures] NEW MODULE: Gestures system for Android and HTML5 platforms
[raygui] NEW MODULE: Set of IMGUI elements for tools development
[rlgl] SHADERS: Support for model shaders and postprocessing shaders (multiple functions)
[textures] FORMATS: Added support for multiple internal formats, including compressed formats
smaller changes:
[rlgl] Added check for OpenGL supported extensions
[rlgl] Added function SetBlenMode() to select some predefined blending modes
[core] Added support for drop&drag of external files into running program
[core] Added functions ShowCursor(), HideCursor(), IsCursorHidden()
[core] Renamed function SetFlags() to SetConfigFlags()
[shapes] Simplified some functions to improve performance
[textures] Added function LoadImageEx()
[textures] Added function LoadImageRaw()
[textures] Added function LoadTextureEx()
[textures] Simplified function parameters LoadTextureFromImage()
[textures] Added function GetImageData()
[textures] Added function GetTextureData()
[textures] Renamed function ConvertToPOT() to ImageConvertToPOT()
[textures] Added function ImageConvertFormat()
[textures] Added function GenTextureMipmaps()
[text] Added support for Latin-1 Extended characters for default font
[models] Review of struct: Model (added shaders support)
[models] Added 3d collision functions (sphere vs sphere vs box vs box)
[models] Added function DrawCubeTexture()
[models] Added function DrawQuad()
[models] Added function DrawRay()
[models] Simplified funtion DrawPlane()
[models] Removed function DrawPlaneEx()
[models] Simplified funtion DrawGizmo()
[models] Removed function DrawGizmoEx()
[models] Added function LoadModelEx()
[models] Review of function LoadCubicMap()
[models] Added function ResolveCollisionCubicmap()
[audio] Decopupled from raylib, now this module can be used as standalone
[audio] Added function UpdateMusicStream()
[raymath] Complete review of the module
[stb] Updated to latest headers versions
[*] Lots of tweaks around
-----------------------------------------------
Release: raylib 1.2.2 (31 December 2014)
-----------------------------------------------

View File

@ -19,7 +19,7 @@ with a small [donation](http://www.raylib.com/helpme.htm) (just some euros...).
raylib philosophy
------------------
* raylib is a tool to LEARN videogames programming, every single function in raylib should be a tutorial on itself.
* 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 open source and free; educators and institutions can use this tool to TEACH videogames programming completely by free.

View File

@ -37,3 +37,345 @@ All rBMF fonts provided with raylib are free to use (freeware) and have been des
* Mecha - Captain Falcon
* PixelPlay - Aleksander Shevchuk
* PixAntiqua - Gerhard Großmann
3d models
---------
dwarf 3d model used in examples is created by Daniel Moreno and licensed as Creative Commons Attribution-NonCommercial 3.0
Full license provided below:
Creative Commons Legal Code
Attribution-NonCommercial 3.0 Unported
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR
DAMAGES RESULTING FROM ITS USE.
License
THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE
COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY
COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS
AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE
TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY
BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS
CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND
CONDITIONS.
1. Definitions
a. "Adaptation" means a work based upon the Work, or upon the Work and
other pre-existing works, such as a translation, adaptation,
derivative work, arrangement of music or other alterations of a
literary or artistic work, or phonogram or performance and includes
cinematographic adaptations or any other form in which the Work may be
recast, transformed, or adapted including in any form recognizably
derived from the original, except that a work that constitutes a
Collection will not be considered an Adaptation for the purpose of
this License. For the avoidance of doubt, where the Work is a musical
work, performance or phonogram, the synchronization of the Work in
timed-relation with a moving image ("synching") will be considered an
Adaptation for the purpose of this License.
b. "Collection" means a collection of literary or artistic works, such as
encyclopedias and anthologies, or performances, phonograms or
broadcasts, or other works or subject matter other than works listed
in Section 1(f) below, which, by reason of the selection and
arrangement of their contents, constitute intellectual creations, in
which the Work is included in its entirety in unmodified form along
with one or more other contributions, each constituting separate and
independent works in themselves, which together are assembled into a
collective whole. A work that constitutes a Collection will not be
considered an Adaptation (as defined above) for the purposes of this
License.
c. "Distribute" means to make available to the public the original and
copies of the Work or Adaptation, as appropriate, through sale or
other transfer of ownership.
d. "Licensor" means the individual, individuals, entity or entities that
offer(s) the Work under the terms of this License.
e. "Original Author" means, in the case of a literary or artistic work,
the individual, individuals, entity or entities who created the Work
or if no individual or entity can be identified, the publisher; and in
addition (i) in the case of a performance the actors, singers,
musicians, dancers, and other persons who act, sing, deliver, declaim,
play in, interpret or otherwise perform literary or artistic works or
expressions of folklore; (ii) in the case of a phonogram the producer
being the person or legal entity who first fixes the sounds of a
performance or other sounds; and, (iii) in the case of broadcasts, the
organization that transmits the broadcast.
f. "Work" means the literary and/or artistic work offered under the terms
of this License including without limitation any production in the
literary, scientific and artistic domain, whatever may be the mode or
form of its expression including digital form, such as a book,
pamphlet and other writing; a lecture, address, sermon or other work
of the same nature; a dramatic or dramatico-musical work; a
choreographic work or entertainment in dumb show; a musical
composition with or without words; a cinematographic work to which are
assimilated works expressed by a process analogous to cinematography;
a work of drawing, painting, architecture, sculpture, engraving or
lithography; a photographic work to which are assimilated works
expressed by a process analogous to photography; a work of applied
art; an illustration, map, plan, sketch or three-dimensional work
relative to geography, topography, architecture or science; a
performance; a broadcast; a phonogram; a compilation of data to the
extent it is protected as a copyrightable work; or a work performed by
a variety or circus performer to the extent it is not otherwise
considered a literary or artistic work.
g. "You" means an individual or entity exercising rights under this
License who has not previously violated the terms of this License with
respect to the Work, or who has received express permission from the
Licensor to exercise rights under this License despite a previous
violation.
h. "Publicly Perform" means to perform public recitations of the Work and
to communicate to the public those public recitations, by any means or
process, including by wire or wireless means or public digital
performances; to make available to the public Works in such a way that
members of the public may access these Works from a place and at a
place individually chosen by them; to perform the Work to the public
by any means or process and the communication to the public of the
performances of the Work, including by public digital performance; to
broadcast and rebroadcast the Work by any means including signs,
sounds or images.
i. "Reproduce" means to make copies of the Work by any means including
without limitation by sound or visual recordings and the right of
fixation and reproducing fixations of the Work, including storage of a
protected performance or phonogram in digital form or other electronic
medium.
2. Fair Dealing Rights. Nothing in this License is intended to reduce,
limit, or restrict any uses free from copyright or rights arising from
limitations or exceptions that are provided for in connection with the
copyright protection under copyright law or other applicable laws.
3. License Grant. Subject to the terms and conditions of this License,
Licensor hereby grants You a worldwide, royalty-free, non-exclusive,
perpetual (for the duration of the applicable copyright) license to
exercise the rights in the Work as stated below:
a. to Reproduce the Work, to incorporate the Work into one or more
Collections, and to Reproduce the Work as incorporated in the
Collections;
b. to create and Reproduce Adaptations provided that any such Adaptation,
including any translation in any medium, takes reasonable steps to
clearly label, demarcate or otherwise identify that changes were made
to the original Work. For example, a translation could be marked "The
original work was translated from English to Spanish," or a
modification could indicate "The original work has been modified.";
c. to Distribute and Publicly Perform the Work including as incorporated
in Collections; and,
d. to Distribute and Publicly Perform Adaptations.
The above rights may be exercised in all media and formats whether now
known or hereafter devised. The above rights include the right to make
such modifications as are technically necessary to exercise the rights in
other media and formats. Subject to Section 8(f), all rights not expressly
granted by Licensor are hereby reserved, including but not limited to the
rights set forth in Section 4(d).
4. Restrictions. The license granted in Section 3 above is expressly made
subject to and limited by the following restrictions:
a. You may Distribute or Publicly Perform the Work only under the terms
of this License. You must include a copy of, or the Uniform Resource
Identifier (URI) for, this License with every copy of the Work You
Distribute or Publicly Perform. You may not offer or impose any terms
on the Work that restrict the terms of this License or the ability of
the recipient of the Work to exercise the rights granted to that
recipient under the terms of the License. You may not sublicense the
Work. You must keep intact all notices that refer to this License and
to the disclaimer of warranties with every copy of the Work You
Distribute or Publicly Perform. When You Distribute or Publicly
Perform the Work, You may not impose any effective technological
measures on the Work that restrict the ability of a recipient of the
Work from You to exercise the rights granted to that recipient under
the terms of the License. This Section 4(a) applies to the Work as
incorporated in a Collection, but this does not require the Collection
apart from the Work itself to be made subject to the terms of this
License. If You create a Collection, upon notice from any Licensor You
must, to the extent practicable, remove from the Collection any credit
as required by Section 4(c), as requested. If You create an
Adaptation, upon notice from any Licensor You must, to the extent
practicable, remove from the Adaptation any credit as required by
Section 4(c), as requested.
b. You may not exercise any of the rights granted to You in Section 3
above in any manner that is primarily intended for or directed toward
commercial advantage or private monetary compensation. The exchange of
the Work for other copyrighted works by means of digital file-sharing
or otherwise shall not be considered to be intended for or directed
toward commercial advantage or private monetary compensation, provided
there is no payment of any monetary compensation in connection with
the exchange of copyrighted works.
c. If You Distribute, or Publicly Perform the Work or any Adaptations or
Collections, You must, unless a request has been made pursuant to
Section 4(a), keep intact all copyright notices for the Work and
provide, reasonable to the medium or means You are utilizing: (i) the
name of the Original Author (or pseudonym, if applicable) if supplied,
and/or if the Original Author and/or Licensor designate another party
or parties (e.g., a sponsor institute, publishing entity, journal) for
attribution ("Attribution Parties") in Licensor's copyright notice,
terms of service or by other reasonable means, the name of such party
or parties; (ii) the title of the Work if supplied; (iii) to the
extent reasonably practicable, the URI, if any, that Licensor
specifies to be associated with the Work, unless such URI does not
refer to the copyright notice or licensing information for the Work;
and, (iv) consistent with Section 3(b), in the case of an Adaptation,
a credit identifying the use of the Work in the Adaptation (e.g.,
"French translation of the Work by Original Author," or "Screenplay
based on original Work by Original Author"). The credit required by
this Section 4(c) may be implemented in any reasonable manner;
provided, however, that in the case of a Adaptation or Collection, at
a minimum such credit will appear, if a credit for all contributing
authors of the Adaptation or Collection appears, then as part of these
credits and in a manner at least as prominent as the credits for the
other contributing authors. For the avoidance of doubt, You may only
use the credit required by this Section for the purpose of attribution
in the manner set out above and, by exercising Your rights under this
License, You may not implicitly or explicitly assert or imply any
connection with, sponsorship or endorsement by the Original Author,
Licensor and/or Attribution Parties, as appropriate, of You or Your
use of the Work, without the separate, express prior written
permission of the Original Author, Licensor and/or Attribution
Parties.
d. For the avoidance of doubt:
i. Non-waivable Compulsory License Schemes. In those jurisdictions in
which the right to collect royalties through any statutory or
compulsory licensing scheme cannot be waived, the Licensor
reserves the exclusive right to collect such royalties for any
exercise by You of the rights granted under this License;
ii. Waivable Compulsory License Schemes. In those jurisdictions in
which the right to collect royalties through any statutory or
compulsory licensing scheme can be waived, the Licensor reserves
the exclusive right to collect such royalties for any exercise by
You of the rights granted under this License if Your exercise of
such rights is for a purpose or use which is otherwise than
noncommercial as permitted under Section 4(b) and otherwise waives
the right to collect royalties through any statutory or compulsory
licensing scheme; and,
iii. Voluntary License Schemes. The Licensor reserves the right to
collect royalties, whether individually or, in the event that the
Licensor is a member of a collecting society that administers
voluntary licensing schemes, via that society, from any exercise
by You of the rights granted under this License that is for a
purpose or use which is otherwise than noncommercial as permitted
under Section 4(c).
e. Except as otherwise agreed in writing by the Licensor or as may be
otherwise permitted by applicable law, if You Reproduce, Distribute or
Publicly Perform the Work either by itself or as part of any
Adaptations or Collections, You must not distort, mutilate, modify or
take other derogatory action in relation to the Work which would be
prejudicial to the Original Author's honor or reputation. Licensor
agrees that in those jurisdictions (e.g. Japan), in which any exercise
of the right granted in Section 3(b) of this License (the right to
make Adaptations) would be deemed to be a distortion, mutilation,
modification or other derogatory action prejudicial to the Original
Author's honor and reputation, the Licensor will waive or not assert,
as appropriate, this Section, to the fullest extent permitted by the
applicable national law, to enable You to reasonably exercise Your
right under Section 3(b) of this License (right to make Adaptations)
but not otherwise.
5. Representations, Warranties and Disclaimer
UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR
OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY
KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE,
INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY,
FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF
LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS,
WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION
OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.
6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE
LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR
ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES
ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
7. Termination
a. This License and the rights granted hereunder will terminate
automatically upon any breach by You of the terms of this License.
Individuals or entities who have received Adaptations or Collections
from You under this License, however, will not have their licenses
terminated provided such individuals or entities remain in full
compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will
survive any termination of this License.
b. Subject to the above terms and conditions, the license granted here is
perpetual (for the duration of the applicable copyright in the Work).
Notwithstanding the above, Licensor reserves the right to release the
Work under different license terms or to stop distributing the Work at
any time; provided, however that any such election will not serve to
withdraw this License (or any other license that has been, or is
required to be, granted under the terms of this License), and this
License will continue in full force and effect unless terminated as
stated above.
8. Miscellaneous
a. Each time You Distribute or Publicly Perform the Work or a Collection,
the Licensor offers to the recipient a license to the Work on the same
terms and conditions as the license granted to You under this License.
b. Each time You Distribute or Publicly Perform an Adaptation, Licensor
offers to the recipient a license to the original Work on the same
terms and conditions as the license granted to You under this License.
c. If any provision of this License is invalid or unenforceable under
applicable law, it shall not affect the validity or enforceability of
the remainder of the terms of this License, and without further action
by the parties to this agreement, such provision shall be reformed to
the minimum extent necessary to make such provision valid and
enforceable.
d. No term or provision of this License shall be deemed waived and no
breach consented to unless such waiver or consent shall be in writing
and signed by the party to be charged with such waiver or consent.
e. This License constitutes the entire agreement between the parties with
respect to the Work licensed here. There are no understandings,
agreements or representations with respect to the Work not specified
here. Licensor shall not be bound by any additional provisions that
may appear in any communication from You. This License may not be
modified without the mutual written agreement of the Licensor and You.
f. The rights granted under, and the subject matter referenced, in this
License were drafted utilizing the terminology of the Berne Convention
for the Protection of Literary and Artistic Works (as amended on
September 28, 1979), the Rome Convention of 1961, the WIPO Copyright
Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996
and the Universal Copyright Convention (as revised on July 24, 1971).
These rights and subject matter take effect in the relevant
jurisdiction in which the License terms are sought to be enforced
according to the corresponding provisions of the implementation of
those treaty provisions in the applicable national law. If the
standard suite of rights granted under applicable copyright law
includes additional rights not granted under this License, such
additional rights are deemed to be included in the License; this
License is not intended to restrict the license of any rights under
applicable law.
Creative Commons Notice
Creative Commons is not a party to this License, and makes no warranty
whatsoever in connection with the Work. Creative Commons will not be
liable to You or any party on any legal theory for any damages
whatsoever, including without limitation any general, special,
incidental or consequential damages arising in connection to this
license. Notwithstanding the foregoing two (2) sentences, if Creative
Commons has expressly identified itself as the Licensor hereunder, it
shall have all rights and obligations of Licensor.
Except for the limited purpose of indicating to the public that the
Work is licensed under the CCPL, Creative Commons does not authorize
the use by either party of the trademark "Creative Commons" or any
related trademark or logo of Creative Commons without the prior
written consent of Creative Commons. Any permitted use will be in
compliance with Creative Commons' then-current trademark usage
guidelines, as may be published on its website or otherwise made
available upon request from time to time. For the avoidance of doubt,
this trademark restriction does not form part of the License.
Creative Commons may be contacted at https://creativecommons.org/.

View File

@ -75,6 +75,28 @@ Lots of code changes and lot of testing have concluded in this amazing new rayli
In December 2014, new raylib 1.2.2 was published with support to compile directly for web (html5) using [emscripten](http://kripken.github.io/emscripten-site/) and [asm.js](http://asmjs.org/).
notes on raylib 1.3
-------------------
On September 2015, after 1 year of raylib 1.2 release, arrives raylib 1.3. This version adds shaders functionality,
improves textures module and provides some new modules (camera system, gestures system, IMGUI).
Shaders, the biggest addition to raylib, with support for simple and easy shaders loading and use. Loaded shaders can be
assigned to models or used as fullscreen postrocessing shaders.
Textures module has been improved 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).
New camera module offers the user multiple preconfigured ready-to-use camera systems (free camera, 1st person, third person),
very easy to use, just calling functions: SetCameraMode() and UpdateCamera().
New gestures module simplifies getures detection on Android and HTML5 programs.
New IMGUI (Immediate Mode GUI) module: raygui, offers a set of functions to create simple user interfaces,
primary intended for tools development, still in experimental state but already fully functional.
Lots of code changes and lot of testing have concluded in this amazing new raylib 1.3.
features
--------
@ -82,6 +104,8 @@ features
* Uses C# PascalCase/camelCase notation
* Hardware accelerated with OpenGL (1.1, 3.3+ or ES2)
* Unique OpenGL abstraction layer: [rlgl](https://github.com/raysan5/raylib/blob/master/src/rlgl.c)
* Hardware accelerated with OpenGL (1.1, 3.3 or ES2)
* Unique OpenGL abstraction layer [rlgl]
* Powerful fonts module with SpriteFonts support
* Multiple textures support, including DDS, PKM and mipmaps generation
* Basic 3d support for Shapes, Models, Heightmaps and Billboards
@ -258,9 +282,16 @@ acknowledgments
The following people have contributed in some way to make raylib project a reality. Big thanks to them!
- [Zopokx](https://github.com/Zopokx) for testing and hosting the web.
- [Zopokx](https://github.com/Zopokx) for testing the web.
- [Elendow](http://www.elendow.com) for testing and helping on web development.
- Victor Dual for implementation and testing of 3D shapes functions.
- Marc Palau for implementation and testing of 3D shapes functions.
- 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.
- 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)
- Daniel Moreno for testing and using raylib on a real product (Koala Seasons)
- Daniel Gomez for testing and using raylib on a real product (Koala Seasons)
- Sergio Martinez for helping on raygui development and tools development.
[raysan5]: mailto:raysan@raysanweb.com "Ramon Santamaria - Ray San"

View File

@ -4,21 +4,21 @@ roadmap
Current version of raylib is quite complete and functional but there is still a lot of things I would like to improve.
Here it is a list of features I would like to add and functions to improve.
Around the source code there are some TODO points with pending revisions/bugs and here it is a list of features I would like to add.
Around the source code there are multiple TODO points with pending revisions/bugs and here it is a list of desired features.
This roadmap is quite outdated... a full list of all the features we are working on should be listed here at some point...
raylib v1.4
raylib v1.x
- [DONE] Review Billboard Drawing functions
- [DONE] Review Heightmap Loading and Drawing functions - Load Heightmap directly as a Model
- Lighting support (only 3d mode)
- [DONE] Simple Collision Detection functions
- [IN PROGRESS] Default scene Camera controls (zoom, pan, rotate)
- Basic Procedural Image Generation (Gradient, Checked, Spot, Noise, Cellular)
- [DONE] Software mipmapping generation and POT conversion (custom implementation)
- [IN PROGRESS] TTF fonts support
- TTF fonts support (using stb_truetype)
- Raycast system for 3D picking (including collisions detection)
- Remove GLEW dependency (use another solution...)
- Floyd-Steinberg dithering on 16bit image format conversion
- Basic image manipulation functions (crop, resize, draw...)
- Basic image procedural generation (spot, gradient, noise...)
- Basic GPU stats sytem (memory, draws, time...)
Check [GITHUB ISSUES][issues] for further details on implementation status for this features!
Any feature missing? Do you have a request? [Let me know!][raysan5]
[raysan5]: mailto:raysan@raysanweb.com "Ramon Santamaria - Ray San"
[isssues]: https://github.com/raysan5/raylib/issues

View File

@ -7,7 +7,7 @@
* This example has been created using raylib 1.1 (www.raylib.com)
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
*
* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
* Copyright (c) 2014 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
@ -58,7 +58,12 @@ int main()
SetMusicVolume(volume);
}
*/
if (IsWindowMinimized()) PauseMusicStream();
else ResumeMusicStream();
timePlayed = GetMusicTimePlayed() / GetMusicTimeLength() * 100 * 4; // We scale by 4 to fit 400 pixels
UpdateMusicStream();
//----------------------------------------------------------------------------------
// Draw

View File

@ -1,11 +1,8 @@
/*******************************************************************************************
*
* raylib [textures] example - DDS Texture loading and drawing (compressed and uncompressed)
* raylib [core] example - Picking in 3d mode
*
* NOTE: This example requires raylib OpenGL 3.3+ or ES2 versions for compressed texture,
* OpenGL 1.1 does not support compressed textures, only uncompressed version.
*
* This example has been created using raylib 1.2 (www.raylib.com)
* This example has been created using raylib 1.0 (www.raylib.com)
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
*
* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
@ -21,33 +18,48 @@ int main()
int screenWidth = 800;
int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [textures] example - DDS texture loading and drawing");
InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d picking");
// NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required)
// Define the camera to look into our 3d world
Camera camera = {{ 0.0, 10.0, 10.0 }, { 0.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }};
Vector3 cubePosition = { 0.0, 0.0, 0.0 };
Texture2D texture = LoadTexture("resources/raylib_logo.dds"); // Texture loading (compressed)
Ray pickingLine;
SetCameraMode(CAMERA_FREE);
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//---------------------------------------------------------------------------------------
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
// TODO: Update your variables here
camera = UpdateCamera(0);
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) pickingLine = GetMouseRay(GetMousePosition(), camera);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
DrawTexture(texture, screenWidth/2 - texture.width/2, screenHeight/2 - texture.height/2, WHITE);
Begin3dMode(camera);
DrawText("this may be a compressed texture!", 320, 370, 10, GRAY);
DrawCube(cubePosition, 2, 2, 2, RED);
DrawCubeWires(cubePosition, 2, 2, 2, MAROON);
DrawGrid(10.0, 1.0);
DrawRay(pickingLine, MAROON);
End3dMode();
DrawFPS(10, 10);
EndDrawing();
//----------------------------------------------------------------------------------
@ -55,9 +67,7 @@ int main()
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadTexture(texture); // Texture unloading
CloseWindow(); // Close window and OpenGL context
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;

View File

@ -15,7 +15,7 @@
* This example has been created using raylib 1.0 (www.raylib.com)
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
*
* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
* Copyright (c) 2014 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
@ -52,7 +52,7 @@ int main()
}
// De-Initialization
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------

View File

@ -164,8 +164,6 @@ EXAMPLES = \
textures_logo_raylib \
textures_image_loading \
textures_rectangle \
textures_compressed_dds \
textures_mipmaps \
textures_srcrec_dstrec \
text_sprite_fonts \
text_rbmf_fonts \
@ -253,14 +251,6 @@ textures_image_loading: textures_image_loading.c
textures_rectangle: textures_rectangle.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
# compile [textures] example - compressed texture loading (DDS)
textures_compressed_dds: textures_compressed_dds.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
# compile [textures] example - texture mipmaps generation
textures_mipmaps: textures_mipmaps.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
# compile [textures] example - texture source and destination rectangles
textures_srcrec_dstrec: textures_srcrec_dstrec.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)

View File

@ -5,7 +5,7 @@
* This example has been created using raylib 1.0 (www.raylib.com)
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
*
* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
* Copyright (c) 2014 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
@ -21,12 +21,12 @@ int main()
InitWindow(screenWidth, screenHeight, "raylib [models] example - obj model loading");
// Define the camera to look into our 3d world
Camera camera = {{ 10.0, 8.0, 10.0 }, { 0.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }};
Camera camera = {{ 3.0, 3.0, 3.0 }, { 0.0, 1.5, 0.0 }, { 0.0, 1.0, 0.0 }};
Texture2D texture = LoadTexture("resources/catsham.png"); // Load model texture
Model cat = LoadModel("resources/cat.obj"); // Load OBJ model
SetModelTexture(&cat, texture); // Bind texture to model
Vector3 catPosition = { 0.0, 0.0, 0.0 }; // Set model position
Texture2D texture = LoadTexture("resources/model/dwarf_diffuse.png"); // Load model texture
Model dwarf = LoadModel("resources/model/dwarf.obj"); // Load OBJ model
SetModelTexture(&dwarf, texture); // Bind texture to model
Vector3 position = { 0.0, 0.0, 0.0 }; // Set model position
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
@ -36,10 +36,10 @@ int main()
{
// Update
//----------------------------------------------------------------------------------
if (IsKeyDown(KEY_LEFT)) catPosition.x -= 0.2;
if (IsKeyDown(KEY_RIGHT)) catPosition.x += 0.2;
if (IsKeyDown(KEY_UP)) catPosition.z -= 0.2;
if (IsKeyDown(KEY_DOWN)) catPosition.z += 0.2;
if (IsKeyDown(KEY_LEFT)) position.x -= 0.2;
if (IsKeyDown(KEY_RIGHT)) position.x += 0.2;
if (IsKeyDown(KEY_UP)) position.z -= 0.2;
if (IsKeyDown(KEY_DOWN)) position.z += 0.2;
//----------------------------------------------------------------------------------
// Draw
@ -50,13 +50,15 @@ int main()
Begin3dMode(camera);
DrawModel(cat, catPosition, 0.1f, WHITE); // Draw 3d model with texture
DrawModel(dwarf, position, 2.0f, WHITE); // Draw 3d model with texture
DrawGrid(10.0, 1.0); // Draw a grid
DrawGizmo(catPosition); // Draw gizmo
DrawGizmo(position); // Draw gizmo
End3dMode();
DrawText("(c) Dwarf 3D model by David Moreno", screenWidth - 200, screenHeight - 20, 10, GRAY);
DrawFPS(10, 10);
@ -67,7 +69,7 @@ int main()
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadTexture(texture); // Unload texture
UnloadModel(cat); // Unload model
UnloadModel(dwarf); // Unload model
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 308 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 302 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

View File

@ -5,7 +5,7 @@
* This example has been created using raylib 1.0 (www.raylib.com)
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
*
* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
* Copyright (c) 2014 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
@ -16,7 +16,7 @@ int main()
// Initialization
//--------------------------------------------------------------------------------------
int screenWidth = 800;
int screenHeight = 150;
int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [text] example - font selector");
@ -45,12 +45,14 @@ int main()
Vector2 mousePoint;
Rectangle btnNextRec = { 673, 18, 109, 44 }; // Button rectangle (useful for collision)
Color btnNextOutColor = DARKBLUE; // Button color (outside line)
Color btnNextInColor = SKYBLUE; // Button color (inside)
int framesCounter = 0; // Useful to count frames button is 'active' = clicked
int positionY = 180; // Text selector and button Y position
Rectangle btnNextRec = { 673, positionY, 109, 44 }; // Button rectangle (useful for collision)
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
@ -71,6 +73,15 @@ int main()
{
if (currentFont > 0) currentFont--;
}
if (IsKeyPressed('0')) currentFont = 0;
else if (IsKeyPressed('1')) currentFont = 1;
else if (IsKeyPressed('2')) currentFont = 2;
else if (IsKeyPressed('3')) currentFont = 3;
else if (IsKeyPressed('4')) currentFont = 4;
else if (IsKeyPressed('5')) currentFont = 5;
else if (IsKeyPressed('6')) currentFont = 6;
else if (IsKeyPressed('7')) currentFont = 7;
// Mouse-based font selection (NEXT button logic)
mousePoint = GetMousePosition();
@ -115,18 +126,21 @@ int main()
BeginDrawing();
ClearBackground(RAYWHITE);
DrawText("font selector - use arroys, button or numbers", 160, 80, 20, DARKGRAY);
DrawLine(120, 120, 680, 120, DARKGRAY);
DrawRectangle(18, 18, 644, 44, DARKGRAY);
DrawRectangle(20, 20, 640, 40, LIGHTGRAY);
DrawText(fontNames[currentFont], 30, 31, 20, BLACK);
DrawText("< >", 610, 26, 30, BLACK);
DrawRectangle(18, positionY, 644, 44, DARKGRAY);
DrawRectangle(20, positionY + 2, 640, 40, LIGHTGRAY);
DrawText(fontNames[currentFont], 30, positionY + 13, 20, BLACK);
DrawText("< >", 610, positionY + 8, 30, BLACK);
DrawRectangleRec(btnNextRec, btnNextOutColor);
DrawRectangle(675, 20, 105, 40, btnNextInColor);
DrawText("NEXT", 700, 31, 20, btnNextOutColor);
DrawRectangle(675, positionY + 2, 105, 40, btnNextInColor);
DrawText("NEXT", 700, positionY + 13, 20, btnNextOutColor);
DrawTextEx(fonts[currentFont], text, (Vector2){ screenWidth/2 - textSize.x/2,
75 + (70 - textSize.y)/2 }, GetFontBaseSize(fonts[currentFont])*3,
260 + (70 - textSize.y)/2 }, GetFontBaseSize(fonts[currentFont])*3,
1, colors[currentFont]);
EndDrawing();

View File

@ -18,20 +18,43 @@ int main()
{
// Initialization
//--------------------------------------------------------------------------------------
int screenWidth = 560;
int screenHeight = 800;
int screenWidth = 800;
int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [text] example - rBMF fonts");
// NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required)
SpriteFont font1 = LoadSpriteFont("resources/fonts/alagard.rbmf"); // rBMF font loading
SpriteFont font2 = LoadSpriteFont("resources/fonts/pixelplay.rbmf"); // rBMF font loading
SpriteFont font3 = LoadSpriteFont("resources/fonts/mecha.rbmf"); // rBMF font loading
SpriteFont font4 = LoadSpriteFont("resources/fonts/setback.rbmf"); // rBMF font loading
SpriteFont font5 = LoadSpriteFont("resources/fonts/romulus.rbmf"); // rBMF font loading
SpriteFont font6 = LoadSpriteFont("resources/fonts/pixantiqua.rbmf"); // rBMF font loading
SpriteFont font7 = LoadSpriteFont("resources/fonts/alpha_beta.rbmf"); // rBMF font loading
SpriteFont font8 = LoadSpriteFont("resources/fonts/jupiter_crash.rbmf"); // rBMF font loading
SpriteFont fonts[8];
fonts[0] = LoadSpriteFont("resources/fonts/alagard.rbmf"); // rBMF font loading
fonts[1] = LoadSpriteFont("resources/fonts/pixelplay.rbmf"); // rBMF font loading
fonts[2] = LoadSpriteFont("resources/fonts/mecha.rbmf"); // rBMF font loading
fonts[3] = LoadSpriteFont("resources/fonts/setback.rbmf"); // rBMF font loading
fonts[4] = LoadSpriteFont("resources/fonts/romulus.rbmf"); // rBMF font loading
fonts[5] = LoadSpriteFont("resources/fonts/pixantiqua.rbmf"); // rBMF font loading
fonts[6] = LoadSpriteFont("resources/fonts/alpha_beta.rbmf"); // rBMF font loading
fonts[7] = LoadSpriteFont("resources/fonts/jupiter_crash.rbmf"); // rBMF font loading
const char *messages[8] = { "ALAGARD FONT designed by Hewett Tsoi",
"PIXELPLAY FONT designed by Aleksander Shevchuk",
"MECHA FONT designed by Captain Falcon",
"SETBACK FONT designed by Brian Kent (AEnigma)",
"ROMULUS FONT designed by Hewett Tsoi",
"PIXANTIQUA FONT designed by Gerhard Grossmann",
"ALPHA_BETA FONT designed by Brian Kent (AEnigma)",
"JUPITER_CRASH FONT designed by Brian Kent (AEnigma)" };
const int spacings[8] = { 2, 4, 8, 4, 3, 4, 4, 1 };
Vector2 positions[8];
for (int i = 0; i < 8; i++)
{
positions[i].x = screenWidth/2 - MeasureTextEx(fonts[i], messages[i], GetFontBaseSize(fonts[i])*2, spacings[i]).x/2;
positions[i].y = 60 + GetFontBaseSize(fonts[i]) + 50*i;
}
Color colors[8] = { MAROON, ORANGE, DARKGREEN, DARKBLUE, DARKPURPLE, LIME, GOLD };
//--------------------------------------------------------------------------------------
// Main game loop
@ -47,15 +70,14 @@ int main()
BeginDrawing();
ClearBackground(RAYWHITE);
DrawTextEx(font1, "TESTING ALAGARD FONT", (Vector2){ 100, 100 }, GetFontBaseSize(font1)*2, 2, MAROON);
DrawTextEx(font2, "TESTING PIXELPLAY FONT", (Vector2){ 100, 180 }, GetFontBaseSize(font2)*2, 4, ORANGE);
DrawTextEx(font3, "TESTING MECHA FONT", (Vector2){ 100, 260 }, GetFontBaseSize(font3)*2, 8, DARKGREEN);
DrawTextEx(font4, "TESTING SETBACK FONT", (Vector2){ 100, 350 }, GetFontBaseSize(font4)*2, 4, DARKBLUE);
DrawTextEx(font5, "TESTING ROMULUS FONT", (Vector2){ 100, 430 }, GetFontBaseSize(font5)*2, 3, DARKPURPLE);
DrawTextEx(font6, "TESTING PIXANTIQUA FONT", (Vector2){ 100, 510 }, GetFontBaseSize(font6)*2, 4, LIME);
DrawTextEx(font7, "TESTING ALPHA_BETA FONT", (Vector2){ 100, 590 }, GetFontBaseSize(font7)*2, 4, GOLD);
DrawTextEx(font8, "TESTING JUPITER_CRASH FONT", (Vector2){ 100, 660 }, GetFontBaseSize(font8)*2, 1, RED);
DrawText("free fonts included with raylib", 250, 20, 20, DARKGRAY);
DrawLine(220, 50, 590, 50, DARKGRAY);
for (int i = 0; i < 8; i++)
{
DrawTextEx(fonts[i], messages[i], positions[i], GetFontBaseSize(fonts[i])*2, spacings[i], colors[i]);
}
EndDrawing();
//----------------------------------------------------------------------------------
@ -63,14 +85,10 @@ int main()
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadSpriteFont(font1); // SpriteFont unloading
UnloadSpriteFont(font2); // SpriteFont unloading
UnloadSpriteFont(font3); // SpriteFont unloading
UnloadSpriteFont(font4); // SpriteFont unloading
UnloadSpriteFont(font5); // SpriteFont unloading
UnloadSpriteFont(font6); // SpriteFont unloading
UnloadSpriteFont(font7); // SpriteFont unloading
UnloadSpriteFont(font8); // SpriteFont unloading
for (int i = 0; i < 8; i++)
{
UnloadSpriteFont(fonts[i]); // SpriteFont unloading
}
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

View File

@ -7,7 +7,7 @@
* This example has been created using raylib 1.1 (www.raylib.com)
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
*
* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
* Copyright (c) 2014 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
@ -25,7 +25,7 @@ int main()
// NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required)
Image image = LoadImage("resources/raylib_logo.png"); // Loaded in CPU memory (RAM)
Texture2D texture = LoadTextureFromImage(image); // Image converted to texture, GPU memory (VRAM)
Texture2D texture = LoadTextureFromImage(image); // Image converted to texture, GPU memory (VRAM)
UnloadImage(image); // Once image has been converted to texture and uploaded to VRAM, it can be unloaded from RAM
//---------------------------------------------------------------------------------------

View File

@ -1,66 +0,0 @@
/*******************************************************************************************
*
* raylib [textures] example - Texture loading with mipmaps, mipmaps generation
*
* NOTE: On OpenGL 1.1, mipmaps are calculated 'manually', original image must be power-of-two
* On OpenGL 3.3 and ES2, mipmaps are generated automatically
*
* This example has been created using raylib 1.1 (www.raylib.com)
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
*
* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
*
********************************************************************************************/
#include "raylib.h"
int main()
{
// Initialization
//--------------------------------------------------------------------------------------
int screenWidth = 800;
int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [textures] example - texture mipmaps generation");
// NOTE: To generate mipmaps for an image, image must be loaded first and converted to texture
Image image = LoadImage("resources/raylib_logo.png"); // Load image to CPU memory (RAM)
Texture2D texture = LoadTextureFromImage(image); // Load texture into GPU memory (VRAM)
GenTextureMipmaps(texture); // Generate mipmaps for texture
UnloadImage(image); // Once texture has been created, we can unload image data from RAM
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
// TODO: Update your variables here
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
DrawTexture(texture, screenWidth/2 - texture.width/2,
screenHeight/2 - texture.height/2 - 30, WHITE);
DrawText("this IS a texture with mipmaps! really!", 210, 360, 20, GRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadTexture(texture); // Texture unloading
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

View File

@ -8,7 +8,7 @@
* OpenAL Soft - Audio device management lib (http://kcat.strangesoft.net/openal.html)
* stb_vorbis - Ogg audio files loading (http://www.nothings.org/stb_vorbis/)
*
* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
* Copyright (c) 2014 Ramon Santamaria (@raysan5)
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
@ -27,7 +27,13 @@
*
**********************************************************************************************/
#include "raylib.h"
//#define AUDIO_STANDALONE // NOTE: To use the audio module as standalone lib, just uncomment this line
#if defined(AUDIO_STANDALONE)
#include "audio.h"
#else
#include "raylib.h"
#endif
#include "AL/al.h" // OpenAL basic header
#include "AL/alc.h" // OpenAL context header (like OpenGL, OpenAL requires a context to work)
@ -36,8 +42,12 @@
#include <string.h> // Required for strcmp()
#include <stdio.h> // Used for .WAV loading
#include "utils.h" // rRES data decompression utility function
#if defined(AUDIO_STANDALONE)
#include <stdarg.h> // Used for functions with variable number of parameters (TraceLog())
#else
#include "utils.h" // rRES data decompression utility function
// NOTE: Includes Android fopen function map
#endif
//#define STB_VORBIS_HEADER_ONLY
#include "stb_vorbis.h" // OGG loading functions
@ -75,6 +85,10 @@ typedef struct Music {
} Music;
#if defined(AUDIO_STANDALONE)
typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType;
#endif
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
@ -85,13 +99,18 @@ static Music currentMusic; // Current music loaded
//----------------------------------------------------------------------------------
// Module specific Functions Declaration
//----------------------------------------------------------------------------------
static Wave LoadWAV(const char *fileName); // Load WAV file
static Wave LoadOGG(char *fileName); // Load OGG file
static void UnloadWave(Wave wave); // Unload wave data
static Wave LoadWAV(const char *fileName); // Load WAV file
static Wave LoadOGG(char *fileName); // Load OGG file
static void UnloadWave(Wave wave); // Unload wave data
static bool BufferMusicStream(ALuint buffer); // Fill music buffers with data
static void EmptyMusicStream(void); // Empty music buffers
extern void UpdateMusicStream(void); // Updates buffers (refill) for music streaming
static bool BufferMusicStream(ALuint buffer); // Fill music buffers with data
static void EmptyMusicStream(void); // Empty music buffers
extern void UpdateMusicStream(void); // Updates buffers (refill) for music streaming
#if defined(AUDIO_STANDALONE)
const char *GetExtension(const char *fileName); // Get the extension for a filename
void TraceLog(int msgType, const char *text, ...); // Outputs a trace log message (INFO, ERROR, WARNING)
#endif
//----------------------------------------------------------------------------------
// Module Functions Definition - Audio Device initialization and Closing
@ -273,8 +292,13 @@ Sound LoadSoundFromRES(const char *rresName, int resId)
{
// NOTE: rresName could be directly a char array with all the data!!! --> TODO
Sound sound;
bool found = false;
#if defined(AUDIO_STANDALONE)
TraceLog(WARNING, "Sound loading from rRES resource file not supported on standalone mode");
#else
bool found = false;
char id[4]; // rRES file identifier
unsigned char version; // rRES file version and subversion
char useless; // rRES header reserved data
@ -416,7 +440,7 @@ Sound LoadSoundFromRES(const char *rresName, int resId)
}
if (!found) TraceLog(WARNING, "[%s] Required resource id [%i] could not be found in the raylib resource file", rresName, resId);
#endif
return sound;
}
@ -425,6 +449,8 @@ void UnloadSound(Sound sound)
{
alDeleteSources(1, &sound.source);
alDeleteBuffers(1, &sound.buffer);
TraceLog(INFO, "Unloaded sound data");
}
// Play a sound
@ -777,6 +803,7 @@ static Wave LoadWAV(const char *fileName)
if (wavFile == NULL)
{
TraceLog(WARNING, "[%s] WAV file could not be opened", fileName);
wave.data = NULL;
}
else
{
@ -846,40 +873,49 @@ static Wave LoadOGG(char *fileName)
Wave wave;
stb_vorbis *oggFile = stb_vorbis_open_filename(fileName, NULL, NULL);
stb_vorbis_info info = stb_vorbis_get_info(oggFile);
wave.sampleRate = info.sample_rate;
wave.bitsPerSample = 16;
wave.channels = info.channels;
if (oggFile == NULL)
{
TraceLog(WARNING, "[%s] OGG file could not be opened", fileName);
wave.data = NULL;
}
else
{
stb_vorbis_info info = stb_vorbis_get_info(oggFile);
TraceLog(DEBUG, "[%s] Ogg sample rate: %i", fileName, info.sample_rate);
TraceLog(DEBUG, "[%s] Ogg channels: %i", fileName, info.channels);
wave.sampleRate = info.sample_rate;
wave.bitsPerSample = 16;
wave.channels = info.channels;
int totalSamplesLength = (stb_vorbis_stream_length_in_samples(oggFile) * info.channels);
TraceLog(DEBUG, "[%s] Ogg sample rate: %i", fileName, info.sample_rate);
TraceLog(DEBUG, "[%s] Ogg channels: %i", fileName, info.channels);
wave.dataSize = totalSamplesLength*sizeof(short); // Size must be in bytes
int totalSamplesLength = (stb_vorbis_stream_length_in_samples(oggFile) * info.channels);
TraceLog(DEBUG, "[%s] Samples length: %i", fileName, totalSamplesLength);
wave.dataSize = totalSamplesLength*sizeof(short); // Size must be in bytes
float totalSeconds = stb_vorbis_stream_length_in_seconds(oggFile);
TraceLog(DEBUG, "[%s] Samples length: %i", fileName, totalSamplesLength);
TraceLog(DEBUG, "[%s] Total seconds: %f", fileName, totalSeconds);
float totalSeconds = stb_vorbis_stream_length_in_seconds(oggFile);
if (totalSeconds > 10) TraceLog(WARNING, "[%s] Ogg audio lenght is larger than 10 seconds (%f), that's a big file in memory, consider music streaming", fileName, totalSeconds);
TraceLog(DEBUG, "[%s] Total seconds: %f", fileName, totalSeconds);
int totalSamples = totalSeconds*info.sample_rate*info.channels;
if (totalSeconds > 10) TraceLog(WARNING, "[%s] Ogg audio lenght is larger than 10 seconds (%f), that's a big file in memory, consider music streaming", fileName, totalSeconds);
TraceLog(DEBUG, "[%s] Total samples calculated: %i", fileName, totalSamples);
int totalSamples = totalSeconds*info.sample_rate*info.channels;
wave.data = malloc(sizeof(short)*totalSamplesLength);
TraceLog(DEBUG, "[%s] Total samples calculated: %i", fileName, totalSamples);
int samplesObtained = stb_vorbis_get_samples_short_interleaved(oggFile, info.channels, wave.data, totalSamplesLength);
wave.data = malloc(sizeof(short)*totalSamplesLength);
TraceLog(DEBUG, "[%s] Samples obtained: %i", fileName, samplesObtained);
int samplesObtained = stb_vorbis_get_samples_short_interleaved(oggFile, info.channels, wave.data, totalSamplesLength);
TraceLog(INFO, "[%s] OGG file loaded successfully (SampleRate: %i, BitRate: %i, Channels: %i)", fileName, wave.sampleRate, wave.bitsPerSample, wave.channels);
TraceLog(DEBUG, "[%s] Samples obtained: %i", fileName, samplesObtained);
stb_vorbis_close(oggFile);
TraceLog(INFO, "[%s] OGG file loaded successfully (SampleRate: %i, BitRate: %i, Channels: %i)", fileName, wave.sampleRate, wave.bitsPerSample, wave.channels);
stb_vorbis_close(oggFile);
}
return wave;
}
@ -888,4 +924,49 @@ static Wave LoadOGG(char *fileName)
static void UnloadWave(Wave wave)
{
free(wave.data);
}
TraceLog(INFO, "Unloaded wave data");
}
// Some required functions for audio standalone module version
#if defined(AUDIO_STANDALONE)
// Get the extension for a filename
const char *GetExtension(const char *fileName)
{
const char *dot = strrchr(fileName, '.');
if(!dot || dot == fileName) return "";
return (dot + 1);
}
// Outputs a trace log message (INFO, ERROR, WARNING)
// NOTE: If a file has been init, output log is written there
void TraceLog(int msgType, const char *text, ...)
{
va_list args;
int traceDebugMsgs = 0;
#ifdef DO_NOT_TRACE_DEBUG_MSGS
traceDebugMsgs = 0;
#endif
switch(msgType)
{
case INFO: fprintf(stdout, "INFO: "); break;
case ERROR: fprintf(stdout, "ERROR: "); break;
case WARNING: fprintf(stdout, "WARNING: "); break;
case DEBUG: if (traceDebugMsgs) fprintf(stdout, "DEBUG: "); break;
default: break;
}
if ((msgType != DEBUG) || ((msgType == DEBUG) && (traceDebugMsgs)))
{
va_start(args, text);
vfprintf(stdout, text, args);
va_end(args);
fprintf(stdout, "\n");
}
if (msgType == ERROR) exit(1); // If ERROR message, exit program
}
#endif

102
src/audio.h Normal file
View File

@ -0,0 +1,102 @@
/**********************************************************************************************
*
* raylib.audio
*
* Basic functions to manage Audio: InitAudioDevice, LoadAudioFiles, PlayAudioFiles
*
* 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/)
*
* Copyright (c) 2015 Ramon Santamaria (@raysan5)
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
* as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
**********************************************************************************************/
#ifndef AUDIO_H
#define AUDIO_H
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
//...
//----------------------------------------------------------------------------------
// Types and Structures Definition
// NOTE: Below types are required for CAMERA_STANDALONE usage
//----------------------------------------------------------------------------------
#ifndef __cplusplus
// Boolean type
typedef enum { false, true } bool;
#endif
// Sound source type
typedef struct Sound {
unsigned int source;
unsigned int buffer;
} Sound;
// Wave type, defines audio wave data
typedef struct Wave {
void *data; // Buffer data pointer
unsigned int dataSize; // Data size in bytes
unsigned int sampleRate;
short bitsPerSample;
short channels;
} Wave;
#ifdef __cplusplus
extern "C" { // Prevents name mangling of functions
#endif
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
//...
//----------------------------------------------------------------------------------
// Module Functions Declaration
//----------------------------------------------------------------------------------
void InitAudioDevice(void); // Initialize audio device and context
void CloseAudioDevice(void); // Close the audio device and context (and music stream)
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 SoundIsPlaying(Sound sound); // Check if a sound is currently playing
void SetSoundVolume(Sound sound, float volume); // Set volume for a sound (1.0 is max level)
void SetSoundPitch(Sound sound, float pitch); // Set pitch for a sound (1.0 is base level)
void PlayMusicStream(char *fileName); // Start music playing (open stream)
void UpdateMusicStream(void); // Updates buffers for music streaming
void StopMusicStream(void); // Stop music playing (close stream)
void PauseMusicStream(void); // Pause music playing
void ResumeMusicStream(void); // Resume playing paused music
bool MusicIsPlaying(void); // Check if music is playing
void SetMusicVolume(float volume); // Set volume for music (1.0 is max level)
float GetMusicTimeLength(void); // Get current music time length (in seconds)
float GetMusicTimePlayed(void); // Get current music time played (in seconds)
#ifdef __cplusplus
}
#endif
#endif // AUDIO_H

View File

@ -1,8 +1,6 @@
/**********************************************************************************************
*
* raylib.camera
*
* Camera Modes Setup and Control Functions
* raylib Camera System - Camera Modes Setup and Control Functions
*
* Copyright (c) 2015 Marc Palau and Ramon Santamaria
*
@ -23,7 +21,14 @@
*
**********************************************************************************************/
#include "camera.h"
//#define CAMERA_STANDALONE // NOTE: To use the camera module as standalone lib, just uncomment this line
// NOTE: ProcessCamera() should be reviewed to adapt inputs to other systems
#if defined(CAMERA_STANDALONE)
#include "camera.h"
#else
#include "raylib.h"
#endif
#include <math.h>
@ -49,7 +54,7 @@
//#define FIRST_PERSON_MOUSE_SENSITIVITY 0.003
#define FIRST_PERSON_FOCUS_DISTANCE 25
#define FIRST_PERSON_MIN_CLAMP 85
#define FIRST_PERSON_MAX_CLAMP -85
#define FIRST_PERSON_MAX_CLAMP -85
#define FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER 5.0
#define FIRST_PERSON_STEP_DIVIDER 30.0
@ -61,7 +66,7 @@
//#define THIRD_PERSON_MOUSE_SENSITIVITY 0.003
#define THIRD_PERSON_DISTANCE_CLAMP 1.2
#define THIRD_PERSON_MIN_CLAMP 5
#define THIRD_PERSON_MAX_CLAMP -85
#define THIRD_PERSON_MAX_CLAMP -85
#define THIRD_PERSON_OFFSET (Vector3){ 0.4, 0, 0 }
// PLAYER (used by camera)
@ -70,23 +75,27 @@
#define PLAYER_DEPTH 0.4
#define PLAYER_MOVEMENT_DIVIDER 20.0
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
// Camera move modes (first person and third person cameras)
typedef enum { MOVE_FRONT = 0, MOVE_LEFT, MOVE_BACK, MOVE_RIGHT, MOVE_UP, MOVE_DOWN } CameraMove;
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
static Camera internalCamera = {{2,0,2},{0,0,0},{0,1,0}};
static Vector2 cameraAngle = { 0, 0 };
static float cameraTargetDistance = 5;
static Vector3 resetingPosition = { 0, 0, 0 };
static int resetingKey = 'Z';
static Vector2 cameraMousePosition = { 0, 0 };
static Vector2 cameraMouseVariation = { 0, 0 };
static float mouseSensitivity = 0.003;
static int cameraMovementController[6] = { 'W', 'A', 'S', 'D', 'E', 'Q' };
static int cameraMovementCounter = 0;
static bool cameraUseGravity = true;
static int pawnControllingKey = MOUSE_MIDDLE_BUTTON;
static int fnControllingKey = KEY_LEFT_ALT;
static int smoothZoomControllingKey = KEY_LEFT_CONTROL;
static int cameraMoveControl[6] = { 'W', 'A', 'S', 'D', 'E', 'Q' };
static int cameraMoveCounter = 0;
static int cameraUseGravity = 1;
static int panControlKey = 2; // raylib: MOUSE_MIDDLE_BUTTON
static int altControlKey = 342; // raylib: KEY_LEFT_ALT
static int smoothZoomControlKey = 341; // raylib: KEY_LEFT_CONTROL
static int cameraMode = CAMERA_CUSTOM;
@ -95,6 +104,20 @@ static int cameraMode = CAMERA_CUSTOM;
//----------------------------------------------------------------------------------
static void ProcessCamera(Camera *camera, Vector3 *playerPosition);
#if defined(CAMERA_STANDALONE)
// NOTE: Camera controls depend on some raylib input functions
// TODO: Set your own input functions (used in ProcessCamera())
static Vector2 GetMousePosition() { return (Vector2){ 0, 0}; }
static void SetMousePosition(Vector2 pos) {}
static int IsMouseButtonDown(int button) { return 0;}
static int GetMouseWheelMove() { return 0; }
static int GetScreenWidth() { return 1280; }
static int GetScreenHeight() { return 720; }
static void ShowCursor() {}
static void HideCursor() {}
static int IsKeyDown(int key) { return 0; }
#endif
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
@ -123,6 +146,8 @@ void SetCameraMode(int mode)
cameraAngle.y = -40 * DEG2RAD;
internalCamera.target = (Vector3){ 0, 0, 0};
ProcessCamera(&internalCamera, &internalCamera.position);
ShowCursor();
}
else if ((cameraMode == CAMERA_CUSTOM) && (mode == CAMERA_ORBITAL))
{
@ -145,48 +170,37 @@ Camera UpdateCamera(Vector3 *position)
return internalCamera;
}
void SetCameraControls(int frontKey, int leftKey, int backKey, int rightKey, int upKey, int downKey)
void SetCameraMoveControls(int frontKey, int backKey, int leftKey, int rightKey, int upKey, int downKey)
{
cameraMovementController[0] = frontKey;
cameraMovementController[1] = leftKey;
cameraMovementController[2] = backKey;
cameraMovementController[3] = rightKey;
cameraMovementController[4] = upKey;
cameraMovementController[5] = downKey;
cameraMoveControl[MOVE_FRONT] = frontKey;
cameraMoveControl[MOVE_LEFT] = leftKey;
cameraMoveControl[MOVE_BACK] = backKey;
cameraMoveControl[MOVE_RIGHT] = rightKey;
cameraMoveControl[MOVE_UP] = upKey;
cameraMoveControl[MOVE_DOWN] = downKey;
}
void SetCameraMouseSensitivity(float sensitivity)
{
mouseSensitivity = (sensitivity / 10000.0);
}
void SetCameraResetPosition(Vector3 resetPosition)
void SetCameraPanControl(int panKey)
{
resetingPosition = resetPosition;
panControlKey = panKey;
}
void SetCameraResetControl(int resetKey)
void SetCameraAltControl(int altKey)
{
resetingKey = resetKey;
altControlKey = altKey;
}
void SetCameraPawnControl(int pawnControlKey)
void SetCameraSmoothZoomControl(int szKey)
{
pawnControllingKey = pawnControlKey;
smoothZoomControlKey = szKey;
}
void SetCameraFnControl(int fnControlKey)
{
fnControllingKey = fnControlKey;
}
void SetCameraSmoothZoomControl(int smoothZoomControlKey)
{
smoothZoomControllingKey = smoothZoomControlKey;
}
void SetCameraOrbitalTarget(Vector3 target)
void SetCameraTarget(Vector3 target)
{
internalCamera.target = target;
}
@ -197,33 +211,43 @@ void SetCameraOrbitalTarget(Vector3 target)
//----------------------------------------------------------------------------------
// Process desired camera mode and controls
// NOTE: Camera controls depend on some raylib functions:
// Mouse: GetMousePosition(), SetMousePosition(), IsMouseButtonDown(), GetMouseWheelMove()
// System: GetScreenWidth(), GetScreenHeight(), ShowCursor(), HideCursor()
// Keys: IsKeyDown()
static void ProcessCamera(Camera *camera, Vector3 *playerPosition)
{
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) || defined(PLATFORM_RPI)
// Mouse movement detection
Vector2 mousePosition = GetMousePosition();
int mouseWheelMove = GetMouseWheelMove();
int panKey = IsMouseButtonDown(panControlKey); // bool value
int screenWidth = GetScreenWidth();
int screenHeight = GetScreenHeight();
if ((cameraMode != CAMERA_FREE) && (cameraMode != CAMERA_ORBITAL))
{
HideCursor();
if (GetMousePosition().x < GetScreenHeight() / 3) SetMousePosition((Vector2){ GetScreenWidth() - GetScreenHeight() / 3, GetMousePosition().y});
else if (GetMousePosition().y < GetScreenHeight() / 3) SetMousePosition((Vector2){ GetMousePosition().x, GetScreenHeight() - GetScreenHeight() / 3});
else if (GetMousePosition().x > GetScreenWidth() - GetScreenHeight() / 3) SetMousePosition((Vector2) { GetScreenHeight() / 3, GetMousePosition().y});
else if (GetMousePosition().y > GetScreenHeight() - GetScreenHeight() / 3) SetMousePosition((Vector2){ GetMousePosition().x, GetScreenHeight() / 3});
if (mousePosition.x < screenHeight/3) SetMousePosition((Vector2){ screenWidth - screenHeight/3, mousePosition.y});
else if (mousePosition.y < screenHeight/3) SetMousePosition((Vector2){ mousePosition.x, screenHeight - screenHeight/3});
else if (mousePosition.x > screenWidth - screenHeight/3) SetMousePosition((Vector2) { screenHeight/3, mousePosition.y});
else if (mousePosition.y > screenHeight - screenHeight/3) SetMousePosition((Vector2){ mousePosition.x, screenHeight/3});
else
{
cameraMouseVariation.x = GetMousePosition().x - cameraMousePosition.x;
cameraMouseVariation.y = GetMousePosition().y - cameraMousePosition.y;
cameraMouseVariation.x = mousePosition.x - cameraMousePosition.x;
cameraMouseVariation.y = mousePosition.y - cameraMousePosition.y;
}
}
else
{
ShowCursor();
cameraMouseVariation.x = GetMousePosition().x - cameraMousePosition.x;
cameraMouseVariation.y = GetMousePosition().y - cameraMousePosition.y;
cameraMouseVariation.x = mousePosition.x - cameraMousePosition.x;
cameraMouseVariation.y = mousePosition.y - cameraMousePosition.y;
}
cameraMousePosition = GetMousePosition();
cameraMousePosition = mousePosition;
// Support for multiple automatic camera modes
switch (cameraMode)
@ -231,92 +255,93 @@ static void ProcessCamera(Camera *camera, Vector3 *playerPosition)
case CAMERA_FREE:
{
// Camera zoom
if ((cameraTargetDistance < FREE_CAMERA_DISTANCE_MAX_CLAMP) && (GetMouseWheelMove() < 0))
if ((cameraTargetDistance < FREE_CAMERA_DISTANCE_MAX_CLAMP) && (mouseWheelMove < 0))
{
cameraTargetDistance -= (GetMouseWheelMove() * CAMERA_SCROLL_SENSITIVITY);
cameraTargetDistance -= (mouseWheelMove*CAMERA_SCROLL_SENSITIVITY);
if (cameraTargetDistance > FREE_CAMERA_DISTANCE_MAX_CLAMP) cameraTargetDistance = FREE_CAMERA_DISTANCE_MAX_CLAMP;
}
// Camera looking down
else if ((camera->position.y > camera->target.y) && (cameraTargetDistance == FREE_CAMERA_DISTANCE_MAX_CLAMP) && (GetMouseWheelMove() < 0))
else if ((camera->position.y > camera->target.y) && (cameraTargetDistance == FREE_CAMERA_DISTANCE_MAX_CLAMP) && (mouseWheelMove < 0))
{
camera->target.x += GetMouseWheelMove() * (camera->target.x - camera->position.x) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
camera->target.y += GetMouseWheelMove() * (camera->target.y - camera->position.y) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
camera->target.z += GetMouseWheelMove() * (camera->target.z - camera->position.z) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
camera->target.x += mouseWheelMove*(camera->target.x - camera->position.x)*CAMERA_SCROLL_SENSITIVITY/cameraTargetDistance;
camera->target.y += mouseWheelMove*(camera->target.y - camera->position.y)*CAMERA_SCROLL_SENSITIVITY/cameraTargetDistance;
camera->target.z += mouseWheelMove*(camera->target.z - camera->position.z)*CAMERA_SCROLL_SENSITIVITY/cameraTargetDistance;
}
else if ((camera->position.y > camera->target.y) && (camera->target.y >= 0))
{
camera->target.x += GetMouseWheelMove() * (camera->target.x - camera->position.x) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
camera->target.y += GetMouseWheelMove() * (camera->target.y - camera->position.y) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
camera->target.z += GetMouseWheelMove() * (camera->target.z - camera->position.z) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
camera->target.x += mouseWheelMove*(camera->target.x - camera->position.x)*CAMERA_SCROLL_SENSITIVITY/cameraTargetDistance;
camera->target.y += mouseWheelMove*(camera->target.y - camera->position.y)*CAMERA_SCROLL_SENSITIVITY/cameraTargetDistance;
camera->target.z += mouseWheelMove*(camera->target.z - camera->position.z)*CAMERA_SCROLL_SENSITIVITY/cameraTargetDistance;
if (camera->target.y < 0) camera->target.y = -0.001;
}
else if ((camera->position.y > camera->target.y) && (camera->target.y < 0) && (GetMouseWheelMove() > 0))
else if ((camera->position.y > camera->target.y) && (camera->target.y < 0) && (mouseWheelMove > 0))
{
cameraTargetDistance -= (GetMouseWheelMove() * CAMERA_SCROLL_SENSITIVITY);
cameraTargetDistance -= (mouseWheelMove*CAMERA_SCROLL_SENSITIVITY);
if (cameraTargetDistance < FREE_CAMERA_DISTANCE_MIN_CLAMP) cameraTargetDistance = FREE_CAMERA_DISTANCE_MIN_CLAMP;
}
// Camera looking up
else if ((camera->position.y < camera->target.y) && (cameraTargetDistance == FREE_CAMERA_DISTANCE_MAX_CLAMP) && (GetMouseWheelMove() < 0))
else if ((camera->position.y < camera->target.y) && (cameraTargetDistance == FREE_CAMERA_DISTANCE_MAX_CLAMP) && (mouseWheelMove < 0))
{
camera->target.x += GetMouseWheelMove() * (camera->target.x - camera->position.x) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
camera->target.y += GetMouseWheelMove() * (camera->target.y - camera->position.y) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
camera->target.z += GetMouseWheelMove() * (camera->target.z - camera->position.z) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
camera->target.x += mouseWheelMove*(camera->target.x - camera->position.x)*CAMERA_SCROLL_SENSITIVITY/cameraTargetDistance;
camera->target.y += mouseWheelMove*(camera->target.y - camera->position.y)*CAMERA_SCROLL_SENSITIVITY/cameraTargetDistance;
camera->target.z += mouseWheelMove*(camera->target.z - camera->position.z)*CAMERA_SCROLL_SENSITIVITY/cameraTargetDistance;
}
else if ((camera->position.y < camera->target.y) && (camera->target.y <= 0))
{
camera->target.x += GetMouseWheelMove() * (camera->target.x - camera->position.x) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
camera->target.y += GetMouseWheelMove() * (camera->target.y - camera->position.y) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
camera->target.z += GetMouseWheelMove() * (camera->target.z - camera->position.z) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
camera->target.x += mouseWheelMove*(camera->target.x - camera->position.x)*CAMERA_SCROLL_SENSITIVITY/cameraTargetDistance;
camera->target.y += mouseWheelMove*(camera->target.y - camera->position.y)*CAMERA_SCROLL_SENSITIVITY/cameraTargetDistance;
camera->target.z += mouseWheelMove*(camera->target.z - camera->position.z)*CAMERA_SCROLL_SENSITIVITY/cameraTargetDistance;
if (camera->target.y > 0) camera->target.y = 0.001;
}
else if ((camera->position.y < camera->target.y) && (camera->target.y > 0) && (GetMouseWheelMove() > 0))
else if ((camera->position.y < camera->target.y) && (camera->target.y > 0) && (mouseWheelMove > 0))
{
cameraTargetDistance -= (GetMouseWheelMove() * CAMERA_SCROLL_SENSITIVITY);
cameraTargetDistance -= (mouseWheelMove * CAMERA_SCROLL_SENSITIVITY);
if (cameraTargetDistance < FREE_CAMERA_DISTANCE_MIN_CLAMP) cameraTargetDistance = FREE_CAMERA_DISTANCE_MIN_CLAMP;
}
// Inputs
if (IsKeyDown(fnControllingKey))
if (IsKeyDown(altControlKey))
{
if (IsKeyDown(smoothZoomControllingKey))
if (IsKeyDown(smoothZoomControlKey))
{
// Camera smooth zoom
if (IsMouseButtonDown(pawnControllingKey)) cameraTargetDistance += (cameraMouseVariation.y * FREE_CAMERA_SMOOTH_ZOOM_SENSITIVITY);
if (panKey) cameraTargetDistance += (cameraMouseVariation.y*FREE_CAMERA_SMOOTH_ZOOM_SENSITIVITY);
}
// Camera orientation calculation
else if (IsMouseButtonDown(pawnControllingKey))
else if (panKey)
{
// Camera orientation calculation
// Get the mouse sensitivity
cameraAngle.x += cameraMouseVariation.x * -FREE_CAMERA_MOUSE_SENSITIVITY;
cameraAngle.y += cameraMouseVariation.y * -FREE_CAMERA_MOUSE_SENSITIVITY;
cameraAngle.x += cameraMouseVariation.x*-FREE_CAMERA_MOUSE_SENSITIVITY;
cameraAngle.y += cameraMouseVariation.y*-FREE_CAMERA_MOUSE_SENSITIVITY;
// Angle clamp
if (cameraAngle.y > FREE_CAMERA_MIN_CLAMP * DEG2RAD) cameraAngle.y = FREE_CAMERA_MIN_CLAMP * DEG2RAD;
else if (cameraAngle.y < FREE_CAMERA_MAX_CLAMP * DEG2RAD) cameraAngle.y = FREE_CAMERA_MAX_CLAMP * DEG2RAD;
if (cameraAngle.y > FREE_CAMERA_MIN_CLAMP*DEG2RAD) cameraAngle.y = FREE_CAMERA_MIN_CLAMP*DEG2RAD;
else if (cameraAngle.y < FREE_CAMERA_MAX_CLAMP*DEG2RAD) cameraAngle.y = FREE_CAMERA_MAX_CLAMP*DEG2RAD;
}
}
// Paning
else if (IsMouseButtonDown(pawnControllingKey))
else if (panKey)
{
camera->target.x += ((cameraMouseVariation.x * -FREE_CAMERA_MOUSE_SENSITIVITY) * cos(cameraAngle.x) + (cameraMouseVariation.y * FREE_CAMERA_MOUSE_SENSITIVITY) * sin(cameraAngle.x) * sin(cameraAngle.y)) * (cameraTargetDistance / FREE_CAMERA_PANNING_DIVIDER);
camera->target.y += ((cameraMouseVariation.y * FREE_CAMERA_MOUSE_SENSITIVITY) * cos(cameraAngle.y)) * (cameraTargetDistance / FREE_CAMERA_PANNING_DIVIDER);
camera->target.z += ((cameraMouseVariation.x * FREE_CAMERA_MOUSE_SENSITIVITY) * sin(cameraAngle.x) + (cameraMouseVariation.y * FREE_CAMERA_MOUSE_SENSITIVITY) * cos(cameraAngle.x) * sin(cameraAngle.y)) * (cameraTargetDistance / FREE_CAMERA_PANNING_DIVIDER);
camera->target.x += ((cameraMouseVariation.x*-FREE_CAMERA_MOUSE_SENSITIVITY)*cos(cameraAngle.x) + (cameraMouseVariation.y*FREE_CAMERA_MOUSE_SENSITIVITY)*sin(cameraAngle.x)*sin(cameraAngle.y))*(cameraTargetDistance/FREE_CAMERA_PANNING_DIVIDER);
camera->target.y += ((cameraMouseVariation.y*FREE_CAMERA_MOUSE_SENSITIVITY)*cos(cameraAngle.y))*(cameraTargetDistance/FREE_CAMERA_PANNING_DIVIDER);
camera->target.z += ((cameraMouseVariation.x*FREE_CAMERA_MOUSE_SENSITIVITY)*sin(cameraAngle.x) + (cameraMouseVariation.y*FREE_CAMERA_MOUSE_SENSITIVITY)*cos(cameraAngle.x)*sin(cameraAngle.y))*(cameraTargetDistance/FREE_CAMERA_PANNING_DIVIDER);
}
// Focus to center
if (IsKeyDown(resetingKey)) camera->target = resetingPosition;
// TODO: Move this function out of the module?
if (IsKeyDown('Z')) camera->target = (Vector3){ 0, 0, 0 };
// Camera position update
camera->position.x = sin(cameraAngle.x) * cameraTargetDistance * cos(cameraAngle.y) + camera->target.x;
camera->position.x = sin(cameraAngle.x)*cameraTargetDistance*cos(cameraAngle.y) + camera->target.x;
if (cameraAngle.y <= 0) camera->position.y = sin(cameraAngle.y) * cameraTargetDistance * sin(cameraAngle.y) + camera->target.y;
else camera->position.y = -sin(cameraAngle.y) * cameraTargetDistance * sin(cameraAngle.y) + camera->target.y;
if (cameraAngle.y <= 0) camera->position.y = sin(cameraAngle.y)*cameraTargetDistance*sin(cameraAngle.y) + camera->target.y;
else camera->position.y = -sin(cameraAngle.y)*cameraTargetDistance*sin(cameraAngle.y) + camera->target.y;
camera->position.z = cos(cameraAngle.x) * cameraTargetDistance * cos(cameraAngle.y) + camera->target.z;
camera->position.z = cos(cameraAngle.x)*cameraTargetDistance*cos(cameraAngle.y) + camera->target.z;
} break;
case CAMERA_ORBITAL:
@ -324,126 +349,126 @@ static void ProcessCamera(Camera *camera, Vector3 *playerPosition)
cameraAngle.x += ORBITAL_CAMERA_SPEED;
// Camera zoom
cameraTargetDistance -= (GetMouseWheelMove() * CAMERA_SCROLL_SENSITIVITY);
cameraTargetDistance -= (mouseWheelMove*CAMERA_SCROLL_SENSITIVITY);
// Camera distance clamp
if (cameraTargetDistance < THIRD_PERSON_DISTANCE_CLAMP) cameraTargetDistance = THIRD_PERSON_DISTANCE_CLAMP;
// Focus to center
if (IsKeyDown('Z')) camera->target = (Vector3) { 0, 0, 0 };
if (IsKeyDown('Z')) camera->target = (Vector3){ 0, 0, 0 };
// Camera position update
camera->position.x = sin(cameraAngle.x) * cameraTargetDistance * cos(cameraAngle.y) + camera->target.x;
camera->position.x = sin(cameraAngle.x)*cameraTargetDistance*cos(cameraAngle.y) + camera->target.x;
if (cameraAngle.y <= 0) camera->position.y = sin(cameraAngle.y) * cameraTargetDistance * sin(cameraAngle.y) + camera->target.y;
else camera->position.y = -sin(cameraAngle.y) * cameraTargetDistance * sin(cameraAngle.y) + camera->target.y;
if (cameraAngle.y <= 0) camera->position.y = sin(cameraAngle.y)*cameraTargetDistance*sin(cameraAngle.y) + camera->target.y;
else camera->position.y = -sin(cameraAngle.y)*cameraTargetDistance*sin(cameraAngle.y) + camera->target.y;
camera->position.z = cos(cameraAngle.x) * cameraTargetDistance * cos(cameraAngle.y) + camera->target.z;
camera->position.z = cos(cameraAngle.x)*cameraTargetDistance*cos(cameraAngle.y) + camera->target.z;
} break;
case CAMERA_FIRST_PERSON:
case CAMERA_THIRD_PERSON:
{
bool isMoving = false;
int isMoving = 0;
// Keyboard inputs
if (IsKeyDown(cameraMovementController[0]))
if (IsKeyDown(cameraMoveControl[MOVE_FRONT]))
{
playerPosition->x -= sin(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
playerPosition->z -= cos(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
if (!cameraUseGravity) camera->position.y += sin(cameraAngle.y) / PLAYER_MOVEMENT_DIVIDER;
playerPosition->x -= sin(cameraAngle.x)/PLAYER_MOVEMENT_DIVIDER;
playerPosition->z -= cos(cameraAngle.x)/PLAYER_MOVEMENT_DIVIDER;
if (!cameraUseGravity) camera->position.y += sin(cameraAngle.y)/PLAYER_MOVEMENT_DIVIDER;
isMoving = true;
isMoving = 1;
}
else if (IsKeyDown(cameraMovementController[2]))
else if (IsKeyDown(cameraMoveControl[MOVE_BACK]))
{
playerPosition->x += sin(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
playerPosition->z += cos(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
if (!cameraUseGravity) camera->position.y -= sin(cameraAngle.y) / PLAYER_MOVEMENT_DIVIDER;
playerPosition->x += sin(cameraAngle.x)/PLAYER_MOVEMENT_DIVIDER;
playerPosition->z += cos(cameraAngle.x)/PLAYER_MOVEMENT_DIVIDER;
if (!cameraUseGravity) camera->position.y -= sin(cameraAngle.y)/PLAYER_MOVEMENT_DIVIDER;
isMoving = true;
isMoving = 1;
}
if (IsKeyDown(cameraMovementController[1]))
if (IsKeyDown(cameraMoveControl[MOVE_LEFT]))
{
playerPosition->x -= cos(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
playerPosition->z += sin(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
playerPosition->x -= cos(cameraAngle.x)/PLAYER_MOVEMENT_DIVIDER;
playerPosition->z += sin(cameraAngle.x)/PLAYER_MOVEMENT_DIVIDER;
isMoving = true;
isMoving = 1;
}
else if (IsKeyDown(cameraMovementController[3]))
else if (IsKeyDown(cameraMoveControl[MOVE_RIGHT]))
{
playerPosition->x += cos(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
playerPosition->z -= sin(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
playerPosition->x += cos(cameraAngle.x)/PLAYER_MOVEMENT_DIVIDER;
playerPosition->z -= sin(cameraAngle.x)/PLAYER_MOVEMENT_DIVIDER;
isMoving = true;
isMoving = 1;
}
if (IsKeyDown(cameraMovementController[4]))
if (IsKeyDown(cameraMoveControl[MOVE_UP]))
{
if (!cameraUseGravity) playerPosition->y += 1 / PLAYER_MOVEMENT_DIVIDER;
if (!cameraUseGravity) playerPosition->y += 1/PLAYER_MOVEMENT_DIVIDER;
}
else if (IsKeyDown(cameraMovementController[5]))
else if (IsKeyDown(cameraMoveControl[MOVE_DOWN]))
{
if (!cameraUseGravity) playerPosition->y -= 1 / PLAYER_MOVEMENT_DIVIDER;
if (!cameraUseGravity) playerPosition->y -= 1/PLAYER_MOVEMENT_DIVIDER;
}
if (cameraMode == CAMERA_THIRD_PERSON)
{
// Camera orientation calculation
// Get the mouse sensitivity
cameraAngle.x += cameraMouseVariation.x * -mouseSensitivity;
cameraAngle.y += cameraMouseVariation.y * -mouseSensitivity;
cameraAngle.x += cameraMouseVariation.x*-mouseSensitivity;
cameraAngle.y += cameraMouseVariation.y*-mouseSensitivity;
// Angle clamp
if (cameraAngle.y > THIRD_PERSON_MIN_CLAMP * DEG2RAD) cameraAngle.y = THIRD_PERSON_MIN_CLAMP * DEG2RAD;
else if (cameraAngle.y < THIRD_PERSON_MAX_CLAMP * DEG2RAD) cameraAngle.y = THIRD_PERSON_MAX_CLAMP * DEG2RAD;
if (cameraAngle.y > THIRD_PERSON_MIN_CLAMP*DEG2RAD) cameraAngle.y = THIRD_PERSON_MIN_CLAMP*DEG2RAD;
else if (cameraAngle.y < THIRD_PERSON_MAX_CLAMP*DEG2RAD) cameraAngle.y = THIRD_PERSON_MAX_CLAMP*DEG2RAD;
// Camera zoom
cameraTargetDistance -= (GetMouseWheelMove() * CAMERA_SCROLL_SENSITIVITY);
cameraTargetDistance -= (mouseWheelMove*CAMERA_SCROLL_SENSITIVITY);
// Camera distance clamp
if (cameraTargetDistance < THIRD_PERSON_DISTANCE_CLAMP) cameraTargetDistance = THIRD_PERSON_DISTANCE_CLAMP;
// Camera is always looking at player
camera->target.x = playerPosition->x + THIRD_PERSON_OFFSET.x * cos(cameraAngle.x) + THIRD_PERSON_OFFSET.z * sin(cameraAngle.x);
camera->target.y = playerPosition->y + PLAYER_HEIGHT * FIRST_PERSON_HEIGHT_RELATIVE_EYES_POSITION + THIRD_PERSON_OFFSET.y;
camera->target.z = playerPosition->z + THIRD_PERSON_OFFSET.z * sin(cameraAngle.x) - THIRD_PERSON_OFFSET.x * sin(cameraAngle.x);
camera->target.x = playerPosition->x + THIRD_PERSON_OFFSET.x*cos(cameraAngle.x) + THIRD_PERSON_OFFSET.z*sin(cameraAngle.x);
camera->target.y = playerPosition->y + PLAYER_HEIGHT*FIRST_PERSON_HEIGHT_RELATIVE_EYES_POSITION + THIRD_PERSON_OFFSET.y;
camera->target.z = playerPosition->z + THIRD_PERSON_OFFSET.z*sin(cameraAngle.x) - THIRD_PERSON_OFFSET.x*sin(cameraAngle.x);
// Camera position update
camera->position.x = sin(cameraAngle.x) * cameraTargetDistance * cos(cameraAngle.y) + camera->target.x;
camera->position.x = sin(cameraAngle.x)*cameraTargetDistance*cos(cameraAngle.y) + camera->target.x;
if (cameraAngle.y <= 0) camera->position.y = sin(cameraAngle.y) * cameraTargetDistance * sin(cameraAngle.y) + camera->target.y;
else camera->position.y = -sin(cameraAngle.y) * cameraTargetDistance * sin(cameraAngle.y) + camera->target.y;
if (cameraAngle.y <= 0) camera->position.y = sin(cameraAngle.y)*cameraTargetDistance*sin(cameraAngle.y) + camera->target.y;
else camera->position.y = -sin(cameraAngle.y)*cameraTargetDistance*sin(cameraAngle.y) + camera->target.y;
camera->position.z = cos(cameraAngle.x) * cameraTargetDistance * cos(cameraAngle.y) + camera->target.z;
camera->position.z = cos(cameraAngle.x)*cameraTargetDistance*cos(cameraAngle.y) + camera->target.z;
}
else
else // CAMERA_FIRST_PERSON
{
if (isMoving) cameraMovementCounter++;
if (isMoving) cameraMoveCounter++;
// Camera orientation calculation
// Get the mouse sensitivity
cameraAngle.x += cameraMouseVariation.x * -mouseSensitivity;
cameraAngle.y += cameraMouseVariation.y * -mouseSensitivity;
cameraAngle.x += cameraMouseVariation.x*-mouseSensitivity;
cameraAngle.y += cameraMouseVariation.y*-mouseSensitivity;
// Angle clamp
if (cameraAngle.y > FIRST_PERSON_MIN_CLAMP * DEG2RAD) cameraAngle.y = FIRST_PERSON_MIN_CLAMP * DEG2RAD;
else if (cameraAngle.y < FIRST_PERSON_MAX_CLAMP * DEG2RAD) cameraAngle.y = FIRST_PERSON_MAX_CLAMP * DEG2RAD;
if (cameraAngle.y > FIRST_PERSON_MIN_CLAMP*DEG2RAD) cameraAngle.y = FIRST_PERSON_MIN_CLAMP*DEG2RAD;
else if (cameraAngle.y < FIRST_PERSON_MAX_CLAMP*DEG2RAD) cameraAngle.y = FIRST_PERSON_MAX_CLAMP*DEG2RAD;
// Camera is always looking at player
camera->target.x = camera->position.x - sin(cameraAngle.x) * FIRST_PERSON_FOCUS_DISTANCE;
camera->target.y = camera->position.y + sin(cameraAngle.y) * FIRST_PERSON_FOCUS_DISTANCE;
camera->target.z = camera->position.z - cos(cameraAngle.x) * FIRST_PERSON_FOCUS_DISTANCE;
camera->target.x = camera->position.x - sin(cameraAngle.x)*FIRST_PERSON_FOCUS_DISTANCE;
camera->target.y = camera->position.y + sin(cameraAngle.y)*FIRST_PERSON_FOCUS_DISTANCE;
camera->target.z = camera->position.z - cos(cameraAngle.x)*FIRST_PERSON_FOCUS_DISTANCE;
camera->position.x = playerPosition->x;
camera->position.y = (playerPosition->y + PLAYER_HEIGHT * FIRST_PERSON_HEIGHT_RELATIVE_EYES_POSITION) - sin(cameraMovementCounter / FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER) / FIRST_PERSON_STEP_DIVIDER;
camera->position.y = (playerPosition->y + PLAYER_HEIGHT*FIRST_PERSON_HEIGHT_RELATIVE_EYES_POSITION) - sin(cameraMoveCounter/FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER)/FIRST_PERSON_STEP_DIVIDER;
camera->position.z = playerPosition->z;
camera->up.x = sin(cameraMovementCounter / (FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER * 2)) / FIRST_PERSON_WAVING_DIVIDER;
camera->up.z = -sin(cameraMovementCounter / (FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER * 2)) / FIRST_PERSON_WAVING_DIVIDER;
camera->up.x = sin(cameraMoveCounter/(FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER*2))/FIRST_PERSON_WAVING_DIVIDER;
camera->up.z = -sin(cameraMoveCounter/(FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER*2))/FIRST_PERSON_WAVING_DIVIDER;
}
} break;
default: break;
}
#endif
}
}

View File

@ -24,7 +24,12 @@
#ifndef CAMERA_H
#define CAMERA_H
#include "raylib.h"
#ifndef PI
#define PI 3.14159265358979323846
#endif
#define DEG2RAD (PI / 180.0f)
#define RAD2DEG (180.0f / PI)
//----------------------------------------------------------------------------------
// Defines and Macros
@ -33,10 +38,30 @@
//----------------------------------------------------------------------------------
// Types and Structures Definition
// NOTE: Below types are required for CAMERA_STANDALONE usage
//----------------------------------------------------------------------------------
// Camera modes
typedef enum { CAMERA_CUSTOM = 0, CAMERA_FREE, CAMERA_ORBITAL, CAMERA_FIRST_PERSON, CAMERA_THIRD_PERSON } CameraMode;
// Vector2 type
typedef struct Vector2 {
float x;
float y;
} Vector2;
// Vector3 type
typedef struct Vector3 {
float x;
float y;
float z;
} Vector3;
// Camera type, defines a camera position/orientation in 3d space
typedef struct Camera {
Vector3 position;
Vector3 target;
Vector3 up;
} Camera;
#ifdef __cplusplus
extern "C" { // Prevents name mangling of functions
@ -50,17 +75,19 @@ extern "C" { // Prevents name mangling of functions
//----------------------------------------------------------------------------------
// Module Functions Declaration
//----------------------------------------------------------------------------------
void SetCameraMode(int mode); // Select camera mode (multiple camera modes available)
Camera UpdateCamera(Vector3 *position); // Update camera with position
void SetCameraMode(int mode); // Set camera mode (multiple camera modes available)
Camera UpdateCamera(Vector3 *playerPosition); // Update camera and player position (1st person and 3rd person cameras)
void SetCameraControls(int front, int left, int back, int right, int up, int down);
void SetCameraMouseSensitivity(float sensitivity);
void SetCameraResetPosition(Vector3 resetPosition);
void SetCameraResetControl(int resetKey);
void SetCameraPawnControl(int pawnControlKey);
void SetCameraFnControl(int fnControlKey);
void SetCameraSmoothZoomControl(int smoothZoomControlKey);
void SetCameraOrbitalTarget(Vector3 target);
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 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 SetCameraMouseSensitivity(float sensitivity); // Set camera mouse sensitivity (1st person and 3rd person cameras)
void SetCameraTarget(Vector3 target); // Set internal camera target
#ifdef __cplusplus
}

View File

@ -17,7 +17,7 @@
*
* On PLATFORM_RPI, graphic device is managed by EGL and input system is coded in raw mode.
*
* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
* Copyright (c) 2014 Ramon Santamaria (@raysan5)
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
@ -164,7 +164,7 @@ static bool customCursor = false; // Tracks if custom cursor has been
static bool cursorOnScreen = false; // Tracks if cursor is inside client area
static Texture2D cursor; // Cursor texture
static Vector2 mousePosition;
static Vector2 mousePosition; // Mouse position on screen
static char previousKeyState[512] = { 0 }; // Required to check if key pressed/released once
static char currentKeyState[512] = { 0 }; // Required to check if key pressed/released once
@ -179,9 +179,12 @@ static int previousMouseWheelY = 0; // Required to track mouse wheel var
static int currentMouseWheelY = 0; // Required to track mouse wheel variation
static int exitKey = KEY_ESCAPE; // Default exit key (ESC)
static int lastKeyPressed = -1;
static int lastKeyPressed = -1; // Register last key pressed
static bool cursorHidden;
static bool cursorHidden; // Track if cursor is hidden
static char **dropFilesPath; // Store dropped files paths as strings
static int dropFilesCount = 0; // Count stored strings
#endif
static double currentTime, previousTime; // Used to track timmings
@ -189,8 +192,8 @@ 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;
static bool showLogo = false;
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)
@ -198,19 +201,6 @@ static bool showLogo = false;
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 UpdateMusicStream(void); // [Module: audio] Updates buffers for music streaming
extern Vector2 GetRawPosition(void);
extern void ResetGestures(void);
#if defined(PLATFORM_ANDROID)
extern void InitAndroidGestures(struct android_app *app);
#endif
#if defined(PLATFORM_WEB)
extern void InitWebGestures(void); // [Module: gestures] Initializes emscripten gestures for web
#endif
//----------------------------------------------------------------------------------
// Module specific Functions Declaration
//----------------------------------------------------------------------------------
@ -241,7 +231,11 @@ static void CharCallback(GLFWwindow *window, unsigned int key);
static void ScrollCallback(GLFWwindow *window, double xoffset, double yoffset); // GLFW3 Srolling Callback, runs on mouse wheel
static void CursorEnterCallback(GLFWwindow *window, int enter); // GLFW3 Cursor Enter Callback, cursor enters client area
static void WindowSizeCallback(GLFWwindow *window, int width, int height); // GLFW3 WindowSize Callback, runs when window is resized
static void WindowIconifyCallback(GLFWwindow* window, int iconified); // GLFW3 WindowIconify Callback, runs when window is minimized/restored
static void WindowIconifyCallback(GLFWwindow *window, int iconified); // GLFW3 WindowIconify Callback, runs when window is minimized/restored
#endif
#if defined(PLATFORM_DESKTOP)
static void WindowDropCallback(GLFWwindow *window, int count, const char **paths); // GLFW3 Window Drop Callback, runs when drop files into window
#endif
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI)
@ -284,10 +278,6 @@ void InitWindow(int width, int height, const char *title)
InitGamepad(); // Gamepad init
#endif
#if defined(PLATFORM_WEB)
InitWebGestures(); // Init touch input events for web
#endif
mousePosition.x = screenWidth/2;
mousePosition.y = screenHeight/2;
@ -341,7 +331,7 @@ void InitWindow(int width, int height, struct android_app *state)
//state->userData = &engine;
app->onAppCmd = AndroidCommandCallback;
InitAndroidGestures(app);
//InitGesturesSystem(app); // NOTE: Must be called by user
InitAssetManager(app->activity->assetManager);
@ -412,6 +402,16 @@ bool WindowShouldClose(void)
#endif
}
// Detect if window has been minimized (or lost focus)
bool IsWindowMinimized(void)
{
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
return windowMinimized;
#else
return false;
#endif
}
// Fullscreen toggle
void ToggleFullscreen(void)
{
@ -497,14 +497,8 @@ void EndDrawing(void)
SwapBuffers(); // Copy back buffer to front buffer
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB)
ResetGestures();
#endif
PollInputEvents(); // Poll user events
UpdateMusicStream(); // NOTE: Function checks if music is enabled
currentTime = GetTime();
drawTime = currentTime - previousTime;
previousTime = currentTime;
@ -538,6 +532,7 @@ void Begin3dMode(Camera camera)
double top = 0.1f*tan(45.0f*PI / 360.0f);
double right = top*aspect;
// NOTE: zNear and zFar values are important when computing depth buffer values
rlFrustum(-right, right, -top, top, 0.1f, 1000.0f);
rlMatrixMode(RL_MODELVIEW); // Switch back to modelview matrix
@ -565,7 +560,7 @@ void End3dMode(void)
// Set target FPS for the game
void SetTargetFPS(int fps)
{
targetTime = 1 / (float)fps;
targetTime = 1 / (double)fps;
TraceLog(INFO, "Target time per frame: %02.03f milliseconds", (float)targetTime*1000);
}
@ -573,16 +568,16 @@ void SetTargetFPS(int fps)
// Returns current FPS
float GetFPS(void)
{
return (1/(float)frameTime);
return (float)(1/frameTime);
}
// Returns time in seconds for one frame
float GetFrameTime(void)
{
// As we are operating quite a lot with frameTime, it could be no stable
// so we round it before before passing around to be used
// As we are operate quite a lot with frameTime,
// it could be no stable, so we round it before passing it around
// NOTE: There are still problems with high framerates (>500fps)
double roundedFrameTime = round(frameTime*10000) / 10000;
double roundedFrameTime = round(frameTime*10000)/10000;
return (float)roundedFrameTime; // Time in seconds to run a frame
}
@ -643,6 +638,34 @@ void ShowLogo(void)
showLogo = true;
}
// Check if a file have been dropped into window
bool IsFileDropped(void)
{
if (dropFilesCount > 0) return true;
else return false;
}
// Retrieve dropped files into window
char **GetDroppedFiles(int *count)
{
*count = dropFilesCount;
return dropFilesPath;
}
// Clear dropped files paths buffer
void ClearDroppedFiles(void)
{
if (dropFilesCount > 0)
{
for (int i = 0; i < dropFilesCount; i++) free(dropFilesPath[i]);
free(dropFilesPath);
dropFilesCount = 0;
}
}
// TODO: Gives the ray trace from mouse position
Ray GetMouseRay(Vector2 mousePosition, Camera camera)
{
Ray ray;
@ -650,24 +673,28 @@ Ray GetMouseRay(Vector2 mousePosition, Camera camera)
Matrix proj = MatrixIdentity();
Matrix view = MatrixLookAt(camera.position, camera.target, camera.up);
// Calculate projection matrix for the camera
float aspect = (GLfloat)GetScreenWidth()/(GLfloat)GetScreenHeight();
double top = 0.1f*tanf(45.0f*PI / 360.0f);
double top = 0.1f*tanf(45.0f*PI/360.0f);
double right = top*aspect;
// NOTE: zNear and zFar values are important for depth
proj = MatrixFrustum(-right, right, -top, top, 0.01f, 1000.0f);
MatrixTranspose(&proj);
float realy = (float)GetScreenHeight() - mousePosition.y;
// NOTE: Our screen origin is top-left instead of bottom-left: transform required!
float invertedMouseY = (float)GetScreenHeight() - mousePosition.y;
// NOTE: Do I really need to get z value from depth buffer?
//float z;
// glReadPixels(mousePosition.x, mousePosition.y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &z);
//glReadPixels(mousePosition.x, mousePosition.y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &z);
//http://www.bfilipek.com/2012/06/select-mouse-opengl.html
Vector3 nearPoint = { mousePosition.x, realy, 0.0f };
Vector3 farPoint = { mousePosition.x, realy, 1.0f };
Vector3 nearPoint = { mousePosition.x, invertedMouseY, 0.0f };
Vector3 farPoint = { mousePosition.x, invertedMouseY, 1.0f };
//nearPoint = internalCamera.position;
farPoint = rlglUnproject(farPoint, proj, view);
nearPoint = rlglUnproject(nearPoint, proj, view);
farPoint = rlglUnproject(farPoint, proj, view); // TODO: it seems it doesn't work...
Vector3 direction = VectorSubtract(farPoint, nearPoint);
VectorNormalize(&direction);
@ -791,7 +818,11 @@ void SetMousePosition(Vector2 position)
// Returns mouse wheel movement Y
int GetMouseWheelMove(void)
{
#if defined(PLATFORM_WEB)
return previousMouseWheelY/100;
#else
return previousMouseWheelY;
#endif
}
// Hide mouse cursor
@ -933,40 +964,6 @@ bool IsGamepadButtonUp(int gamepad, int button)
}
#endif
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB)
// Returns touch position X
int GetTouchX(void)
{
return (int)GetRawPosition().x;
}
// Returns touch position Y
int GetTouchY(void)
{
return (int)GetRawPosition().y;
}
// Returns touch position XY
Vector2 GetTouchPosition(void)
{
Vector2 position = GetRawPosition();
if ((screenWidth > displayWidth) || (screenHeight > displayHeight))
{
// TODO: Seems to work ok but... review!
position.x = position.x*((float)screenWidth / (float)(displayWidth - renderOffsetX)) - renderOffsetX/2;
position.y = position.y*((float)screenHeight / (float)(displayHeight - renderOffsetY)) - renderOffsetY/2;
}
else
{
position.x = position.x*((float)renderWidth / (float)displayWidth) - renderOffsetX/2;
position.y = position.y*((float)renderHeight / (float)displayHeight) - renderOffsetY/2;
}
return position;
}
#endif
//----------------------------------------------------------------------------------
// Module specific Functions Definition
//----------------------------------------------------------------------------------
@ -1010,7 +1007,8 @@ static void InitDisplay(int width, int height)
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); // Avoid window being resizable
//glfwWindowHint(GLFW_DECORATED, GL_TRUE); // Border and buttons on Window
//glfwWindowHint(GLFW_RED_BITS, 8); // Bit depths of color components for default framebuffer
//glfwWindowHint(GLFW_RED_BITS, 8); // Color framebuffer red component bits
//glfwWindowHint(GLFW_DEPTH_BITS, 16); // Depth buffer bits (24 by default)
//glfwWindowHint(GLFW_REFRESH_RATE, 0); // Refresh rate for fullscreen window
//glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API); // Default OpenGL API to use. Alternative: GLFW_OPENGL_ES_API
//glfwWindowHint(GLFW_AUX_BUFFERS, 0); // Number of auxiliar buffers
@ -1074,6 +1072,9 @@ static void InitDisplay(int width, int height)
glfwSetCharCallback(window, CharCallback);
glfwSetScrollCallback(window, ScrollCallback);
glfwSetWindowIconifyCallback(window, WindowIconifyCallback);
#if defined(PLATFORM_DESKTOP)
glfwSetDropCallback(window, WindowDropCallback);
#endif
glfwMakeContextCurrent(window);
@ -1106,7 +1107,14 @@ static void InitDisplay(int width, int height)
VC_RECT_T srcRect;
#endif
// TODO: if (configFlags & FLAG_MSAA_4X_HINT) activate (EGL_SAMPLES, 4)
EGLint samples = 0;
EGLint sampleBuffer = 0;
if (configFlags & FLAG_MSAA_4X_HINT)
{
samples = 4;
sampleBuffer = 1;
}
const EGLint framebufferAttribs[] =
{
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, // Type of context support -> Required on RPI?
@ -1115,10 +1123,10 @@ static void InitDisplay(int width, int height)
EGL_GREEN_SIZE, 8, // GREEN color bit depth (alternative: 6)
EGL_BLUE_SIZE, 8, // BLUE color bit depth (alternative: 5)
//EGL_ALPHA_SIZE, 8, // ALPHA bit depth
EGL_DEPTH_SIZE, 8, // Depth buffer size (Required to use Depth testing!)
EGL_DEPTH_SIZE, 16, // Depth buffer size (Required to use Depth testing!)
//EGL_STENCIL_SIZE, 8, // Stencil buffer size
//EGL_SAMPLE_BUFFERS, 1, // Activate MSAA
//EGL_SAMPLES, 4, // 4x Antialiasing (Free on MALI GPUs)
EGL_SAMPLE_BUFFERS, sampleBuffer, // Activate MSAA
EGL_SAMPLES, samples, // 4x Antialiasing if activated (Free on MALI GPUs)
EGL_NONE
};
@ -1317,20 +1325,28 @@ static void WindowSizeCallback(GLFWwindow *window, int width, int height)
// GLFW3 WindowIconify Callback, runs when window is minimized/restored
static void WindowIconifyCallback(GLFWwindow* window, int iconified)
{
if (iconified)
{
// The window was iconified
PauseMusicStream();
if (iconified) windowMinimized = true; // The window was iconified
else windowMinimized = false; // The window was restored
}
#endif
windowMinimized = true;
}
else
#if defined(PLATFORM_DESKTOP)
// GLFW3 Window Drop Callback, runs when drop files into window
// NOTE: Paths are stored in dinamic memory for further retrieval
// Everytime new files are dropped, old ones are discarded
static void WindowDropCallback(GLFWwindow *window, int count, const char **paths)
{
ClearDroppedFiles();
dropFilesPath = (char **)malloc(sizeof(char *)*count);
for (int i = 0; i < count; i++)
{
// The window was restored
ResumeMusicStream();
windowMinimized = false;
dropFilesPath[i] = (char *)malloc(sizeof(char)*256); // Max path length set to 256 char
strcpy(dropFilesPath[i], paths[i]);
}
dropFilesCount = count;
}
#endif
@ -1379,7 +1395,7 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
case APP_CMD_GAINED_FOCUS:
{
TraceLog(INFO, "APP_CMD_GAINED_FOCUS");
ResumeMusicStream();
//ResumeMusicStream();
} break;
case APP_CMD_PAUSE:
{
@ -1389,7 +1405,7 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
{
//DrawFrame();
TraceLog(INFO, "APP_CMD_LOST_FOCUS");
PauseMusicStream();
//PauseMusicStream();
} break;
case APP_CMD_TERM_WINDOW:
{
@ -1476,7 +1492,7 @@ static double GetTime(void)
clock_gettime(CLOCK_MONOTONIC, &ts);
uint64_t time = ts.tv_sec*1000000000LLU + (uint64_t)ts.tv_nsec;
return (double)(time - baseTime) * 1e-9;
return (double)(time - baseTime)*1e-9;
#endif
}

View File

@ -1,8 +1,6 @@
/**********************************************************************************************
*
* raylib.gestures
*
* Gestures Detection and Usage Functions Definitions
* raylib Gestures System - Gestures Detection and Usage Functions (Android and HTML5)
*
* Copyright (c) 2015 Marc Palau and Ramon Santamaria
*
@ -23,8 +21,13 @@
*
**********************************************************************************************/
#include "raylib.h"
#include "utils.h"
//#define GESTURES_STANDALONE // NOTE: To use the gestures module as standalone lib, just uncomment this line
#if defined(GESTURES_STANDALONE)
#include "gestures.h"
#else
#include "raylib.h" // Required for typedef(s): Vector2, Gestures
#endif
#include <stdlib.h> // malloc(), free()
#include <stdio.h> // printf(), fprintf()
@ -53,9 +56,11 @@
//----------------------------------------------------------------------------------
#define FORCE_TO_SWIPE 20
#define TAP_TIMEOUT 300
#define MAX_TOUCH_POINTS 4
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
typedef enum {
TYPE_MOTIONLESS,
TYPE_DRAG,
@ -75,72 +80,56 @@ typedef struct {
Vector2 position[MAX_TOUCH_POINTS];
} GestureEvent;
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
static GestureType gestureType = TYPE_MOTIONLESS;
static double eventTime = 0;
//static int32_t touchId; // Not used...
//static int32_t touchId; // Not used...
// Tap
// Our initial press position on tap
// Tap gesture variables
static Vector2 initialTapPosition = { 0, 0 };
// Double tap
// If we are double tapping or not
// Double Tap gesture variables
static bool doubleTapping = false;
// If we recently made a tap
static bool untap = false;
static bool untap = false; // Check if recently done a tap
// Drag
// Our initial press position on drag
// Drag gesture variables
static Vector2 initialDragPosition = { 0, 0 };
// Position that will compare itself with the mouse one
static Vector2 endDragPosition = { 0, 0 };
// Position of the last event detection
static Vector2 lastDragPosition = { 0, 0 };
// The total drag vector
static Vector2 dragVector = { 0, 0 };
// The distance traveled dragging
static float magnitude = 0;
// The angle direction of the drag
static float angle = 0;
// A magnitude to calculate how fast we did the drag ( pixels per frame )
static float intensity = 0;
// Time that have passed while dragging
static int draggingTimeCounter = 0;
// Pinch
// First initial pinch position
static float magnitude = 0; // Distance traveled dragging
static float angle = 0; // Angle direction of the drag
static float intensity = 0; // How fast we did the drag (pixels per frame)
static int draggingTimeCounter = 0; // Time that have passed while dragging
// Pinch gesture variables
static Vector2 firstInitialPinchPosition = { 0, 0 };
// Second initial pinch position
static Vector2 secondInitialPinchPosition = { 0, 0 };
// First end pinch position
static Vector2 firstEndPinchPosition = { 0, 0 };
// Second end pinch position
static Vector2 secondEndPinchPosition = { 0, 0 };
// Delta Displacement
static float pinchDelta = 0;
static float pinchDelta = 0; // Pinch delta displacement
// Detected gesture
// Detected gestures
static int previousGesture = GESTURE_NONE;
static int currentGesture = GESTURE_NONE;
unsigned int enabledGestures = 0; // TODO: Currently not in use...
static unsigned int enabledGestures = 0; // TODO: Currently not in use...
static Vector2 touchPosition;
//----------------------------------------------------------------------------------
// Module specific Functions Declaration
//----------------------------------------------------------------------------------
extern void ResetGestures(void);
extern Vector2 GetRawPosition(void);
static void ProcessMotionEvent(GestureEvent event);
static void InitPinchGesture(Vector2 posA, Vector2 posB);
static float CalculateAngle(Vector2 initialPosition, Vector2 actualPosition, float magnitude);
static float OnPinch();
static void SetDualInput(GestureEvent event);
static float Distance(Vector2 v1, Vector2 v2);
static float DotProduct(Vector2 v1, Vector2 v2);
static float VectorDistance(Vector2 v1, Vector2 v2);
static float VectorDotProduct(Vector2 v1, Vector2 v2);
static double GetCurrentTime();
#if defined(PLATFORM_WEB)
@ -155,15 +144,43 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
// Module Functions Definition
//----------------------------------------------------------------------------------
// Returns tap position XY
extern Vector2 GetRawPosition(void)
// Returns touch position X
int GetTouchX(void)
{
return touchPosition;
return (int)touchPosition.x;
}
// Returns touch position Y
int GetTouchY(void)
{
return (int)touchPosition.y;
}
// Returns touch position XY
// TODO: touch position should be scaled depending on display size and render size
Vector2 GetTouchPosition(void)
{
Vector2 position = touchPosition;
/*
if ((screenWidth > displayWidth) || (screenHeight > displayHeight))
{
// TODO: Seems to work ok but... review!
position.x = position.x*((float)screenWidth / (float)(displayWidth - renderOffsetX)) - renderOffsetX/2;
position.y = position.y*((float)screenHeight / (float)(displayHeight - renderOffsetY)) - renderOffsetY/2;
}
else
{
position.x = position.x*((float)renderWidth / (float)displayWidth) - renderOffsetX/2;
position.y = position.y*((float)renderHeight / (float)displayHeight) - renderOffsetY/2;
}
*/
return position;
}
// Check if a gesture have been detected
bool IsGestureDetected(void)
{
/*
if (currentGesture == GESTURE_DRAG) TraceLog(INFO, "DRAG");
else if (currentGesture == GESTURE_TAP) TraceLog(INFO, "TAP");
else if (currentGesture == GESTURE_DOUBLETAP) TraceLog(INFO, "DOUBLE");
@ -174,6 +191,7 @@ bool IsGestureDetected(void)
else if (currentGesture == GESTURE_SWIPE_DOWN) TraceLog(INFO, "DOWN");
else if (currentGesture == GESTURE_PINCH_IN) TraceLog(INFO, "PINCH IN");
else if (currentGesture == GESTURE_PINCH_OUT) TraceLog(INFO, "PINCH OUT");
*/
if (currentGesture != GESTURE_NONE) return true;
else return false;
@ -228,33 +246,24 @@ float GetGesturePinchAngle(void)
return 0;
}
extern void ResetGestures(void)
{
if (currentGesture == GESTURE_TAP) currentGesture = GESTURE_HOLD;
else if (currentGesture != GESTURE_HOLD) currentGesture = GESTURE_NONE;
}
#if defined(PLATFORM_WEB)
extern void InitWebGestures(void)
// Init gestures system (web)
void InitGesturesSystem(void)
{
/*
emscripten_set_touchstart_callback("#canvas", data, 0, Emscripten_HandleTouch);
emscripten_set_touchend_callback("#canvas", data, 0, Emscripten_HandleTouch);
emscripten_set_touchmove_callback("#canvas", data, 0, Emscripten_HandleTouch);
emscripten_set_touchcancel_callback("#canvas", data, 0, Emscripten_HandleTouch);
*/
// Init gestures system web (emscripten)
// NOTE: Some code examples
//emscripten_set_touchstart_callback(0, NULL, 1, Emscripten_HandleTouch);
//emscripten_set_touchend_callback("#canvas", data, 0, Emscripten_HandleTouch);
emscripten_set_touchstart_callback("#canvas", NULL, 1, EmscriptenInputCallback);
emscripten_set_touchend_callback("#canvas", NULL, 1, EmscriptenInputCallback);
emscripten_set_touchmove_callback("#canvas", NULL, 1, EmscriptenInputCallback);
emscripten_set_touchcancel_callback("#canvas", NULL, 1, EmscriptenInputCallback);
}
#endif
#if defined(PLATFORM_ANDROID)
extern void InitAndroidGestures(struct android_app *app)
#elif defined(PLATFORM_ANDROID)
// Init gestures system (android)
void InitGesturesSystem(struct android_app *app)
{
app->onInputEvent = AndroidInputCallback;
@ -262,6 +271,15 @@ extern void InitAndroidGestures(struct android_app *app)
}
#endif
// Update gestures detected (must be called every frame)
void UpdateGestures(void)
{
// NOTE: Gestures are processed through system callbacks on touch events
if ((previousGesture == GESTURE_TAP) && (currentGesture == GESTURE_TAP)) currentGesture = GESTURE_HOLD;
else if (currentGesture != GESTURE_HOLD) currentGesture = GESTURE_NONE;
}
//----------------------------------------------------------------------------------
// Module specific Functions Definition
//----------------------------------------------------------------------------------
@ -271,13 +289,15 @@ static void ProcessMotionEvent(GestureEvent event)
dragVector = (Vector2){ 0, 0 };
pinchDelta = 0;
previousGesture = currentGesture;
switch (gestureType)
{
case TYPE_MOTIONLESS: // Detect TAP, DOUBLE_TAP and HOLD events
{
if (event.action == DOWN)
{
if (event.pointCount > 1) SetDualInput(event);
if (event.pointCount > 1) InitPinchGesture(event.position[0], event.position[1]);
else
{
// Set the press position
@ -317,7 +337,7 @@ static void ProcessMotionEvent(GestureEvent event)
// Begin dragging
else if (event.action == MOVE)
{
if (event.pointCount > 1) SetDualInput(event);
if (event.pointCount > 1) InitPinchGesture(event.position[0], event.position[1]);
else
{
// Set the drag starting position
@ -354,7 +374,7 @@ static void ProcessMotionEvent(GestureEvent event)
// Update while we are dragging
else if (event.action == MOVE)
{
if (event.pointCount > 1) SetDualInput(event);
if (event.pointCount > 1) InitPinchGesture(event.position[0], event.position[1]);
else
{
lastDragPosition = endDragPosition;
@ -395,8 +415,17 @@ static void ProcessMotionEvent(GestureEvent event)
// If there is no more than two inputs
if (event.pointCount == 2)
{
// Detect pinch delta
pinchDelta = OnPinch();
// Calculate distances
float initialDistance = VectorDistance(firstInitialPinchPosition, secondInitialPinchPosition);
float endDistance = VectorDistance(firstEndPinchPosition, secondEndPinchPosition);
// Calculate Vectors
Vector2 firstTouchVector = { firstEndPinchPosition.x - firstInitialPinchPosition.x, firstEndPinchPosition.y - firstInitialPinchPosition.y };
Vector2 secondTouchVector = { secondEndPinchPosition.x - secondInitialPinchPosition.x, secondEndPinchPosition.y - secondInitialPinchPosition.y };
// Detect the pinch gesture
if (VectorDotProduct(firstTouchVector, secondTouchVector) < -0.5) pinchDelta = initialDistance - endDistance;
else pinchDelta = 0;
// Pinch gesture resolution
if (pinchDelta != 0)
@ -422,36 +451,30 @@ static void ProcessMotionEvent(GestureEvent event)
//--------------------------------------------------------------------
}
static float CalculateAngle(Vector2 initialPosition, Vector2 actualPosition, float magnitude)
static float CalculateAngle(Vector2 initialPosition, Vector2 finalPosition, float magnitude)
{
float angle;
// Calculate arcsinus of the movement ( Our sinus is (actualPosition.y - initialPosition.y) / magnitude)
angle = asin((actualPosition.y - initialPosition.y) / magnitude);
// Calculate arcsinus of the movement
angle = asin((finalPosition.y - initialPosition.y)/magnitude);
angle *= RAD2DEG;
// Calculate angle depending on the sector
if (actualPosition.x - initialPosition.x >= 0)
if ((finalPosition.x - initialPosition.x) >= 0)
{
// Sector 4
if (actualPosition.y - initialPosition.y >= 0)
if ((finalPosition.y - initialPosition.y) >= 0)
{
angle *= -1;
angle += 360;
}
// Sector 1
else
{
angle *= -1;
}
else angle *= -1;
}
else
{
// Sector 3
if (actualPosition.y - initialPosition.y >= 0)
{
angle += 180;
}
if ((finalPosition.y - initialPosition.y) >= 0) angle += 180;
// Sector 2
else
{
@ -463,31 +486,15 @@ static float CalculateAngle(Vector2 initialPosition, Vector2 actualPosition, flo
return angle;
}
static float OnPinch()
{
// Calculate distances
float initialDistance = Distance(firstInitialPinchPosition, secondInitialPinchPosition);
float endDistance = Distance(firstEndPinchPosition, secondEndPinchPosition);
// Calculate Vectors
Vector2 firstTouchVector = { firstEndPinchPosition.x - firstInitialPinchPosition.x, firstEndPinchPosition.y - firstInitialPinchPosition.y };
Vector2 secondTouchVector = { secondEndPinchPosition.x - secondInitialPinchPosition.x, secondEndPinchPosition.y - secondInitialPinchPosition.y };
// Detect the pinch gesture
// Calculate Distances
if (DotProduct(firstTouchVector, secondTouchVector) < -0.5) return initialDistance - endDistance;
else return 0;
}
static void SetDualInput(GestureEvent event)
static void InitPinchGesture(Vector2 posA, Vector2 posB)
{
initialDragPosition = (Vector2){ 0, 0 };
endDragPosition = (Vector2){ 0, 0 };
lastDragPosition = (Vector2){ 0, 0 };
// Initialize positions
firstInitialPinchPosition = event.position[0];
secondInitialPinchPosition = event.position[1];
firstInitialPinchPosition = posA;
secondInitialPinchPosition = posB;
firstEndPinchPosition = firstInitialPinchPosition;
secondEndPinchPosition = secondInitialPinchPosition;
@ -500,7 +507,7 @@ static void SetDualInput(GestureEvent event)
gestureType = TYPE_DUAL_INPUT;
}
static float Distance(Vector2 v1, Vector2 v2)
static float VectorDistance(Vector2 v1, Vector2 v2)
{
float result;
@ -512,7 +519,7 @@ static float Distance(Vector2 v1, Vector2 v2)
return result;
}
static float DotProduct(Vector2 v1, Vector2 v2)
static float VectorDotProduct(Vector2 v1, Vector2 v2)
{
float result;
@ -569,7 +576,7 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
//int32_t key = AKeyEvent_getKeyCode(event);
//int32_t AKeyEvent_getMetaState(event);
int32_t code = AKeyEvent_getKeyCode((const AInputEvent *)event);
//int32_t code = AKeyEvent_getKeyCode((const AInputEvent *)event);
// If we are in active mode, we eat the back button and move into pause mode.
// If we are already in pause mode, we allow the back button to be handled by the OS, which means we'll be shut down.
@ -652,10 +659,4 @@ static EM_BOOL EmscriptenInputCallback(int eventType, const EmscriptenTouchEvent
return 1;
}
#endif
#endif

107
src/gestures.h Normal file
View File

@ -0,0 +1,107 @@
/**********************************************************************************************
*
* raylib Gestures System - Gestures Detection and Usage Functions (Android and HTML5)
*
* Copyright (c) 2015 Marc Palau 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.
*
**********************************************************************************************/
#ifndef GESTURES_H
#define GESTURES_H
#ifndef PI
#define PI 3.14159265358979323846
#endif
#define DEG2RAD (PI / 180.0f)
#define RAD2DEG (180.0f / PI)
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
//...
//----------------------------------------------------------------------------------
// Types and Structures Definition
// NOTE: Below types are required for GESTURES_STANDALONE usage
//----------------------------------------------------------------------------------
#ifndef __cplusplus
// Boolean type
typedef enum { false, true } bool;
#endif
// Vector2 type
typedef struct Vector2 {
float x;
float y;
} Vector2;
// Gestures type
// NOTE: It could be used as flags to enable only some gestures
typedef enum {
GESTURE_NONE = 1,
GESTURE_TAP = 2,
GESTURE_DOUBLETAP = 4,
GESTURE_HOLD = 8,
GESTURE_DRAG = 16,
GESTURE_SWIPE_RIGHT = 32,
GESTURE_SWIPE_LEFT = 64,
GESTURE_SWIPE_UP = 128,
GESTURE_SWIPE_DOWN = 256,
GESTURE_PINCH_IN = 512,
GESTURE_PINCH_OUT = 1024
} Gestures;
#ifdef __cplusplus
extern "C" { // Prevents name mangling of functions
#endif
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
//...
//----------------------------------------------------------------------------------
// Module Functions Declaration
//----------------------------------------------------------------------------------
int GetTouchX(void); // Returns touch position X (relative to screen size)
int GetTouchY(void); // Returns touch position Y (relative to screen size)
Vector2 GetTouchPosition(void); // Returns touch position XY (relative to screen size)
#if defined(PLATFORM_WEB)
void InitGesturesSystem(void); // Init gestures system (web)
#elif defined(PLATFORM_ANDROID)
void InitGesturesSystem(struct android_app *app); // Init gestures system (android)
#endif
void UpdateGestures(void); // Update gestures detected (must be called every frame)
bool IsGestureDetected(void); // Check if a gesture have been detected
int GetGestureType(void); // Get latest detected gesture
void SetGesturesEnabled(unsigned int gestureFlags); // Enable a set of gestures using flags
float GetGestureDragIntensity(void); // Get gesture drag intensity
float GetGestureDragAngle(void); // Get gesture drag angle
Vector2 GetGestureDragVector(void); // Get gesture drag vector
int GetGestureHoldDuration(void); // Get gesture hold time in frames
float GetGesturePinchDelta(void); // Get gesture pinch delta
float GetGesturePinchAngle(void); // Get gesture pinch angle
#ifdef __cplusplus
}
#endif
#endif // GESTURES_H

View File

@ -93,7 +93,7 @@ else
endif
# define all object files required
OBJS = core.o rlgl.o raymath.o shapes.o text.o textures.o models.o audio.o utils.o camera.o gestures.o
OBJS = core.o rlgl.o raymath.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 first target entry in the file,
# in this case, the 'default' target entry is raylib
@ -139,6 +139,10 @@ models.o: models.c
# compile audio module
audio.o: audio.c
$(CC) -c audio.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
# compile stb_vorbis library
stb_vorbis.o: stb_vorbis.c
$(CC) -c stb_vorbis.c -O1 $(INCLUDES) -D$(PLATFORM)
# compile utils module
utils.o: utils.c

View File

@ -4,7 +4,7 @@
*
* Basic functions to draw 3d shapes and load/draw 3d models (.OBJ)
*
* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
* Copyright (c) 2014 Ramon Santamaria (@raysan5)
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
@ -558,22 +558,33 @@ void DrawGizmo(Vector3 position)
Model LoadModel(const char *fileName)
{
VertexData vData;
Model model;
// TODO: Initialize default data for model in case loading fails, maybe a cube?
if (strcmp(GetExtension(fileName),"obj") == 0) vData = LoadOBJ(fileName);
else TraceLog(WARNING, "[%s] Model extension not recognized, it can't be loaded", fileName);
// NOTE: At this point we have all vertex, texcoord, normal data for the model in vData struct
// NOTE: model properties (transform, texture, shader) are initialized inside rlglLoadModel()
Model model = rlglLoadModel(vData); // Upload vertex data to GPU
// Now that vertex data is uploaded to GPU, we can free arrays
// NOTE: We don't need CPU vertex data on OpenGL 3.3 or ES2
if (rlGetVersion() != OPENGL_11)
if (vData.vertexCount == 0)
{
free(vData.vertices);
free(vData.texcoords);
free(vData.normals);
TraceLog(WARNING, "Model could not be loaded");
}
else
{
// NOTE: model properties (transform, texture, shader) are initialized inside rlglLoadModel()
model = rlglLoadModel(vData); // Upload vertex data to GPU
// Now that vertex data is uploaded to GPU, we can free arrays
// NOTE: We don't need CPU vertex data on OpenGL 3.3 or ES2
if (rlGetVersion() != OPENGL_11)
{
free(vData.vertices);
free(vData.texcoords);
free(vData.normals);
}
}
return model;
@ -1105,6 +1116,8 @@ void UnloadModel(Model model)
rlDeleteBuffers(model.mesh.vboId[2]);
rlDeleteVertexArrays(model.mesh.vaoId);
TraceLog(INFO, "Unloaded model data");
}
// Link a texture to a model

View File

@ -36,7 +36,7 @@
* 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 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.
@ -176,7 +176,6 @@
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
#ifndef __cplusplus
// Boolean type
typedef enum { false, true } bool;
@ -354,6 +353,9 @@ typedef enum {
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 {
@ -370,6 +372,9 @@ typedef enum {
GESTURE_PINCH_OUT = 1024
} Gestures;
// 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
@ -383,13 +388,14 @@ extern "C" { // Prevents name mangling of functions
// Window and Graphics Device Functions (Module: core)
//------------------------------------------------------------------------------------
#if defined(PLATFORM_ANDROID)
void InitWindow(int width, int height, struct android_app *state); // Init Android activity
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
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)
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI)
void SetCustomCursor(const char *cursorImage); // Set a custom cursor icon/image
@ -418,6 +424,10 @@ Color Fade(Color color, float alpha); // Color fade-in or
void SetConfigFlags(char flags); // Enable some window configurations
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
Ray GetMouseRay(Vector2 mousePosition, Camera camera); // TODO: Gives the ray trace from mouse position
//------------------------------------------------------------------------------------
@ -441,6 +451,8 @@ void SetShaderMapNormal(Shader *shader, const char *uniformName, Texture2D textu
void SetShaderMapSpecular(Shader *shader, const char *uniformName, Texture2D texture); // Specular map texture shader assignment
void SetShaderMap(Shader *shader, int mapLocation, Texture2D texture, int textureUnit); // TODO: Generic shader map assignment
void SetBlendMode(int mode); // Set blending mode (alpha, additive, multiplied)
//------------------------------------------------------------------------------------
// Input Handling Functions (Module: core)
//------------------------------------------------------------------------------------
@ -461,9 +473,9 @@ Vector2 GetMousePosition(void); // Returns mouse positio
void SetMousePosition(Vector2 position); // Set mouse position XY
int GetMouseWheelMove(void); // Returns mouse wheel movement Y
void ShowCursor(void); // Shows cursor
void HideCursor(void); // Hides cursor
bool IsCursorHidden(void); // Returns true if cursor is not visible
void ShowCursor(void); // Shows cursor
void HideCursor(void); // Hides cursor
bool IsCursorHidden(void); // Returns true if cursor is not visible
#endif
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
@ -476,22 +488,47 @@ bool IsGamepadButtonUp(int gamepad, int button); // Detect if a gamepad b
#endif
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB)
int GetTouchX(void); // Returns touch position X
int GetTouchY(void); // Returns touch position Y
Vector2 GetTouchPosition(void); // Returns touch position XY
//------------------------------------------------------------------------------------
// Gestures and Touch Handling Functions (Module: gestures)
//------------------------------------------------------------------------------------
int GetTouchX(void); // Returns touch position X (relative to screen size)
int GetTouchY(void); // Returns touch position Y (relative to screen size)
Vector2 GetTouchPosition(void); // Returns touch position XY (relative to screen size)
// Gestures System (module: gestures)
bool IsGestureDetected(void);
int GetGestureType(void);
void SetGesturesEnabled(unsigned int gestureFlags);
float GetGestureDragIntensity(void);
float GetGestureDragAngle(void);
Vector2 GetGestureDragVector(void);
int GetGestureHoldDuration(void); // Hold time in frames
float GetGesturePinchDelta(void);
float GetGesturePinchAngle(void);
#if defined(PLATFORM_WEB)
void InitGesturesSystem(void); // Init gestures system (web)
#elif defined(PLATFORM_ANDROID)
void InitGesturesSystem(struct android_app *app); // Init gestures system (android)
#endif
void UpdateGestures(void); // Update gestures detected (must be called every frame)
bool IsGestureDetected(void); // Check if a gesture have been detected
int GetGestureType(void); // Get latest detected gesture
void SetGesturesEnabled(unsigned int gestureFlags); // Enable a set of gestures using flags
float GetGestureDragIntensity(void); // Get gesture drag intensity
float GetGestureDragAngle(void); // Get gesture drag angle
Vector2 GetGestureDragVector(void); // Get gesture drag vector
int GetGestureHoldDuration(void); // Get gesture hold time in frames
float GetGesturePinchDelta(void); // Get gesture pinch delta
float GetGesturePinchAngle(void); // Get gesture pinch angle
#endif
//------------------------------------------------------------------------------------
// Camera System Functions (Module: camera)
//------------------------------------------------------------------------------------
void SetCameraMode(int mode); // Set camera mode (multiple camera modes available)
Camera UpdateCamera(Vector3 *playerPosition); // Update camera and player position (1st person and 3rd person cameras)
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 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 SetCameraMouseSensitivity(float sensitivity); // Set camera mouse sensitivity (1st person and 3rd person cameras)
void SetCameraTarget(Vector3 target); // Set internal camera target
//------------------------------------------------------------------------------------
// Basic Shapes Drawing Functions (Module: shapes)
@ -625,6 +662,7 @@ void SetSoundVolume(Sound sound, float volume); // Set volume fo
void SetSoundPitch(Sound sound, float pitch); // Set pitch for a sound (1.0 is base level)
void PlayMusicStream(char *fileName); // Start music playing (open stream)
void UpdateMusicStream(void); // Updates buffers for music streaming
void StopMusicStream(void); // Stop music playing (close stream)
void PauseMusicStream(void); // Pause music playing
void ResumeMusicStream(void); // Resume playing paused music

View File

@ -7,7 +7,7 @@
* OpenGL 3.3+ - Vertex data is stored in VAOs, call rlglDraw() to render
* OpenGL ES 2 - Same behaviour as OpenGL 3.3+
*
* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
* Copyright (c) 2014 Ramon Santamaria (@raysan5)
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
@ -33,20 +33,21 @@
#include <string.h> // Declares strcmp(), strlen(), strtok()
#if defined(GRAPHICS_API_OPENGL_11)
#ifdef __APPLE__ // OpenGL include for OSX
#ifdef __APPLE__ // OpenGL include for OSX
#include <OpenGL/gl.h>
#else
#include <GL/gl.h> // Basic OpenGL include
#include <GL/gl.h> // Basic OpenGL include
#endif
#endif
#if defined(GRAPHICS_API_OPENGL_33)
#define GLEW_STATIC
#ifdef __APPLE__ // OpenGL include for OSX
#ifdef __APPLE__ // OpenGL include for OSX
#include <OpenGL/gl3.h>
#else
#include <GL/glew.h> // Extensions loading lib
//#include "glad.h" // TODO: Other extensions loading lib? --> REVIEW
#include <GL/glew.h> // GLEW extensions loading lib
//#include "glad.h" // glad extensions loading lib: ERRORS: windows.h
//#include "gl_core_3_3.h" // glLoadGen extension loading lib: ERRORS: windows.h
#endif
#endif
@ -56,6 +57,10 @@
#include <GLES2/gl2ext.h>
#endif
#if defined(RLGL_STANDALONE)
#include <stdarg.h> // Used for functions with variable number of parameters (TraceLog())
#endif
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
@ -177,6 +182,10 @@ typedef struct {
unsigned char a;
} pixel;
#if defined(RLGL_STANDALONE)
typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType;
#endif
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
@ -218,7 +227,6 @@ static bool useTempBuffer = false;
// Flags for supported extensions
static bool vaoSupported = false; // VAO support (OpenGL ES2 could not support VAO extension)
static bool npotSupported = false; // NPOT textures full support
// Compressed textures support flags
//static bool texCompDXTSupported = false; // DDS texture compression support
@ -236,7 +244,8 @@ static bool enabledPostpro = false;
#endif
// Compressed textures support flags
static bool texCompDXTSupported = false; // DDS texture compression 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)
@ -246,6 +255,11 @@ static PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArrays;
//static PFNGLISVERTEXARRAYOESPROC glIsVertexArray; // NOTE: Fails in WebGL, omitted
#endif
// Save screen size data (render size), required for postpro quad
static int screenWidth, screenHeight;
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;
@ -273,6 +287,10 @@ static pixel *GenNextMipmap(pixel *srcData, int srcWidth, int srcHeight);
static char** StringSplit(char *baseString, const char delimiter, int *numExt);
#endif
#if defined(RLGL_STANDALONE)
static void TraceLog(int msgType, const char *text, ...);
#endif
//----------------------------------------------------------------------------------
// Module Functions Definition - Matrix operations
//----------------------------------------------------------------------------------
@ -838,35 +856,69 @@ void rlglInit(void)
//for (int i = 0; i < numComp; i++) TraceLog(INFO, "Supported compressed format: 0x%x", format[i]);
// NOTE: We don't need that much data on screen... right now...
#if defined(GRAPHICS_API_OPENGL_11)
TraceLog(INFO, "OpenGL 1.1 profile initialized");
#endif
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
// Get supported extensions list
GLint numExt;
#if defined(GRAPHICS_API_OPENGL_33)
#define GLEW_EXTENSIONS_LOADER
#if defined(GLEW_EXTENSIONS_LOADER)
// Initialize extensions using GLEW
glewExperimental = 1; // Needed for core profile
GLenum error = glewInit();
if (error != GLEW_OK) TraceLog(ERROR, "Failed to initialize GLEW - Error Code: %s\n", glewGetErrorString(error));
if (glewIsSupported("GL_VERSION_3_3"))
{
TraceLog(INFO, "OpenGL 3.3 Core profile");
TraceLog(INFO, "OpenGL 3.3 Core profile supported");
vaoSupported = true;
npotSupported = true;
}
else TraceLog(ERROR, "OpenGL 3.3 Core profile not supported");
// NOTE: GLEW is a big library that loads ALL extensions, we can use some alternative to load only required ones
// Alternatives: glLoadGen, glad, libepoxy
//if (!gladLoadGL()) TraceLog("ERROR: Failed to initialize glad\n");
// With GLEW we can check if an extension has been loaded in two ways:
// With GLEW, we can check if an extension has been loaded in two ways:
//if (GLEW_ARB_vertex_array_object) { }
//if (glewIsSupported("GL_ARB_vertex_array_object")) { }
// NOTE: GLEW is a big library that loads ALL extensions, we can use some alternative to load only required ones
// Alternatives: glLoadGen, glad, libepoxy
#elif defined(GLAD_EXTENSIONS_LOADER)
// NOTE: glad is generated and contains only required OpenGL version and core extensions
if (!gladLoadGL()) TraceLog(ERROR, "Failed to initialize glad\n");
//if (!gladLoadGLLoader((GLADloadproc) glfwGetProcAddress)) TraceLog(ERROR, "Failed to initialize glad\n");
if (GLAD_GL_VERSION_3_3)
{
TraceLog(INFO, "OpenGL 3.3 Core profile supported");
vaoSupported = true;
npotSupported = true;
}
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
#elif defined(GLLOADGEN_EXTENSIONS_LOADER)
// NOTE: glLoadGen already generates a header with required OpenGL version and core extensions
if (ogl_LoadFunctions() != ogl_LOAD_FAILED)
{
TraceLog(INFO, "OpenGL 3.3 Core profile supported");
vaoSupported = true;
npotSupported = true;
}
else TraceLog(ERROR, "OpenGL 3.3 Core profile not supported");
#endif
// NOTE: We don't need to check again supported extensions but we do (in case GLEW is replaced sometime)
// We get a list of available extensions and we check for some of them (compressed textures)
@ -995,6 +1047,7 @@ void rlglInit(void)
}
// Init postpro system
// NOTE: Uses global variables screenWidth and screenHeight
void rlglInitPostpro(void)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
@ -1003,57 +1056,82 @@ void rlglInitPostpro(void)
glBindTexture(GL_TEXTURE_2D, fboColorTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, GetScreenWidth(), GetScreenHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, screenWidth, screenHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_2D, 0);
// Create the texture that will serve as the depth attachment for the framebuffer.
// Create the renderbuffer that will serve as the depth attachment for the framebuffer.
glGenRenderbuffers(1, &fboDepthTexture);
glBindRenderbuffer(GL_RENDERBUFFER, fboDepthTexture);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, screenWidth, screenHeight);
// NOTE: We can also use a texture for depth buffer (GL_ARB_depth_texture/GL_OES_depth_texture extensions)
// A renderbuffer is simpler than a texture and could offer better performance on embedded devices
/*
glGenTextures(1, &fboDepthTexture);
glBindTexture(GL_TEXTURE_2D, fboDepthTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, GetScreenWidth(), GetScreenHeight(), 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_2D, 0);
*/
// Create the framebuffer object
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
// Attach color texture and depth texture to FBO
// Attach color texture and depth renderbuffer to FBO
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboColorTexture, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, fboDepthTexture, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fboDepthTexture);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) TraceLog(WARNING, "Framebuffer object could not be created...");
else TraceLog(INFO, "[FBO ID %i] Framebuffer object created successfully", fbo);
if (status != GL_FRAMEBUFFER_COMPLETE)
{
TraceLog(WARNING, "Framebuffer object could not be created...");
switch(status)
{
case GL_FRAMEBUFFER_UNSUPPORTED: TraceLog(WARNING, "Framebuffer is unsupported"); break;
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: TraceLog(WARNING, "Framebuffer incomplete attachment"); break;
#if defined(GRAPHICS_API_OPENGL_ES2)
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: TraceLog(WARNING, "Framebuffer incomplete dimensions"); break;
#endif
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: TraceLog(WARNING, "Framebuffer incomplete missing attachment"); break;
default: break;
}
}
else
{
TraceLog(INFO, "[FBO ID %i] Framebuffer object created successfully", fbo);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// Create a simple quad model to render fbo texture
VertexData quadData;
quadData.vertexCount = 6;
float w = GetScreenWidth();
float h = GetScreenHeight();
float quadPositions[6*3] = { w, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, h, 0.0, 0, h, 0.0, w, h, 0.0, w, 0.0, 0.0 };
float quadTexcoords[6*2] = { 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0 };
float quadNormals[6*3] = { 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0 };
unsigned char quadColors[6*4] = { 255 };
quadData.vertices = quadPositions;
quadData.texcoords = quadTexcoords;
quadData.normals = quadNormals;
quadData.colors = quadColors;
postproQuad = rlglLoadModel(quadData);
// NOTE: fboColorTexture id must be assigned to postproQuad model shader
// Create a simple quad model to render fbo texture
VertexData quadData;
quadData.vertexCount = 6;
float w = screenWidth;
float h = screenHeight;
float quadPositions[6*3] = { w, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, h, 0.0, 0, h, 0.0, w, h, 0.0, w, 0.0, 0.0 };
float quadTexcoords[6*2] = { 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0 };
float quadNormals[6*3] = { 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0 };
unsigned char quadColors[6*4] = { 255 };
quadData.vertices = quadPositions;
quadData.texcoords = quadTexcoords;
quadData.normals = quadNormals;
quadData.colors = quadColors;
postproQuad = rlglLoadModel(quadData);
// NOTE: fboColorTexture id must be assigned to postproQuad model shader
}
#endif
}
@ -1116,7 +1194,20 @@ void rlglClose(void)
{
glDeleteFramebuffers(1, &fbo);
UnloadModel(postproQuad);
// Unload postpro quad model data
#if defined(GRAPHICS_API_OPENGL_11)
free(postproQuad.mesh.vertices);
free(postproQuad.mesh.texcoords);
free(postproQuad.mesh.normals);
#endif
rlDeleteBuffers(postproQuad.mesh.vboId[0]);
rlDeleteBuffers(postproQuad.mesh.vboId[1]);
rlDeleteBuffers(postproQuad.mesh.vboId[2]);
rlDeleteVertexArrays(postproQuad.mesh.vaoId);
TraceLog(INFO, "Unloaded postpro quad data");
}
free(draws);
@ -1287,7 +1378,7 @@ void rlglDrawPostpro(void)
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
glBindFramebuffer(GL_FRAMEBUFFER, 0);
rlglDrawModel(postproQuad, (Vector3){0,0,0}, 0.0f, (Vector3){0,0,0}, (Vector3){1.0f, 1.0f, 1.0f}, WHITE, false);
rlglDrawModel(postproQuad, (Vector3){0,0,0}, 0.0f, (Vector3){0,0,0}, (Vector3){1.0f, 1.0f, 1.0f}, (Color){ 255, 255, 255, 255 }, false);
#endif
}
@ -1352,15 +1443,16 @@ void rlglDrawModel(Model model, Vector3 position, float rotationAngle, Vector3 r
// NOTE: Drawing in OpenGL 3.3+, transform is passed to shader
glUniformMatrix4fv(model.shader.projectionLoc, 1, false, GetMatrixVector(projection));
glUniformMatrix4fv(model.shader.modelviewLoc, 1, false, GetMatrixVector(modelviewworld));
// Apply color tinting to model
// NOTE: Just update one uniform on fragment shader
float vColor[4] = { (float)color.r/255, (float)color.g/255, (float)color.b/255, (float)color.a/255 };
glUniform4fv(model.shader.tintColorLoc, 1, vColor);
// Set shader textures (diffuse, normal, specular)
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, model.shader.texDiffuseId);
glUniform1i(model.shader.mapDiffuseLoc, 0);
if (model.shader.texNormalId != 0)
{
@ -1390,14 +1482,21 @@ void rlglDrawModel(Model model, Vector3 position, float rotationAngle, Vector3 r
glEnableVertexAttribArray(model.shader.texcoordLoc);
// Add normals support
glBindBuffer(GL_ARRAY_BUFFER, model.mesh.vboId[2]);
glVertexAttribPointer(model.shader.normalLoc, 3, GL_FLOAT, 0, 0, 0);
glEnableVertexAttribArray(model.shader.normalLoc);
if (model.shader.normalLoc != -1)
{
glBindBuffer(GL_ARRAY_BUFFER, model.mesh.vboId[2]);
glVertexAttribPointer(model.shader.normalLoc, 3, GL_FLOAT, 0, 0, 0);
glEnableVertexAttribArray(model.shader.normalLoc);
}
}
// Draw call!
glDrawArrays(GL_TRIANGLES, 0, model.mesh.vertexCount);
//glDisableVertexAttribArray(model.shader.vertexLoc);
//glDisableVertexAttribArray(model.shader.texcoordLoc);
//if (model.shader.normalLoc != -1) glDisableVertexAttribArray(model.shader.normalLoc);
if (model.shader.texNormalId != 0)
{
glActiveTexture(GL_TEXTURE1);
@ -1426,17 +1525,23 @@ void rlglDrawModel(Model model, Vector3 position, float rotationAngle, Vector3 r
}
// Initialize Graphics Device (OpenGL stuff)
// NOTE: Stores global variables screenWidth and screenHeight
void rlglInitGraphics(int offsetX, int offsetY, int width, int height)
{
// Save screen size data (global vars), required on postpro quad
// NOTE: Size represents render size, it could differ from screen size!
screenWidth = width;
screenHeight = height;
// NOTE: Required! viewport must be recalculated if screen resized!
glViewport(offsetX/2, offsetY/2, width - offsetX, height - offsetY); // Set viewport width and height
// NOTE: Don't confuse glViewport with the transformation matrix
// NOTE: glViewport just defines the area of the context that you will actually draw to.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear used buffers, depth buffer is used for 3D
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set background color (black)
//glClearDepth(1.0f); // Clear depth buffer (default)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear used buffers, depth buffer is used for 3D
glEnable(GL_DEPTH_TEST); // Enables depth testing (required for 3D)
glDepthFunc(GL_LEQUAL); // Type of depth testing to apply
@ -1468,170 +1573,61 @@ void rlglInitGraphics(int offsetX, int offsetY, int width, int height)
// Possible options: GL_SMOOTH (Color interpolation) or GL_FLAT (no interpolation)
#endif
TraceLog(INFO, "OpenGL Graphics initialized successfully");
TraceLog(INFO, "OpenGL graphic device initialized successfully");
}
// Get world coordinates from screen coordinates
// TODO: It doesn't work! It drives me crazy!
// NOTE: Using global variables: screenWidth, screenHeight
Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view)
{
Vector3 result = { 0, 0, 0 }; // Object coordinates
//GLint viewport[4];
//glGetIntegerv(GL_VIEWPORT, viewport);
//glGetIntegerv(GL_VIEWPORT, viewport); // Not available on OpenGL ES 2.0
// Viewport data
/*
int x = 0;
int y = 0;
int width = GetScreenWidth();
int height = GetScreenHeight();
float minDepth = 0.0f;
float maxDepth = 1.0f;
*/
/*
Matrix modelviewprojection = MatrixMultiply(modelview, projection);
int x = 0; // viewport[0]
int y = 0; // viewport[1]
int width = screenWidth; // viewport[2]
int height = screenHeight; // viewport[3]
Matrix modelviewprojection = MatrixMultiply(view, proj);
MatrixInvert(&modelviewprojection);
Vector3 vector;
vector.x = (((source.x - x) / ((float)width)) * 2.0f) - 1.0f;
vector.y = -((((source.y - y) / ((float)height)) * 2.0f) - 1.0f);
vector.z = (source.z - minDepth) / (maxDepth - minDepth);
//float a = (((vector.x * matrix.M14) + (vector.y * matrix.M24)) + (vector.z * matrix.M34)) + matrix.M44;
//float a = (((vector.x * modelviewprojection.m3) + (vector.y * modelviewprojection.m7)) + (vector.z * modelviewprojection.m11)) + modelviewprojection.m15;
VectorTransform(&vector, modelviewprojection);
//if (!MathUtil.IsOne(a)) vector = (vector / a);
//VectorScale(&vector, 1/a);
return vector;
*/
/*
Vector3 worldPoint;
// Transformation matrices
Matrix modelviewprojection = MatrixIdentity();
Quaternion quat;
// Calculation for inverting a matrix, compute projection x modelview
modelviewprojection = MatrixMultiply(proj, view);
MatrixInvert(&modelviewprojection);
// NOTE: Compute unproject using Vector3
// Transformation of normalized coordinates between -1 and 1
quat.x = ((source.x - (float)x)/(float)width*2.0) - 1.0f;
quat.y = ((source.y - (float)y)/(float)height*2.0) - 1.0f;
quat.z = 2.0*source.z - 1.0;
quat.w = 1.0;
result.x = ((source.x - (float)x)/(float)width)*2.0f - 1.0f;
result.y = ((source.y - (float)y)/(float)height)*2.0f - 1.0f;
result.z = source.z*2.0f - 1.0f;
// Objects coordinates
// Object coordinates (multiply vector by matrix)
VectorTransform(&result, modelviewprojection);
*/
// NOTE: Compute unproject using Quaternion (Vector4)
Quaternion quat;
quat.x = ((source.x - (float)x)/(float)width)*2.0f - 1.0f;
quat.y = ((source.y - (float)y)/(float)height)*2.0f - 1.0f;
quat.z = source.z*2.0f - 1.0f;
quat.w = 1.0;
QuaternionTransform(&quat, modelviewprojection);
//if (quat.w == 0.0) return 0;
if (quat.w != 0.0)
{
quat.x /= quat.w;
quat.y /= quat.w;
quat.z /= quat.w;
}
worldPoint.x = quat.x/quat.w;
worldPoint.y = quat.y/quat.w;
worldPoint.z = quat.z/quat.w;
result.x = quat.x;
result.y = quat.y;
result.z = quat.z;
return worldPoint;
*/
/*
Quaternion quat;
Vector3 vec;
quat.x = 2.0f * GetMousePosition().x / (float)width - 1;
quat.y = -(2.0f * GetMousePosition().y / (float)height - 1);
quat.z = 0;
quat.w = 1;
Matrix invView;
MatrixInvert(&view);
Matrix invProj;
MatrixInvert(&proj);
quat.x = invProj.m0 * quat.x + invProj.m4 * quat.y + invProj.m8 * quat.z + invProj.m12 * quat.w;
quat.y = invProj.m1 * quat.x + invProj.m5 * quat.y + invProj.m9 * quat.z + invProj.m13 * quat.w;
quat.z = invProj.m2 * quat.x + invProj.m6 * quat.y + invProj.m10 * quat.z + invProj.m14 * quat.w;
quat.w = invProj.m3 * quat.x + invProj.m7 * quat.y + invProj.m11 * quat.z + invProj.m15 * quat.w;
quat.x = invView.m0 * quat.x + invView.m4 * quat.y + invView.m8 * quat.z + invView.m12 * quat.w;
quat.y = invView.m1 * quat.x + invView.m5 * quat.y + invView.m9 * quat.z + invView.m13 * quat.w;
quat.z = invView.m2 * quat.x + invView.m6 * quat.y + invView.m10 * quat.z + invView.m14 * quat.w;
quat.w = invView.m3 * quat.x + invView.m7 * quat.y + invView.m11 * quat.z + invView.m15 * quat.w;
vec.x /= quat.w;
vec.y /= quat.w;
vec.z /= quat.w;
return vec;
*/
/*
Vector3 worldPoint;
// Transformation matrices
Matrix modelviewprojection;
Quaternion quat;
// Calculation for inverting a matrix, compute projection x modelview
modelviewprojection = MatrixMultiply(view, proj);
// Now compute the inverse of matrix A
MatrixInvert(&modelviewprojection);
// Transformation of normalized coordinates between -1 and 1
quat.x = ((source.x - (float)x)/(float)width*2.0) - 1.0f;
quat.y = ((source.y - (float)y)/(float)height*2.0) - 1.0f;
quat.z = 2.0*source.z - 1.0;
quat.w = 1.0;
// Traspose quaternion and multiply
Quaternion result;
result.x = modelviewprojection.m0 * quad.x + modelviewprojection.m4 * quad.y + modelviewprojection.m8 * quad.z + modelviewprojection.m12 * quad.w;
result.y = modelviewprojection.m1 * quad.x + modelviewprojection.m5 * quad.y + modelviewprojection.m9 * quad.z + modelviewprojection.m13 * quad.w;
result.z = modelviewprojection.m2 * quad.x + modelviewprojection.m6 * quad.y + modelviewprojection.m10 * quad.z + modelviewprojection.m14 * quad.w;
result.w = modelviewprojection.m3 * quad.x + modelviewprojection.m7 * quad.y + modelviewprojection.m11 * quad.z + modelviewprojection.m15 * quad.w;
// Invert
result.w = 1.0f / result.w;
//if (quat.w == 0.0) return 0;
worldPoint.x = quat.x * quat.w;
worldPoint.y = quat.y * quat.w;
worldPoint.z = quat.z * quat.w;
return worldPoint;
*/
/*
// Needed Vectors
Vector3 normalDeviceCoordinates;
Quaternion rayClip;
Quaternion rayEye;
Vector3 rayWorld;
// Getting normal device coordinates
float x = (2.0 * mousePosition.x) / GetScreenWidth() - 1.0;
float y = 1.0 - (2.0 * mousePosition.y) / GetScreenHeight();
float z = 1.0;
normalDeviceCoordinates = (Vector3){ x, y, z };
// Getting clip vector
rayClip = (Quaternion){ normalDeviceCoordinates.x, normalDeviceCoordinates.y, -1, 1 };
Matrix invProjection = projection;
MatrixInvert(&invProjection);
rayEye = MatrixQuaternionMultiply(invProjection, rayClip);
rayEye = (Quaternion){ rayEye.x, rayEye.y, -1, 0 };
Matrix invModelview = modelview;
MatrixInvert(&invModelview);
rayWorld = MatrixVector3Multiply(invModelview, (Vector3){rayEye.x, rayEye.y, rayEye.z} );
VectorNormalize(&rayWorld);
return rayWorld;
*/
return (Vector3){ 0, 0, 0 };
return result;
}
// Convert image data to OpenGL texture (returns OpenGL valid Id)
@ -1780,9 +1776,9 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int textureForma
#endif
// Magnification and minification filters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Filter for pixel-perfect drawing, alternative: GL_LINEAR
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // Filter for pixel-perfect drawing, alternative: GL_LINEAR
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Alternative: GL_LINEAR
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // Alternative: GL_LINEAR
#if defined(GRAPHICS_API_OPENGL_33)
if (mipmapCount > 1)
{
@ -1883,9 +1879,10 @@ Model rlglLoadModel(VertexData mesh)
model.shader.id = 0; // No shader used
#elif defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
model.texture.id = whiteTexture; // Default whiteTexture
model.texture.width = 1; // Default whiteTexture width
model.texture.height = 1; // Default whiteTexture height
model.texture.id = whiteTexture; // Default whiteTexture
model.texture.width = 1; // Default whiteTexture width
model.texture.height = 1; // Default whiteTexture height
model.shader = simpleShader; // Default model shader
GLuint vaoModel = 0; // Vertex Array Objects (VAO)
GLuint vertexBuffer[3]; // Vertex Buffer Objects (VBO)
@ -1903,22 +1900,20 @@ Model rlglLoadModel(VertexData mesh)
// Enable vertex attributes: position
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh.vertexCount, mesh.vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(simpleShader.vertexLoc);
glVertexAttribPointer(simpleShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
glVertexAttribPointer(model.shader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
glEnableVertexAttribArray(model.shader.vertexLoc);
// Enable vertex attributes: texcoords
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*mesh.vertexCount, mesh.texcoords, GL_STATIC_DRAW);
glEnableVertexAttribArray(simpleShader.texcoordLoc);
glVertexAttribPointer(simpleShader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0);
glVertexAttribPointer(model.shader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0);
glEnableVertexAttribArray(model.shader.texcoordLoc);
// Enable vertex attributes: normals
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[2]);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh.vertexCount, mesh.normals, GL_STATIC_DRAW);
glEnableVertexAttribArray(simpleShader.normalLoc);
glVertexAttribPointer(simpleShader.normalLoc, 3, GL_FLOAT, 0, 0, 0);
model.shader = simpleShader; // By default, simple shader will be used
glVertexAttribPointer(model.shader.normalLoc, 3, GL_FLOAT, 0, 0, 0);
glEnableVertexAttribArray(model.shader.normalLoc);
model.mesh.vboId[0] = vertexBuffer[0]; // Vertex position VBO
model.mesh.vboId[1] = vertexBuffer[1]; // Texcoords VBO
@ -1975,6 +1970,8 @@ void *rlglReadTexturePixels(unsigned int textureId, unsigned int format)
#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33)
int width, height;
glBindTexture(GL_TEXTURE_2D, textureId);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
//glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &format);
@ -1995,15 +1992,13 @@ void *rlglReadTexturePixels(unsigned int textureId, unsigned int format)
case UNCOMPRESSED_R8G8B8A8: pixels = (unsigned char *)malloc(size*4); glFormat = GL_RGBA; glType = GL_UNSIGNED_BYTE; break; // 32 bpp
default: TraceLog(WARNING, "Texture format not suported"); break;
}
glBindTexture(GL_TEXTURE_2D, textureId);
// NOTE: Each row written to or read from by OpenGL pixel operations like glGetTexImage are aligned to a 4 byte boundary by default, which may add some padding.
// Use glPixelStorei to modify padding with the GL_[UN]PACK_ALIGNMENT setting.
// GL_PACK_ALIGNMENT affects operations that read from OpenGL memory (glReadPixels, glGetTexImage, etc.)
// GL_UNPACK_ALIGNMENT affects operations that write to OpenGL memory (glTexImage, etc.)
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glGetTexImage(GL_TEXTURE_2D, 0, glFormat, glType, pixels);
glBindTexture(GL_TEXTURE_2D, 0);
@ -2027,39 +2022,54 @@ Shader LoadShader(char *vsFileName, char *fsFileName)
// Shaders loading from external text file
char *vShaderStr = TextFileRead(vsFileName);
char *fShaderStr = TextFileRead(fsFileName);
shader.id = LoadShaderProgram(vShaderStr, fShaderStr);
if (shader.id != 0) TraceLog(INFO, "[SHDR ID %i] Custom shader loaded successfully", shader.id);
else TraceLog(WARNING, "[SHDR ID %i] Custom shader could not be loaded", shader.id);
// Shader strings must be freed
free(vShaderStr);
free(fShaderStr);
// Set shader textures ids (all 0 by default)
shader.texDiffuseId = 0;
shader.texNormalId = 0;
shader.texSpecularId = 0;
if ((vShaderStr != NULL) && (fShaderStr != NULL))
{
shader.id = LoadShaderProgram(vShaderStr, fShaderStr);
// Get handles to GLSL input attibute locations
//-------------------------------------------------------------------
shader.vertexLoc = glGetAttribLocation(shader.id, "vertexPosition");
shader.texcoordLoc = glGetAttribLocation(shader.id, "vertexTexCoord");
shader.normalLoc = glGetAttribLocation(shader.id, "vertexNormal");
// NOTE: custom shader does not use colorLoc
shader.colorLoc = -1;
if (shader.id != 0)
{
TraceLog(INFO, "[SHDR ID %i] Custom shader loaded successfully", shader.id);
// Set shader textures ids (all 0 by default)
shader.texDiffuseId = 0;
shader.texNormalId = 0;
shader.texSpecularId = 0;
// Get handles to GLSL uniform locations (vertex shader)
shader.modelviewLoc = glGetUniformLocation(shader.id, "modelviewMatrix");
shader.projectionLoc = glGetUniformLocation(shader.id, "projectionMatrix");
// Get handles to GLSL input attibute locations
//-------------------------------------------------------------------
shader.vertexLoc = glGetAttribLocation(shader.id, "vertexPosition");
shader.texcoordLoc = glGetAttribLocation(shader.id, "vertexTexCoord");
shader.normalLoc = glGetAttribLocation(shader.id, "vertexNormal");
// NOTE: custom shader does not use colorLoc
shader.colorLoc = -1;
// Get handles to GLSL uniform locations (fragment shader)
shader.tintColorLoc = glGetUniformLocation(shader.id, "tintColor");
shader.mapDiffuseLoc = glGetUniformLocation(shader.id, "texture0");
shader.mapNormalLoc = -1; // It can be set later
shader.mapSpecularLoc = -1; // It can be set later
//--------------------------------------------------------------------
// Get handles to GLSL uniform locations (vertex shader)
shader.modelviewLoc = glGetUniformLocation(shader.id, "modelviewMatrix");
shader.projectionLoc = glGetUniformLocation(shader.id, "projectionMatrix");
// Get handles to GLSL uniform locations (fragment shader)
shader.tintColorLoc = glGetUniformLocation(shader.id, "tintColor");
shader.mapDiffuseLoc = glGetUniformLocation(shader.id, "texture0");
shader.mapNormalLoc = -1; // It can be set later
shader.mapSpecularLoc = -1; // It can be set later
//--------------------------------------------------------------------
}
else
{
TraceLog(WARNING, "Custom shader could not be loaded");
shader = simpleShader;
}
// Shader strings must be freed
free(vShaderStr);
free(fShaderStr);
}
else
{
TraceLog(WARNING, "Custom shader could not be loaded");
shader = simpleShader;
}
#endif
return shader;
@ -2169,6 +2179,8 @@ unsigned int LoadShaderProgram(char *vShaderStr, char *fShaderStr)
void UnloadShader(Shader shader)
{
rlDeleteShader(shader.id);
TraceLog(INFO, "[SHDR ID %i] Unloaded shader program data", shader.id);
}
// Set custom shader to be used on batch draw
@ -2205,6 +2217,7 @@ void SetCustomShader(Shader shader)
}
// Set postprocessing shader
// NOTE: Uses global variables screenWidth and screenHeight
void SetPostproShader(Shader shader)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
@ -2218,8 +2231,8 @@ void SetPostproShader(Shader shader)
Texture2D texture;
texture.id = fboColorTexture;
texture.width = GetScreenWidth();
texture.height = GetScreenHeight();
texture.width = screenWidth;
texture.height = screenHeight;
SetShaderMapDiffuse(&postproQuad.shader, texture);
@ -2236,9 +2249,12 @@ void SetDefaultShader(void)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
SetCustomShader(defaultShader);
SetPostproShader(defaultShader);
enabledPostpro = false;
if (enabledPostpro)
{
SetPostproShader(defaultShader);
enabledPostpro = false;
}
#endif
}
@ -2267,7 +2283,8 @@ void SetModelShader(Model *model, Shader shader)
if (vaoSupported) glBindVertexArray(0); // Unbind VAO
//if (model->texture.id > 0) model->shader.texDiffuseId = model->texture.id;
// NOTE: If SetModelTexture() is called previously, texture is not assigned to new shader
if (model->texture.id > 0) model->shader.texDiffuseId = model->texture.id;
#endif
}
@ -2423,6 +2440,26 @@ void SetShaderMap(Shader *shader, int mapLocation, Texture2D texture, int textur
*/
}
// Set blending mode (alpha, additive, multiplied)
// NOTE: Only 3 blending modes predefined
void SetBlendMode(int mode)
{
if ((blendMode != mode) && (mode < 3))
{
rlglDraw();
switch (mode)
{
case BLEND_ALPHA: glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); break;
case BLEND_ADDITIVE: glBlendFunc(GL_SRC_ALPHA, GL_ONE); break; // Alternative: glBlendFunc(GL_ONE, GL_ONE);
case BLEND_MULTIPLIED: glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); break;
default: break;
}
blendMode = mode;
}
}
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
void PrintProjectionMatrix(void)
{
@ -3026,7 +3063,7 @@ typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType;
// Output a trace log message
// NOTE: Expected msgType: (0)Info, (1)Error, (2)Warning
void TraceLog(int msgType, const char *text, ...)
static void TraceLog(int msgType, const char *text, ...)
{
va_list args;
va_start(args, text);

View File

@ -7,7 +7,7 @@
* OpenGL 3.3+ - Vertex data is stored in VAOs, call rlglDraw() to render
* OpenGL ES 2 - Vertex data is stored in VBOs or VAOs (when available), call rlglDraw() to render
*
* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
* Copyright (c) 2014 Ramon Santamaria (@raysan5)
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
@ -36,6 +36,10 @@
#include "utils.h" // Required for function TraceLog()
#endif
#if defined(RLGL_STANDALONE)
#define RAYMATH_STANDALONE
#endif
#include "raymath.h" // Required for data type Matrix and Matrix functions
// Select desired OpenGL version
@ -89,9 +93,26 @@ typedef enum { RL_LINES, RL_TRIANGLES, RL_QUADS } DrawMode;
typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion;
#ifdef RLGL_STANDALONE
#ifndef __cplusplus
// Boolean type
typedef enum { false, true } bool;
#endif
// byte type
typedef unsigned char byte;
// Color type, RGBA (32bit)
typedef struct Color {
unsigned char r;
unsigned char g;
unsigned char b;
unsigned char a;
} Color;
// Texture formats (support depends on OpenGL version)
typedef enum {
UNCOMPRESSED_GRAYSCALE = 1, // 8 bit per pixel (no alpha)
UNCOMPRESSED_GRAY_ALPHA,
UNCOMPRESSED_R5G6B5, // 16 bpp
UNCOMPRESSED_R8G8B8, // 24 bpp
UNCOMPRESSED_R5G5B5A1, // 16 bpp (1 bit alpha)
@ -106,7 +127,8 @@ typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion;
COMPRESSED_ETC2_EAC_RGBA, // 8 bpp
COMPRESSED_PVRT_RGB, // 4 bpp
COMPRESSED_PVRT_RGBA, // 4 bpp
/*COMPRESSED_ASTC_RGBA_4x4*/ // 8 bpp
COMPRESSED_ASTC_4x4_RGBA, // 8 bpp
COMPRESSED_ASTC_8x8_RGBA // 2 bpp
} TextureFormat;
// VertexData type
@ -123,35 +145,46 @@ typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion;
// Shader type
typedef struct Shader {
unsigned int id; // Shader program id
unsigned int id; // Shader program id
// TODO: This should be Texture2D objects
unsigned int texDiffuseId; // Diffuse texture id
unsigned int texNormalId; // Normal texture id
unsigned int texSpecularId; // Specular texture id
// Variable attributes
unsigned int vertexLoc; // Vertex attribute location point (vertex shader)
unsigned int texcoordLoc; // Texcoord attribute location point (vertex shader)
unsigned int normalLoc; // Normal attribute location point (vertex shader)
unsigned int colorLoc; // Color attibute location point (vertex shader)
int vertexLoc; // Vertex attribute location point (vertex shader)
int texcoordLoc; // Texcoord attribute location point (vertex shader)
int normalLoc; // Normal attribute location point (vertex shader)
int colorLoc; // Color attibute location point (vertex shader)
// Uniforms
unsigned int projectionLoc; // Projection matrix uniform location point (vertex shader)
unsigned int modelviewLoc; // ModeView matrix uniform location point (vertex shader)
unsigned int textureLoc; // Texture uniform location point (fragment shader)
unsigned int tintColorLoc; // Color uniform location point (fragment shader)
int projectionLoc; // Projection matrix uniform location point (vertex shader)
int modelviewLoc; // ModeView matrix uniform location point (vertex shader)
int tintColorLoc; // Color uniform location point (fragment shader)
int mapDiffuseLoc; // Diffuse map texture uniform location point (fragment shader)
int mapNormalLoc; // Normal map texture uniform location point (fragment shader)
int mapSpecularLoc; // Specular map texture uniform location point (fragment shader)
} Shader;
// 3d Model type
typedef struct Model {
VertexData mesh;
Matrix transform;
Texture2D texture;
Shader shader;
} Model;
// Texture2D type
typedef struct Texture2D {
unsigned int id; // Texture id
int width;
int height;
} Texture2D;
// 3d Model type
typedef struct Model {
VertexData mesh;
Matrix transform;
Texture2D texture;
Shader shader;
} Model;
// Color blending modes (pre-defined)
typedef enum { BLEND_ALPHA = 0, BLEND_ADDITIVE, BLEND_MULTIPLIED } BlendMode;
#endif
#ifdef __cplusplus
@ -231,6 +264,31 @@ void PrintProjectionMatrix(void); // DEBUG: Print projection matrix
void PrintModelviewMatrix(void); // DEBUG: Print modelview matrix
#endif
#if defined(RLGL_STANDALONE)
//------------------------------------------------------------------------------------
// Shaders System Functions (Module: rlgl)
// NOTE: This functions are useless when using OpenGL 1.1
//------------------------------------------------------------------------------------
Shader LoadShader(char *vsFileName, char *fsFileName); // Load a custom shader and bind default locations
unsigned int LoadShaderProgram(char *vShaderStr, char *fShaderStr); // Load a custom shader and return program id
void UnloadShader(Shader shader); // Unload a custom shader from memory
void SetPostproShader(Shader shader); // Set fullscreen postproduction shader
void SetCustomShader(Shader shader); // Set custom shader to be used in batch draw
void SetDefaultShader(void); // Set default shader to be used in batch draw
void SetModelShader(Model *model, Shader shader); // Link a shader to a model
bool IsPosproShaderEnabled(void); // Check if postprocessing shader is enabled
int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location
void SetShaderValue(Shader shader, int uniformLoc, float *value, int size); // Set shader uniform value (float)
void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size); // Set shader uniform value (int)
void SetShaderMapDiffuse(Shader *shader, Texture2D texture); // Default diffuse shader map texture assignment
void SetShaderMapNormal(Shader *shader, const char *uniformName, Texture2D texture); // Normal map texture shader assignment
void SetShaderMapSpecular(Shader *shader, const char *uniformName, Texture2D texture); // Specular map texture shader assignment
void SetShaderMap(Shader *shader, int mapLocation, Texture2D texture, int textureUnit); // TODO: Generic shader map assignment
void SetBlendMode(int mode); // Set blending mode (alpha, additive, multiplied)
#endif
#ifdef __cplusplus
}
#endif

View File

@ -4,7 +4,7 @@
*
* Basic functions to draw 2d Shapes and check collisions
*
* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
* Copyright (c) 2014 Ramon Santamaria (@raysan5)
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.

View File

@ -4,7 +4,7 @@
*
* Basic functions to load SpriteFonts and draw Text
*
* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
* Copyright (c) 2014 Ramon Santamaria (@raysan5)
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
@ -216,6 +216,8 @@ extern void UnloadDefaultFont(void)
{
UnloadTexture(defaultFont.texture);
free(defaultFont.charSet);
TraceLog(INFO, "Unloaded default font data");
}
// Get the default font, useful to be used with extended parameters
@ -266,6 +268,8 @@ void UnloadSpriteFont(SpriteFont spriteFont)
{
UnloadTexture(spriteFont.texture);
free(spriteFont.charSet);
TraceLog(INFO, "Unloaded sprite font data");
}
// Draw text (using default font)

View File

@ -8,7 +8,7 @@
* stb_image - Multiple formats image loading (JPEG, PNG, BMP, TGA, PSD, GIF, PIC)
* NOTE: stb_image has been slightly modified, original library: https://github.com/nothings/stb
*
* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
* Copyright (c) 2014 Ramon Santamaria (@raysan5)
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
@ -330,7 +330,6 @@ Texture2D LoadTexture(const char *fileName)
else
{
TraceLog(WARNING, "Texture could not be created");
texture.id = 0;
}
@ -390,12 +389,17 @@ Texture2D LoadTextureFromImage(Image image)
void UnloadImage(Image image)
{
free(image.data);
// NOTE: It becomes anoying every time a texture is loaded
//TraceLog(INFO, "Unloaded image data");
}
// Unload texture from GPU memory
void UnloadTexture(Texture2D texture)
{
rlDeleteTextures(texture.id);
TraceLog(INFO, "[TEX ID %i] Unloaded texture data", texture.id);
}
// Get pixel data from image in the form of Color struct array
@ -486,20 +490,28 @@ Color *GetImageData(Image image)
}
// Get pixel data from GPU texture and return an Image
// NOTE: Compressed texture formats not supported
Image GetTextureData(Texture2D texture)
{
Image image;
image.data = NULL;
image.data = rlglReadTexturePixels(texture.id, texture.format);
if (image.data != NULL)
if (texture.format < 8)
{
image.width = texture.width;
image.height = texture.height;
image.format = texture.format;
image.mipmaps = 1;
image.data = rlglReadTexturePixels(texture.id, texture.format);
if (image.data != NULL)
{
image.width = texture.width;
image.height = texture.height;
image.format = texture.format;
image.mipmaps = 1;
TraceLog(INFO, "Texture pixel data obtained successfully");
}
else TraceLog(WARNING, "Texture pixel data could not be obtained");
}
else TraceLog(WARNING, "Texture pixel data could not be obtained");
else TraceLog(WARNING, "Compressed texture data could not be obtained");
return image;
}
@ -507,136 +519,139 @@ Image GetTextureData(Texture2D texture)
// Convert image data to desired format
void ImageConvertFormat(Image *image, int newFormat)
{
if ((image->format != newFormat) && (image->format < 8) && (newFormat < 8))
if (image->format != newFormat)
{
Color *pixels = GetImageData(*image);
free(image->data);
image->format = newFormat;
int k = 0;
switch (image->format)
if ((image->format < 8) && (newFormat < 8))
{
case UNCOMPRESSED_GRAYSCALE:
{
image->data = (unsigned char *)malloc(image->width*image->height*sizeof(unsigned char));
for (int i = 0; i < image->width*image->height; i++)
{
((unsigned char *)image->data)[i] = (unsigned char)((float)pixels[k].r*0.299f + (float)pixels[k].g*0.587f + (float)pixels[k].b*0.114f);
k++;
}
} break;
case UNCOMPRESSED_GRAY_ALPHA:
{
image->data = (unsigned char *)malloc(image->width*image->height*2*sizeof(unsigned char));
for (int i = 0; i < image->width*image->height*2; i += 2)
{
((unsigned char *)image->data)[i] = (unsigned char)((float)pixels[k].r*0.299f + (float)pixels[k].g*0.587f + (float)pixels[k].b*0.114f);
((unsigned char *)image->data)[i + 1] = pixels[k].a;
k++;
}
Color *pixels = GetImageData(*image);
free(image->data);
image->format = newFormat;
} break;
case UNCOMPRESSED_R5G6B5:
int k = 0;
switch (image->format)
{
image->data = (unsigned short *)malloc(image->width*image->height*sizeof(unsigned short));
unsigned char r;
unsigned char g;
unsigned char b;
for (int i = 0; i < image->width*image->height; i++)
case UNCOMPRESSED_GRAYSCALE:
{
r = (unsigned char)(round((float)pixels[k].r*31/255));
g = (unsigned char)(round((float)pixels[k].g*63/255));
b = (unsigned char)(round((float)pixels[k].b*31/255));
image->data = (unsigned char *)malloc(image->width*image->height*sizeof(unsigned char));
((unsigned short *)image->data)[i] = (unsigned short)r << 11 | (unsigned short)g << 5 | (unsigned short)b;
k++;
}
} break;
case UNCOMPRESSED_R8G8B8:
{
image->data = (unsigned char *)malloc(image->width*image->height*3*sizeof(unsigned char));
for (int i = 0; i < image->width*image->height*3; i += 3)
for (int i = 0; i < image->width*image->height; i++)
{
((unsigned char *)image->data)[i] = (unsigned char)((float)pixels[k].r*0.299f + (float)pixels[k].g*0.587f + (float)pixels[k].b*0.114f);
k++;
}
} break;
case UNCOMPRESSED_GRAY_ALPHA:
{
((unsigned char *)image->data)[i] = pixels[k].r;
((unsigned char *)image->data)[i + 1] = pixels[k].g;
((unsigned char *)image->data)[i + 2] = pixels[k].b;
k++;
}
} break;
case UNCOMPRESSED_R5G5B5A1:
{
image->data = (unsigned short *)malloc(image->width*image->height*sizeof(unsigned short));
unsigned char r;
unsigned char g;
unsigned char b;
unsigned char a = 1;
for (int i = 0; i < image->width*image->height; i++)
{
r = (unsigned char)(round((float)pixels[k].r*31/255));
g = (unsigned char)(round((float)pixels[k].g*31/255));
b = (unsigned char)(round((float)pixels[k].b*31/255));
a = (pixels[k].a > 50) ? 1 : 0;
image->data = (unsigned char *)malloc(image->width*image->height*2*sizeof(unsigned char));
((unsigned short *)image->data)[i] = (unsigned short)r << 11 | (unsigned short)g << 6 | (unsigned short)b << 1| (unsigned short)a;
for (int i = 0; i < image->width*image->height*2; i += 2)
{
((unsigned char *)image->data)[i] = (unsigned char)((float)pixels[k].r*0.299f + (float)pixels[k].g*0.587f + (float)pixels[k].b*0.114f);
((unsigned char *)image->data)[i + 1] = pixels[k].a;
k++;
}
k++;
}
} break;
case UNCOMPRESSED_R4G4B4A4:
{
image->data = (unsigned short *)malloc(image->width*image->height*sizeof(unsigned short));
unsigned char r;
unsigned char g;
unsigned char b;
unsigned char a;
for (int i = 0; i < image->width*image->height; i++)
} break;
case UNCOMPRESSED_R5G6B5:
{
r = (unsigned char)(round((float)pixels[k].r*15/255));
g = (unsigned char)(round((float)pixels[k].g*15/255));
b = (unsigned char)(round((float)pixels[k].b*15/255));
a = (unsigned char)(round((float)pixels[k].a*15/255));
image->data = (unsigned short *)malloc(image->width*image->height*sizeof(unsigned short));
((unsigned short *)image->data)[i] = (unsigned short)r << 12 | (unsigned short)g << 8| (unsigned short)b << 4| (unsigned short)a;
unsigned char r;
unsigned char g;
unsigned char b;
for (int i = 0; i < image->width*image->height; i++)
{
r = (unsigned char)(round((float)pixels[k].r*31/255));
g = (unsigned char)(round((float)pixels[k].g*63/255));
b = (unsigned char)(round((float)pixels[k].b*31/255));
((unsigned short *)image->data)[i] = (unsigned short)r << 11 | (unsigned short)g << 5 | (unsigned short)b;
k++;
}
} break;
case UNCOMPRESSED_R8G8B8A8:
{
image->data = (unsigned char *)malloc(image->width*image->height*4*sizeof(unsigned char));
for (int i = 0; i < image->width*image->height*4; i += 4)
k++;
}
} break;
case UNCOMPRESSED_R8G8B8:
{
((unsigned char *)image->data)[i] = pixels[k].r;
((unsigned char *)image->data)[i + 1] = pixels[k].g;
((unsigned char *)image->data)[i + 2] = pixels[k].b;
((unsigned char *)image->data)[i + 3] = pixels[k].a;
k++;
}
} break;
default: break;
image->data = (unsigned char *)malloc(image->width*image->height*3*sizeof(unsigned char));
for (int i = 0; i < image->width*image->height*3; i += 3)
{
((unsigned char *)image->data)[i] = pixels[k].r;
((unsigned char *)image->data)[i + 1] = pixels[k].g;
((unsigned char *)image->data)[i + 2] = pixels[k].b;
k++;
}
} break;
case UNCOMPRESSED_R5G5B5A1:
{
image->data = (unsigned short *)malloc(image->width*image->height*sizeof(unsigned short));
unsigned char r;
unsigned char g;
unsigned char b;
unsigned char a = 1;
for (int i = 0; i < image->width*image->height; i++)
{
r = (unsigned char)(round((float)pixels[k].r*31/255));
g = (unsigned char)(round((float)pixels[k].g*31/255));
b = (unsigned char)(round((float)pixels[k].b*31/255));
a = (pixels[k].a > 50) ? 1 : 0;
((unsigned short *)image->data)[i] = (unsigned short)r << 11 | (unsigned short)g << 6 | (unsigned short)b << 1| (unsigned short)a;
k++;
}
} break;
case UNCOMPRESSED_R4G4B4A4:
{
image->data = (unsigned short *)malloc(image->width*image->height*sizeof(unsigned short));
unsigned char r;
unsigned char g;
unsigned char b;
unsigned char a;
for (int i = 0; i < image->width*image->height; i++)
{
r = (unsigned char)(round((float)pixels[k].r*15/255));
g = (unsigned char)(round((float)pixels[k].g*15/255));
b = (unsigned char)(round((float)pixels[k].b*15/255));
a = (unsigned char)(round((float)pixels[k].a*15/255));
((unsigned short *)image->data)[i] = (unsigned short)r << 12 | (unsigned short)g << 8| (unsigned short)b << 4| (unsigned short)a;
k++;
}
} break;
case UNCOMPRESSED_R8G8B8A8:
{
image->data = (unsigned char *)malloc(image->width*image->height*4*sizeof(unsigned char));
for (int i = 0; i < image->width*image->height*4; i += 4)
{
((unsigned char *)image->data)[i] = pixels[k].r;
((unsigned char *)image->data)[i + 1] = pixels[k].g;
((unsigned char *)image->data)[i + 2] = pixels[k].b;
((unsigned char *)image->data)[i + 3] = pixels[k].a;
k++;
}
} break;
default: break;
}
free(pixels);
}
free(pixels);
else TraceLog(WARNING, "Image data format is compressed, can not be converted");
}
else TraceLog(WARNING, "Image data format is compressed, can not be converted");
}
@ -644,8 +659,8 @@ void ImageConvertFormat(Image *image, int newFormat)
// NOTE: Requirement on OpenGL ES 2.0 (RPI, HTML5)
void ImageConvertToPOT(Image *image, Color fillColor)
{
// TODO: Review for new image struct
/*
Color *pixels = GetImageData(*image); // Get pixels data
// Just add the required amount of pixels at the right and bottom sides of image...
int potWidth = GetNextPOT(image->width);
int potHeight = GetNextPOT(image->height);
@ -653,29 +668,33 @@ void ImageConvertToPOT(Image *image, Color fillColor)
// Check if POT texture generation is required (if texture is not already POT)
if ((potWidth != image->width) || (potHeight != image->height))
{
Color *imgDataPixelPOT = NULL;
Color *pixelsPOT = NULL;
// Generate POT array from NPOT data
imgDataPixelPOT = (Color *)malloc(potWidth * potHeight * sizeof(Color));
pixelsPOT = (Color *)malloc(potWidth * potHeight * sizeof(Color));
for (int j = 0; j < potHeight; j++)
{
for (int i = 0; i < potWidth; i++)
{
if ((j < image->height) && (i < image->width)) imgDataPixelPOT[j*potWidth + i] = image->data[j*image->width + i];
else imgDataPixelPOT[j*potWidth + i] = fillColor;
if ((j < image->height) && (i < image->width)) pixelsPOT[j*potWidth + i] = pixels[j*image->width + i];
else pixelsPOT[j*potWidth + i] = fillColor;
}
}
TraceLog(WARNING, "Image converted to POT: (%ix%i) -> (%ix%i)", image->width, image->height, potWidth, potHeight);
free(image->pixels);
free(pixels); // Free pixels data
free(image->data); // Free old image data
int format = image->format; // Store image data format to reconvert later
*image = LoadImageEx(pixelsPOT, potWidth, potHeight);
free(pixelsPOT); // Free POT pixels data
image->pixels = imgDataPixelPOT;
image->width = potWidth;
image->height = potHeight;
ImageConvertFormat(image, format); // Reconvert image to previous format
}
*/
}
// Copy an image to a new image

View File

@ -8,7 +8,7 @@
* tinfl - zlib DEFLATE algorithm decompression lib
* stb_image_write - PNG writting functions
*
* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
* Copyright (c) 2014 Ramon Santamaria (@raysan5)
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.