diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 000000000..b96670b17 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,8 @@ +# These are supported funding model platforms + +github: raysan5 +patreon: # raylib +open_collective: # Replace with a single Open Collective username +ko_fi: # raysan +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +custom: # Replace with a single custom sponsorship URL diff --git a/.github/ISSUE_TEMPLATE/custom-issue-template.md b/.github/ISSUE_TEMPLATE/custom-issue-template.md deleted file mode 100644 index d3c475aee..000000000 --- a/.github/ISSUE_TEMPLATE/custom-issue-template.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -name: custom issue template -about: generic template for new issues -title: "[module] Short description of the issue/bug/feature" -labels: '' -assignees: '' - ---- - -Please, before submitting a new issue verify and check: - - - [ ] I tested it on latest raylib version from master branch - - [ ] I checked there is no similar issue already reported - - [ ] My code has no errors or misuse of raylib - -### Issue description - -*Briefly describe the issue you are experiencing (or the feature you want to see added to raylib). Tell us what you were trying to do and what happened instead. Remember, this is not the best place to ask questions. For questions, go to [raylib Discord server](https://discord.gg/VkzNHUE).* - -### Environment - -*Provide your Platform, Operating System, OpenGL version, GPU details where you experienced the issue.* - -### Issue Screenshot - -*If possible, provide a screenshot that illustrates the issue. Usually an image is better than a thousand words.* - -### Code Example - -*Provide minimal reproduction code to test the issue. Please, format the code properly and try to keep it as simple as possible, just focusing on the experienced issue.* diff --git a/.gitignore b/.gitignore index df96338ae..17cad97ac 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,7 @@ Thumbs.db *.cache *.ilk *.log + [Bb]in [Dd]ebug/ [Dd]ebug.win32/ @@ -51,6 +52,8 @@ packages/ *.o *.exe *.a +*.bc +*.so !raylib.rc.o # Ignore all examples files diff --git a/.travis.yml b/.travis.yml index 54cc8bf9a..ea319702e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -120,9 +120,12 @@ before_install: script: - cd build - - if test -n "$WAYLAND"; - then wget https://mirrors.kernel.org/ubuntu/pool/universe/e/extra-cmake-modules/extra-cmake-modules_5.38.0a-0ubuntu1_amd64.deb; - sudo dpkg -i extra-cmake-modules_5.38.0a-0ubuntu1_amd64.deb; + - if test -n "$WAYLAND"; then + wget https://mirrors.edge.kernel.org/ubuntu/pool/universe/e/extra-cmake-modules/extra-cmake-modules_5.44.0-0ubuntu1_amd64.deb; + sudo apt-get clean; + sudo apt-get update; + sudo apt-get install dpkg; + sudo dpkg -i extra-cmake-modules_5.44.0-0ubuntu1_amd64.deb; git clone git://anongit.freedesktop.org/wayland/wayland-protocols; pushd wayland-protocols; git checkout 1.15 && ./autogen.sh --prefix=/usr && make && sudo make install; diff --git a/BINDINGS.md b/BINDINGS.md index b84c9064f..f9c667748 100644 --- a/BINDINGS.md +++ b/BINDINGS.md @@ -4,29 +4,41 @@ Some people ported raylib to other languages in form of bindings or wrappers to - [raylib](https://github.com/raysan5/raylib) : raylib **C/C++** version (default) - [raylib-lua](https://github.com/raysan5/raylib-lua) : raylib **Lua** binding - - [raylib-lua-ffi](https://github.com/raysan5/raylib/issues/693) : raylib **Lua** ffi binding + - [raylib-lua-ffi](https://github.com/raysan5/raylib/issues/693) : raylib **Lua** binding - [raylib-go](https://github.com/gen2brain/raylib-go) : raylib **Go** binding - [raylib-Nim](https://gitlab.com/define-private-public/raylib-Nim) : raylib **Nim** binding - [raylib-cr](https://github.com/AregevDev/raylib-cr) : raylib **Crystal** binding - - [cray](https://gitlab.com/Zatherz/cray) - raylib **Crystal** binding + - [cray](https://gitlab.com/Zatherz/cray) : raylib **Crystal** binding + - [cray](https://github.com/tapgg/cray) : raylib **Crystal** binding - [Graphics::Raylib](https://metacpan.org/pod/Graphics::Raylib) : raylib **Perl** wrapper - [raylib-pascal](https://github.com/drezgames/raylib-pascal) - raylib **Pascal** binding + - [raylib-pas](https://github.com/tazdij/raylib-pas) - raylib **Pascal** binding (including rlgl & raymath) - [Raylib-cs](https://github.com/ChrisDill/Raylib-cs) : raylib **C#** binding - [RaylibSharp](https://github.com/TheLumaio/RaylibSharp) : raylib **C#** binding - [raylib-ruby-ffi](https://github.com/D3nX/raylib-ruby-ffi) : raylib **Ruby** binding - [raylib-rs](https://github.com/deltaphc/raylib-rs) : raylib **Rust** binding - [raylib-py](https://github.com/overdev/raylib-py) : raylib **Python** binding + - [raylib-python-cffi](https://github.com/electronstudio/raylib-python-cffi) : raylib **Python** binding - [raylib-haskell](https://github.com/DevJac/raylib-haskell) : raylib **Haskell** binding - [raylib-java](https://github.com/XoanaIO/raylib-java) : raylib **Java** binding - [raylib-chaiscript](https://github.com/RobLoach/raylib-chaiscript) : raylib **ChaiScript** binding - [node-raylib](https://github.com/RobLoach/node-raylib) : **Node.js** raylib binding - [raylib-odin](https://github.com/kevinw/raylib-odin): **Odin** raylib binding - [raylib-factor](https://github.com/Silverbeard00/raylib-factor): **Factor** raylib binding + - [cl-raylib](https://github.com/longlene/cl-raylib) : raylib **Common Lisp** binding + - [raylib-nim](https://github.com/Skrylar/raylib-nim) : raylib **Nim** binding + - [raylib-php](https://github.com/joseph-montanez/raylib-php) : raylib **PHP 7** binding + - [raylib-php-ffi](https://github.com/oraoto/raylib-php-ffi) : raylib **PHP** binding + - [raylib-d](https://github.com/0xFireball/raylib_d) : raylib **dlang** binding + - [raylib-ruby](https://github.com/a0/raylib-ruby) : raylib **Ruby** wrapper + - [conan-raylib](https://github.com/veyroter/conan-raylib) : raylib **conan** package + - [raylib-squirrel](https://github.com/RobLoach/raylib-squirrel) : raylib **squirrel** binding (probe of concept) + - [raylib-mruby](https://github.com/lihaochen910/raylib-mruby) : raylib **mruby** binding - *[raylib COBOL Usage example](https://github.com/Martinfx/Cobol/tree/master/OpenCobol/Games/raylib)* - *raylib flat-assembler Usage example*: not uploaded yet... Missing some language? Check the [bindings not yet in this list](https://gist.github.com/raysan5/5764cc5b885183f523fce47f098f3d9b#bindings-not-yet-in-the-official-list) or create a new binding! :) - + Usually, raylib bindings follow the convention: `raylib-{language}` Let me know if you're writing a new binding for raylib, I will list it here and I usually diff --git a/CHANGELOG b/CHANGELOG index c133acfda..41b37b30a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,27 +1,32 @@ changelog --------- -Current Release: raylib 2.0.0 (July 2018) +Current Release: raylib 2.5.0 (31 May 2019) ----------------------------------------------- Release: raylib 2.5 (May 2019) ----------------------------------------------- KEY CHANGES: - - New text management API - - Cubemap textures support - - Skeletal model animation support - - New textures drawing: Quad and N-Patch based rectangles - - New drawing shapes available: CircleSector, Ring and RectangleRounded - - VR system redesign to allow custom device parameters and distortion shader + - [core] Redesigned Gamepad mechanism, now common to all platforms and gamepads + - [core] HighDPI monitors support with automatic content scaling + - [rlgl] Complete module redesign to use one single internal buffer + - [rlgl] VR system redesign to allow custom device parameters and distortion shader + - [shapes] New drawing shapes available: CircleSector, Ring and RectangleRounded + - [text] New text management API (multiple functions) + - [text] Full Unicode support (utf8 text) + - [textures] Cubemap textures support + - [textures] Quad and N-Patch drawing + - [models] Skeletal model animation support + - [models] Support multiple meshes per model + - [models] Support glTF model loading Detailed changes: -[build] ... +[build] REVIEWED: Default raylib and examples Makefile [build] REVIEWED: Notepad++ NppExec scripts [build] REVIEWED: VS2015 and VS2017 projects [build] REVIEWED: Android APK build pipeline - [core] Converted most #defined values as enum values -[core] Complete redesign of RPI input system +[core] Complete redesign of RPI input system to use evdev events [core] ADDED: IsWindowResized() - Check if window has been resized [core] ADDED: IsWindowHidden() - Check if window is currently hidden [core] ADDED: UnhideWindow() - Show the window @@ -105,25 +110,44 @@ Detailed changes: [raudio] ADDED: IsAudioStreamPlaying() - Check if audio stream is playing [raudio] ADDED: SetAudioStreamVolume() - Set volume for audio stream (1.0 is max level) [raudio] ADDED: SetAudioStreamPitch() - Set pitch for audio stream (1.0 is base level) +[examples] Complete review of full examples collection, many additions [examples] ADDED: core_custom_logging - Custom trace log system [examples] ADDED: core_input_multitouch - Multitouch input example +[examples] ADDED: core_window_letterbox - Window adapted to screen +[examples] ADDED: core_loading_thread - Data loading in second thread +[examples] REVIEWED: core_input_gamepad - Adapted to new gamepad system [examples] REVIEWED: core_vr_simulator - HMD device parameters and distortion shader should be provided [examples] ADDED: core_window_scale_letterbox - Windows resizing and letterbox content [examples] ADDED: shapes_rectangle_scaling_mouse - Scale a rectangle with mouse -TODO: [examples] ADDED: shapes_draw_circle_sector - Circle sector drawing -TODO: [examples] ADDED: shapes_draw_ring - Ring drawing -TODO: [examples] ADDED: shapes_draw_rectangle_rounded - Rounded rectangle drawing +[examples] ADDED: shapes_draw_circle_sector - Circle sector drawing +[examples] ADDED: shapes_draw_ring - Ring drawing +[examples] ADDED: shapes_draw_rectangle_rounded - Rounded rectangle drawing +[examples] ADDED: shapes_bouncing_ball - Ball bouncing in the screen +[examples] ADDED: shapes_collision_area - Collision detection and drawing +[examples] ADDED: shapes_following_eyes - Some maths on eyes and mouse +[examples] ADDED: shapes_easings_ball_anim - Ball animation +[examples] ADDED: shapes_easings_box_anim - Box animation +[examples] ADDED: shapes_easings_rectangle_array - Rectangles animation +[examples] REVIEWED: shapes_colors_palette - Reviewed color selection and text displaying [examples] ADDED: textures_background_scrolling - Scrolling and parallaz background effect [examples] ADDED: textures_image_npatch - Drawing N-Patch based boxes -TODO: [examples] ADDED: textures_sprite_button -TODO: [examples] ADDED: textures_sprite_explosion +[examples] ADDED: textures_sprite_button - Sprite button with sound +[examples] ADDED: textures_sprite_explosion - Sprite explosion with sound +[examples] ADDED: textures_bunnymark - Benchmarking test [examples] ADDED: text_draw_inside_rectangle - Drawing text inside a delimited rectangle box +[examples] ADDED: text_unicode - Multiple languages text drawing +[examples] ADDED: text_rectangle_bound - Fit text inside a rectangle +[examples] REVIEWED: text_bmfont_ttf - Simplified example [examples] ADDED: models_animation - Animated models loading and animation playing [examples] ADDED: models_obj_viewer - Draw and drop models viewer [examples] ADDED: models_rlgl_solar_system - Solar system simulation using rlgl functionality +[examples] ADDED: models_first_person_maze - 3D maze fps [examples] ADDED: shaders_palette_switch - Switching color palette on shader [examples] ADDED: shaders_raymarching - Raymarching shader [examples] ADDED: shaders_texture_drawing - Texture drawing on GPU +[examples] ADDED: shaders_texture_waves - Texture waves on shader +[examples] ADDED: shaders_julia_set - Julia set fractals +[examples] ADDED: shaders_eratosthenes - Prime number visualization shader [examples] REVIEWED: audio_raw_stream - Mostly rewritten [games] ADDED: GGJ19 game - Cat vs Roomba [*] Updated external libraries to latest version @@ -134,7 +158,7 @@ Release: raylib 2.0 (July 2018) ----------------------------------------------- KEY CHANGES: - Removed external dependencies (GLFW3 and OpenAL) - - Complete redesign of audio module to use mini_al audio library + - Complete redesign of audio module to use miniaudio library - Support AppVeyor and Travis CI (continuous integration) building - Reviewed raymath.h for better consistency and performance (inlining) - Refactor all #define SUPPORT_* into a single config.h diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md deleted file mode 100644 index 4aff53c81..000000000 --- a/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,46 +0,0 @@ -# Contributor Covenant Code of Conduct - -## Our Pledge - -In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. - -## Our Standards - -Examples of behavior that contributes to creating a positive environment include: - -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members - -Examples of unacceptable behavior by participants include: - -* The use of sexualized language or imagery and unwelcome sexual attention or advances -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a professional setting - -## Our Responsibilities - -Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. - -Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. - -## Scope - -This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at ray@raylib.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. - -Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] - -[homepage]: http://contributor-covenant.org -[version]: http://contributor-covenant.org/version/1/4/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index aa9a7678e..739dbcc03 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,6 +2,14 @@ Hello contributors! Welcome to raylib! +Do you enjoy raylib and want to contribute? Nice! You can help with the following points: + +- C programming - Can you write/review/test/improve the code? +- Documentation/Tutorials/Example - Can you write some tutorial/example? +- Web Development - Can you help [with the web](https://github.com/raysan5/raylib.com)? +- Porting to other platforms - Can you port and compile raylib on another systems? +- Testing - Can you find some bugs on raylib? + This document contains a set of guidelines to contribute to the project. These are mostly guidelines, not rules. Use your best judgement, and feel free to propose changes to this document in a pull-request. @@ -89,29 +97,40 @@ contributing (in some way or another) to make the raylib project better. Huge th - [Chris Hemingway](https://github.com/cHemingway) for improving raylib on OSX build system. - [Emanuele Petriglia](https://github.com/LelixSuper) for working on multiple GNU/Linux improvements and developing [TicTacToe](https://github.com/LelixSuper/TicTacToe) raylib game. - [Joshua Reisenauer](https://github.com/kd7tck) for adding audio modules support (XM, MOD) and reviewing audio system. - - [Marcelo Paez](https://github.com/paezao) for his help on OSX to solve High DPI display issue. Thanks Marcelo! - - [Ghassan Al-Mashareqa](https://github.com/ghassanpl) for his amazing contribution with raylib Lua module, I just work over his code to implement [rlua](https://github.com/raysan5/raylib/blob/master/src/rlua.h) - - [Teodor Stoenescu](https://github.com/teodor-stoenescu) for his improvements on OBJ object loading. - - [RDR8](https://github.com/RDR8) for helping with Linux build improvements - - [Saggi Mizrahi](https://github.com/ficoos) for multiple fixes on Linux and audio system - - [Daniel Lemos](https://github.com/xspager) for fixing issues on Linux games building + - [Marcelo Paez](https://github.com/paezao) for helping on OSX High DPI display issue. + - [Ghassan Al-Mashareqa](https://github.com/ghassanpl) for an amazing contribution to raylib Lua module. + - [Teodor Stoenescu](https://github.com/teodor-stoenescu) for improvements on OBJ object loading. + - [RDR8](https://github.com/RDR8) for helping with Linux build improvements. + - [Saggi Mizrahi](https://github.com/ficoos) for multiple fixes on Linux and audio system. + - [Daniel Lemos](https://github.com/xspager) for fixing issues on Linux games building. - [Joel Davis](https://github.com/joeld42) for adding raycast picking utilities and a [great example](https://github.com/raysan5/raylib/blob/master/examples/models/models_mesh_picking.c) - - [Richard Goodwin](https://github.com/AudioMorphology) for adding RPI touchscreen support - - [Milan Nikolic](https://github.com/gen2brain) for adding Android build support with custom standalone toolchain + - [Richard Goodwin](https://github.com/AudioMorphology) for adding RPI touchscreen support. + - [Milan Nikolic](https://github.com/gen2brain) for adding Android build support with custom standalone toolchain. - [Michael Vetter](https://github.com/jubalh) for improvements on build system and his work on Suse Linux package... and multiple fixes! - - [Wilhem Barbier](https://github.com/nounoursheureux) for adding Image generation functions and some fixes - - [Benjamin Summerton](https://github.com/define-private-public) for improving OSX building and his amazing work on CMake build sytem - - [MartinFX](https://github.com/Martinfx) for adding compilation support for FreeBSD OS and derivatives - - [Wilhem Barbier](https://github.com/nounoursheureux) for supporting default shaders on shader loading, if shader not provided - - [Ahmad Fatoum](https://github.com/a3f) for implementing continuus integration support for raylib (Travis and AppVeyor) and greatly improving build system. - - [SamNChiet](https://github.com/SamNChiet) for his work on UWP inputs implementation. - - [David Reid](https://github.com/mackron) for a complete review of audio module to support his amazing mini_al audio library. + - [Wilhem Barbier](https://github.com/nounoursheureux) for adding Image generation functions, shaders work and some fixes. + - [Benjamin Summerton](https://github.com/define-private-public) for improving OSX building and his amazing work on CMake build sytem. + - [MartinFX](https://github.com/Martinfx) for adding compilation support for FreeBSD OS and derivatives. + - [Ahmad Fatoum](https://github.com/a3f) for implementing CI support for raylib (Travis and AppVeyor) and great improvements on build system. + - [SamNChiet](https://github.com/SamNChiet) for a greatly improved UWP input implementation. + - [David Reid](https://github.com/mackron) for a complete review of audio module to support his amazing miniaudio library. - [Kai](https://github.com/questor) for multiple code reviews and improvements. - - [RDR8](https://github.com/RDR8) for his work on Makefiles for Linux - [Max Danielsson](https://github.com/autious) for adding support for orthographic 3d camera projection - - [Lumaio](https://github.com/TheLumaio) for his great work on GBuffers and GetCollisionRayModel() - - [Jonas Daeyaert](https://github.com/culacant) for his amazing work on IQM animated models support - - [Seth Archambault](https://github.com/SethArchambault) for his work on Android Gamepad support (SNES model) + - [Lumaio](https://github.com/TheLumaio) for his great work on GBuffers and GetCollisionRayModel(). + - [Jonas Daeyaert](https://github.com/culacant) for an amazing work on IQM animated models support. + - [Seth Archambault](https://github.com/SethArchambault) for the work on Android Gamepad support (SNES model). - [D3nX](https://github.com/D3nX) for adding Code::Blocks project template. + - [Jak Barnes](https://github.com/Syphonx) for a great work on `rnet`, new raylib network module + - [Vlad Adrian](https://github.com/Demizdor) for an amazing work on Unicode support, new shapes functions and raygui. + - [Reece Mackie](https://github.com/Rover656) for a great work on improving UWP support + - [flashback-fx](flashback-fx) for improving easings library and example + - [Jorge A. Gomes](https://github.com/overdev) for adding nine-patch textures support and example + - [Berni8k](https://github.com/Berni8k) for improving Raspberry Pi input system, using evdev + - [Wilhem Barbier](https://github.com/wbrbr) for implementing glTF loading support and solving several issues + - [Marco Lizza](https://github.com/MarcoLizza) for improving logging system and multiple issues + - [Anata](https://github.com/anatagawa) for creating amazing examples and contributing with them + - [Narice](https://github.com/narice) made easings.h includable as standalone header + - [Eric J.](https://github.com/ProfJski) for shaders_eratosthenes example contribution + - [PompPenguin](https://github.com/PompPenguin) for reviewing 3rd person camera + - [Mohamed Shazan](https://github.com/msmshazan) for adding support for ANGLE graphics backend Please, if I forget someone in this list, excuse me and send a PR! diff --git a/HELPME.md b/HELPME.md deleted file mode 100644 index 5d9026493..000000000 --- a/HELPME.md +++ /dev/null @@ -1,39 +0,0 @@ -help me! --------- - -I’m working hard on raylib but my resources are quite limited. If you enjoy raylib and want to help / contribute in some way, -please, [let me know][raysan5]. - -The following help is highly appreciated: - - - C programming - Can you write / review / test / improve the code? - - Documentation / Tutorials / Example writters - Can you write some tutorial / example? - - Web Development - Can you help with the web? SEO, style, code writting: https://github.com/raysan5/raylib.com - - Porting to Linux, OSX, RaspberryPi, consoles... - Can you compile and test raylib on another systems? - - Testers of current features and multiple systems - Can you find some bug on raylib? - -If you can not help on any of the above points but you still want to contribute in some way... please, consider helping -with a small [donation](http://www.raylib.com/helpme.html) or contributing with [raylib patreon](https://www.patreon.com/raylib). It will really motivate to continue improving this project... - -raylib philosophy ------------------- - - * raylib is a tool to enjoy videogames programming, every single function in raylib should be a tutorial on itself. - * raylib is SIMPLE and EASY-TO-USE, I tried to keep it compact with a small set of functions, if a function is too complex or has not a clear usefulness, better not to include it. - * raylib is open source and free; educators and institutions can use this tool to TEACH videogames programming completely by free. - * raylib is collaborative; contribution of tutorials / code-examples / bugs-solving / code-comments are highly appreciated. - * raylib's license (and its external libs respective licenses) allow using it for commercial products. - -contact -------- - - * Webpage: [http://www.raylib.com](http://www.raylib.com) - * Twitter: [http://www.twitter.com/raysan5](http://www.twitter.com/raysan5) - * Facebook: [http://www.facebook.com/raylibgames](http://www.facebook.com/raylibgames) - * Reddit: [https://www.reddit.com/r/raylib](https://www.reddit.com/r/raylib) - * Twitch: [http://www.twitch.tv/raysan5](http://www.twitch.tv/raysan5) - * Patreon: [https://www.patreon.com/raylib](https://www.patreon.com/raylib) - * Discord: [https://discord.gg/raylib](https://discord.gg/VkzNHUE) - * YouTube: [https://www.youtube.com/channel/raylib](https://www.youtube.com/channel/UC8WIBkhYb5sBNqXO1mZ7WSQ) - -[raysan5]: mailto:ray@raylib.com "Ramon Santamaria - Ray San" diff --git a/HISTORY.md b/HISTORY.md index bbd16c439..7ddc45578 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -3,24 +3,15 @@ history ------- -I've developed videogames for some years and 4 years ago I started teaching videogames development -to young people with artistic profile, most of them had never written a single line of code. +I've developed videogames since 2006 and in 2012 I started teaching videogames development to young people with artistic profile, most of them had never written a single line of code. -I started with C language basis and, after searching for the most simple and easy-to-use library to teach -videogames programming, I found WinBGI; it was great and it worked very well with students, in just a -couple of weeks that people that had never written a single line of code were able to program (and understand) -a simple PONG and some of them even a BREAKOUT! +I started with C language basis and, after searching for the most simple and easy-to-use library to teach videogames programming, I found WinBGI; it was great and it worked very well with students, in just a couple of weeks that people that had never written a single line of code were able to program (and understand) a simple PONG and some of them even a BREAKOUT! -But WinBGI was not the clearer and most organized lib. There were a lot of things I found useless and -confusing and some function names were not clear enough for most of the students; not to mention points -like no transparencies support or no hardware acceleration. +But WinBGI was not the clearer and most organized lib. There were a lot of things I found confusing and some function names were not clear enough for most of the students; not to mention points like no transparencies support or no hardware acceleration. -So, I decided to create my own lib, hardware accelerated, clear function names, quite organized, well structured, -plain C coding and, the most important, primarily intended to LEARN videogames programming. +So, I decided to create my own library, hardware accelerated, clear function names, quite organized, well structured, plain C coding and, the most important, primarily intended to learn videogames programming. -I've coded quite a lot in C# and XNA and I really love it (in fact, my students learn C# after C), -so, I decided to use C# language notation and XNA naming conventions. That way, students can jump from -raylib to XNA, MonoGame or similar libs extremely easily. +Most of my videogames coding experience was in C# and XNA and I really love it (in fact, my students learn C# after C), so, I decided to use C# language notation and XNA naming conventions. That way, students can jump from raylib to XNA, MonoGame or similar libs extremely easily. raylib started as a weekend project and after three months of hard work, raylib 1.0 was published on November 2013. @@ -29,32 +20,24 @@ Enjoy it. notes on raylib 1.1 ------------------- -On April 2014, after 6 month of first raylib release, raylib 1.1 has been released. This new version presents a -complete internal redesign of the library to support OpenGL 1.1, OpenGL 3.3+ and OpenGL ES 2.0. +On April 2014, after 6 month of first raylib release, raylib 1.1 has been released. This new version presents a complete internal redesign of the library to support OpenGL 1.1, OpenGL 3.3+ and OpenGL ES 2.0. -A new module named [rlgl](https://github.com/raysan5/raylib/blob/master/src/rlgl.h) has been added to the library. This new module translates raylib-OpenGL-style -immediate mode functions (i.e. rlVertex3f(), rlBegin(), ...) to different versions of OpenGL (1.1, 3.3+, ES2), selectable by one define. +A new module named [rlgl](https://github.com/raysan5/raylib/blob/master/src/rlgl.h) has been added to the library. This new module translates raylib-OpenGL-style immediate mode functions (i.e. rlVertex3f(), rlBegin(), ...) to different versions of OpenGL (1.1, 3.3+, ES2), selectable by one define. -[rlgl](https://github.com/raysan5/raylib/blob/master/src/rlgl.h) also comes with a second new module named [raymath](https://github.com/raysan5/raylib/blob/master/src/raymath.h), which includes -a bunch of useful functions for 3d-math with vectors, matrices and quaternions. +[rlgl](https://github.com/raysan5/raylib/blob/master/src/rlgl.h) also comes with a second new module named [raymath](https://github.com/raysan5/raylib/blob/master/src/raymath.h), which includes a bunch of useful functions for 3d-math with vectors, matrices and quaternions. -Some other big changes of this new version have been the support for OGG files loading and stream playing, and the -support of DDS texture files (compressed and uncompressed) along with mipmaps support. +Some other big changes of this new version have been the support for OGG files loading and stream playing, and the support of DDS texture files (compressed and uncompressed) along with mipmaps support. Lots of code changes and lot of testing have concluded in this amazing new raylib 1.1. notes on raylib 1.2 ------------------- -On September 2014, after 5 month of raylib 1.1 release, it comes raylib 1.2. Again, this version presents a -complete internal redesign of [core](https://github.com/raysan5/raylib/blob/master/src/core.c) module to support two new platforms: [Android](http://www.android.com/) and [Raspberry Pi](http://www.raspberrypi.org/). +On September 2014, after 5 month of raylib 1.1 release, it comes raylib 1.2. Again, this version presents a complete internal redesign of [core](https://github.com/raysan5/raylib/blob/master/src/core.c) module to support two new platforms: [Android](http://www.android.com/) and [Raspberry Pi](http://www.raspberrypi.org/). -It's been some month of really hard work to accomodate raylib to those new platforms while keeping it easy for the user. -On Android, raylib manages internally the activity cicle, as well as the inputs; on Raspberry Pi, a complete raw input -system has been written from scratch. +It's been some month of really hard work to accomodate raylib to those new platforms while keeping it easy for the users. On Android, raylib manages internally the activity cicle, as well as the inputs; on Raspberry Pi, a complete raw input system has been written from scratch. -A new display initialization system has been created to support multiple resolutions, adding black bars if required; -user only defines desired screen size and it gets properly displayed. +A new display initialization system has been created to support multiple resolutions, adding black bars if required; user only defines desired screen size and it gets properly displayed. Now raylib can easily deploy games to Android devices and Raspberry Pi (console mode). @@ -65,21 +48,17 @@ In December 2014, new raylib 1.2.2 was published with support to compile directl 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 tremendously textures module and also provides some new modules (camera system, gestures system, IMGUI). +On September 2015, after 1 year of raylib 1.2 release, arrives raylib 1.3. This version adds shaders functionality, improves tremendously textures module and also provides some new modules (camera system, gestures system, immediate-mode gui). -Shaders support is the biggest addition to raylib 1.3, with support for easy shaders loading and use. Loaded shaders can be -attached to 3d models or used as fullscreen postrocessing effects. A bunch of postprocessing shaders are also included -in this release, check raylib/shaders folder. +Shaders support is the biggest addition to raylib 1.3, with support for easy shaders loading and use. Loaded shaders can be attached to 3d models or used as fullscreen postrocessing effects. A bunch of postprocessing shaders are also included in this release, check raylib/shaders folder. Textures module has grown to support most of the internal texture formats available in OpenGL (RGB565, RGB888, RGBA5551, RGBA4444, etc.), including compressed texture formats (DXT, ETC1, ETC2, ASTC, PVRT); raylib 1.3 can load .dds, .pkm, .ktx, .astc and .pvr files. -A brand new [camera](https://github.com/raysan5/raylib/blob/master/src/camera.c) module offers to the user multiple preconfigured ready-to-use camera systems (free camera, 1st person, 3rd person). -Camera modes are very easy to use, just check examples: [core_3d_camera_free.c](https://github.com/raysan5/raylib/blob/master/examples/core_3d_camera_free.c) and [core_3d_camera_first_person.c](https://github.com/raysan5/raylib/blob/master/examples/core_3d_camera_first_person.c). + +A brand new [camera](https://github.com/raysan5/raylib/blob/master/src/camera.c) module offers to the user multiple preconfigured ready-to-use camera systems (free camera, 1st person, 3rd person). Camera modes are very easy to use, just check examples: [core_3d_camera_free.c](https://github.com/raysan5/raylib/blob/master/examples/core_3d_camera_free.c) and [core_3d_camera_first_person.c](https://github.com/raysan5/raylib/blob/master/examples/core_3d_camera_first_person.c). New [gestures](https://github.com/raysan5/raylib/blob/master/src/gestures.h) module simplifies gestures detection on Android and HTML5 programs. -[raygui](https://github.com/raysan5/raylib/blob/master/src/raygui.h), the new IMGUI (Immediate Mode GUI) module offers a set of functions to create simple user interfaces, -primary intended for tools development. It's still in experimental state but already fully functional. +[raygui](https://github.com/raysan5/raylib/blob/master/src/raygui.h), the new immediate-mode GUI module offers a set of functions to create simple user interfaces, primary intended for tools development. It's still in experimental state but already fully functional. Most of the examples have been completely rewritten and +10 new examples have been added to show the new raylib features. @@ -88,29 +67,22 @@ Lots of code changes and lot of testing have concluded in this amazing new rayli notes on raylib 1.4 ------------------- -On February 2016, after 4 months of raylib 1.3 release, it comes raylib 1.4. For this new version, -lots of parts of the library have been reviewed, lots of bugs have been solved and some interesting features have been added. +On February 2016, after 4 months of raylib 1.3 release, it comes raylib 1.4. For this new version, lots of parts of the library have been reviewed, lots of bugs have been solved and some interesting features have been added. -First big addition is a set of [Image manipulation functions](https://github.com/raysan5/raylib/blob/master/src/raylib.h#L673) have been added to crop, resize, colorize, flip, dither and even draw image-to-image or text-to-image. -Now a basic image processing can be done before converting the image to texture for usage. +First big addition is a set of [Image manipulation functions](https://github.com/raysan5/raylib/blob/master/src/raylib.h#L673) have been added to crop, resize, colorize, flip, dither and even draw image-to-image or text-to-image. Now a basic image processing can be done before converting the image to texture for usage. -SpriteFonts system has been improved, adding support for AngelCode fonts (.fnt) and TrueType Fonts (using [stb_truetype](https://github.com/nothings/stb/blob/master/stb_truetype.h) helper library). -Now raylib can read standard .fnt font data and also generate at loading a SpriteFont from a TTF file. +SpriteFonts system has been improved, adding support for AngelCode fonts (.fnt) and TrueType Fonts (using [stb_truetype](https://github.com/nothings/stb/blob/master/stb_truetype.h) helper library). Now raylib can read standard .fnt font data and also generate at loading a SpriteFont from a TTF file. -New [physac](https://github.com/raysan5/raylib/blob/master/src/physac.h) physics module for basic 2D physics support. Still in development but already functional. -Module comes with some usage examples for basic jump and level interaction and also force-based physic movements. +New [physac](https://github.com/raysan5/raylib/blob/master/src/physac.h) physics module for basic 2D physics support. Still in development but already functional. Module comes with some usage examples for basic jump and level interaction and also force-based physic movements. [raymath](https://github.com/raysan5/raylib/blob/master/src/raymath.h) module has been reviewed; some bugs have been solved and the module has been converted to a header-only file for easier portability, optionally, functions can also be used as inline. -[gestures](https://github.com/raysan5/raylib/blob/master/src/gestures.c) module has redesigned and simplified, now it can process touch events from any source, including mouse. -This way, gestures system can be used on any platform providing an unified way to work with inputs and allowing the user to create multiplatform games with only one source code. +[gestures](https://github.com/raysan5/raylib/blob/master/src/gestures.c) module has redesigned and simplified, now it can process touch events from any source, including mouse. This way, gestures system can be used on any platform providing an unified way to work with inputs and allowing the user to create multiplatform games with only one source code. -Raspberry Pi input system has been redesigned to better read raw inputs using generic Linux event handlers (keyboard:`stdin`, mouse:`/dev/input/mouse0`, gamepad:`/dev/input/js0`). -Gamepad support has also been added (experimental). +Raspberry Pi input system has been redesigned to better read raw inputs using generic Linux event handlers (keyboard:`stdin`, mouse:`/dev/input/mouse0`, gamepad:`/dev/input/js0`). Gamepad support has also been added (experimental). Other important improvements are the functional raycast system for 3D picking, including some ray collision-detection functions, -and the addition of two simple functions for persistent data storage. Now raylib user can save and load game data in a file (only some platforms supported). -A simple [easings](https://github.com/raysan5/raylib/blob/master/src/easings.h) module has also been added for values animation. +and the addition of two simple functions for persistent data storage. Now raylib user can save and load game data in a file (only some platforms supported). A simple [easings](https://github.com/raysan5/raylib/blob/master/src/easings.h) module has also been added for values animation. Up to 8 new code examples have been added to show the new raylib features and +10 complete game samples have been provided to learn how to create some classic games like Arkanoid, Asteroids, Missile Commander, Snake or Tetris. @@ -180,7 +152,7 @@ Improved library consistency and organization in general. Functions and paramete Some other features: Gamepad support on HTML5, RPI touch screen support, 32bit audio support, frames timing improvements, public log system, rres file format support, automatic GIF recording... -And here it is another version of **raylib, a simple and easy-to-use library to learn videogames programming**. Enjoy it. +And here it is another version of **raylib, a simple and easy-to-use library to enjoy videogames programming**. Enjoy it. notes on raylib 1.8 ------------------- @@ -195,9 +167,9 @@ PBR Materials support, a completely redesigned shaders and material system allow Custom Android APK build pipeline with [simple Makefile](https://github.com/raysan5/raylib/blob/master/templates/simple_game/Makefile). Actually, full code building mechanism based on plain Makefile has been completely reviewed and Android building has been added for sources and also for examples and templates building into final APK package. This way, raylib Android building has been greatly simplified and integrated seamlessly into standard build scripts. -[rlgl](https://github.com/raysan5/raylib/blob/master/src/rlgl.c) module has been completely reviewed and most of the functions renamed for consistency. This way, standalone usage of rlgl is promoted, with a [complete example provided](https://github.com/raysan5/raylib/blob/master/examples/others/rlgl_standalone.c). rlgl offers a pseudo-OpenGL 1.1 immediate-mode programming-style layer, with backends to multiple OpenGL versions. +[rlgl](https://github.com/raysan5/raylib/blob/master/src/rlgl.h) module has been completely reviewed and most of the functions renamed for consistency. This way, standalone usage of rlgl is promoted, with a [complete example provided](https://github.com/raysan5/raylib/blob/master/examples/others/rlgl_standalone.c). rlgl offers a pseudo-OpenGL 1.1 immediate-mode programming-style layer, with backends to multiple OpenGL versions. -[raymath](https://github.com/raysan5/raylib/blob/master/src/rlgl.c) library has been also reviewed to align with other advance math libraries like [GLM](https://github.com/g-truc/glm). Matrix math has been improved and simplified, some new Quaternion functions have been added and Vector3 functions have been renamed all around the library for consistency with new Vector2 functionality. +[raymath](https://github.com/raysan5/raylib/blob/master/src/raymath.h) library has been also reviewed to align with other advance math libraries like [GLM](https://github.com/g-truc/glm). Matrix math has been improved and simplified, some new Quaternion functions have been added and Vector3 functions have been renamed all around the library for consistency with new Vector2 functionality. Additionally, as always, examples and templates have been reviewed to work with new version (some new examples have been added), all external libraries have been updated to latest stable version and latest Notepad++ and MinGW have been configured to work with new raylib. For a full list of changes, just check [CHANGELOG](CHANGELOG). @@ -210,11 +182,11 @@ It's been 9 month since last raylib version was published, a lots of things have In **raylib 2.0** the full API has been carefully reviewed for better consistency, some new functionality has been added and the overall raylib experience has been greatly improved... The key features of new version are: -**Complete removal of external dependencies.** Finally, raylib does not require external libraries to be installed and linked along with raylib, all required libraries are contained and compiled within raylib. Obviously some external libraries are related but only the strictly platform-dependant required ones, that comes installed with the OS. So, raylib becomes a self-contained platform-independent games development library. +**Complete removal of external dependencies.** Finally, raylib does not require external libraries to be installed and linked along with raylib, all required libraries are contained and compiled within raylib. Obviously some external libraries are required but only the strictly platform-dependant ones, the ones that come installed with the OS. So, raylib becomes a self-contained platform-independent games development library. -**Full redesign of audio module to use the amazing mini_al audio library**, along with external dependencies removal, OpenAL library has been replaced by mini_al, this brand new library offers automatic dynamic linking with default OS audio systems. Undoubtly, the perfect low-level companion for raylib audio module! +**Full redesign of audio module to use the amazing miniaudio library**, along with external dependencies removal, OpenAL library has been replaced by [miniaudio](https://github.com/dr-soft/miniaudio), this brand new library offers automatic dynamic linking with default OS audio systems. Undoubtly, the perfect low-level companion for raylib audio module! -**Support for continuous integration building*** through AppVeyor and Travis CI. As a consequence, raylib GitHub develop branch has been completely removed simplyfing the code-base to a single master branch, always stable. Every time a new commit is deployed, library is compiled for **up-to 12 different configurations**, including multiple platforms, 32bit/64bit and multiple compiler options! All those binaries are automatically attached to any new release! +**Support for continuous integration building*** through AppVeyor and Travis CI. Consequently, raylib GitHub develop branch has been removed, simplyfing the code-base to a single master branch, always stable. Every time a new commit is deployed, library is compiled for **up-to 12 different configurations**, including multiple platforms, 32bit/64bit and multiple compiler options! All those binaries are automatically attached to any new release! **More platforms supported and tested**, including BSD family (FreeBSD, openBSD, NetBSD, DragonFly) and Linux-based family platforms (openSUSE, Debian, Ubuntu, Arch, NixOS...). raylib has already been added to some package managers! Oh, and last but not less important, **Android 64bit** is already supported by raylib! @@ -224,9 +196,32 @@ Refactored all raylib configuration #defines into a **centralized `config.h` hea A part of that, lots of new features, like a brand **new font rendering and packaging system** for TTF fonts with **SDF support** (thanks to the amazing STB headers), new functions for **CPU image data manipulation**, new orthographic 3d camera mode, a complete review of `raymath.h` single-file header-only library for better consistency and performance, new examples and way, [way more](https://github.com/raysan5/raylib/blob/master/CHANGELOG). -Probably by now, **raylib 2.0 is the simplest and easiest-to-use library to learn (and understand) videogames programming**... but, undoubtly its development has exceeded any initial objective; raylib has become a simple and easy-to-use trully multiplatform portable standalone media library with thousands of possibilities... and that's just the beginning! +Probably by now, **raylib 2.0 is the simplest and easiest-to-use library to enjoy (and learn) videogames programming**... but, undoubtly its development has exceeded any initial objective; raylib has become a simple and easy-to-use trully multiplatform portable standalone media library with thousands of possibilities... and that's just the beginning! notes on raylib 2.5 ------------------- -SOON. \ No newline at end of file +After almost one years since latest raylib installment, here it is **raylib 2.5**. A lot of work has been put on this new version and consequently I decided to bump versioning several digits. The complete list of changes and additions is humungous, details can be found in the [CHANGELOG](CHANGELOG), and here it is a short recap with the highlight improvements. + +New **window management and filesystem functions** to query monitor information, deal with clipboard, check directory files info and even launch a URL with default system web browser. Experimental **High-DPI monitor support** has also been added through a compile flag. + +**Redesigned Gamepad mechanism**, now generic for all platforms and gamepads, no more specific gamepad configurations. +**Redesigned UWP input system**, now raylib supports UWP seamlessly, previous implementation required a custom input system implemented in user code. + +`rlgl` module has been redesigned to **support a unique buffer for shapes drawing batching**, including LINES, TRIANGLES, QUADS in the same indexed buffer, also added support for multi-buffering if required. Additionally, `rlPushMatrix()`/`rlPopMatrix()` functionality has been reviewed to behave exactly like OpenGL 1.1, `models_rlgl_solar_system` example has been added to illustrate this behaviour. + +**VR simulator** has been reviewed to **allow custom configuration of Head-Mounted-Device parameters and distortion shader**, `core_vr_simulator` has been properly adapted to showcase this new functionality, now the VR simulator is a generic configurable stereo rendering system that allows any VR device simulation with just a few lines of code or even dynamic tweaking of HMD parameters. + +Support for **Unicode text drawing**; now raylib processes UTF8 strings on drawing, supporting Unicode codepoints, allowing rendering mostly any existent language (as long as the font with the glyphs is provided). An amazing example showing this feature has also been added: `text_unicode`. + +Brand **new text management API**, with the addition of multiple functions to deal with string data, including functionality like replace, insert, join, split, append, to uppercase, to lower... Note that most of those functions are intended for text management on rendering, using pre-loaded internal buffers, avoiding new memory allocation that user should free manually. + +Multiple **new shapes and textures drawing functions** to support rings (`DrawRing()`, `DrawRingLines()`), circle sectors (`DrawCircleSector()`, `DrawCircleSectorLines()`), rounded rectangles (`DrawRectangleRounded()`, `DrawRectangleRoundedLines()`) and also n-patch textures (`DrawTextureNPatch()`), detailed examples have been added to illustrate all this new functionality. + +Experimental **cubemap support**, to automatically load multiple cubemap layouts (`LoadTextureCubemap()`). It required some internal `rlgl` redesign to allow cubemap textures. + +**Skeletal animation support for 3d models**, this addition implied a redesign of `Model` data structure to accomodate multiple mesh/multiple materials support and bones information. Multiple models functions have been reviewed and added on this process, also **glTF models loading support** has been added. + +This is a just a brief list with some of the changes of the new **raylib 2.5** but there is way more, about **70 new functions** have been added and several subsystems have been redesigned. More than **30 new examples** have been created to show the new functionalities and better illustrate already available ones. + +It has been a long year of hard work to make raylib a solid technology to develop new products over it. diff --git a/LICENSE.md b/LICENSE.md index b66f47832..70f6a4853 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -27,23 +27,26 @@ applications, and to alter it and redistribute it freely, subject to the followi fonts ------ -The following fonts [provided with raylib](https://github.com/raysan5/raylib/tree/master/examples/text/resources/fonts) are free to use (freeware) and have been designed by the following people: - - * Alpha Beta - Brian Kent (AEnigma) - * Setback - Brian Kent (AEnigma) - * Jupiter Crash - Brian Kent (AEnigma) - * Alagard - Hewett Tsoi - * Romulus - Hewett Tsoi - * Mecha - Captain Falcon - * PixelPlay - Aleksander Shevchuk - * PixAntiqua - Gerhard Großmann + * [Alpha Beta](https://www.dafont.com/es/alpha-beta.font) - Brian Kent (AEnigma) + * [Setback](https://www.dafont.com/es/setback.font) - Brian Kent (AEnigma) + * [Jupiter Crash](https://www.dafont.com/es/jupiter-crash.font) - Brian Kent (AEnigma) + * [Alagard](https://www.dafont.com/es/alagard.font) - Hewett Tsoi + * [Romulus](https://www.dafont.com/es/romulus.font) - Hewett Tsoi + * [Mecha](https://www.dafont.com/es/mecha-cf.font) - Captain Falcon + * [PixelPlay](https://www.dafont.com/es/pixelplay.font) - Aleksander Shevchuk + * [PixAntiqua](https://www.dafont.com/es/pixantiqua.font) - Gerhard Großmann + * [Kaiserzeit Gotisch](https://www.dafont.com/es/kaiserzeit-gotisch.font) - Dieter Steffmann + * [Noto CJK](https://www.google.com/get/noto/help/cjk/) - Google Fonts + * [Anonymous Pro](https://fonts.google.com/specimen/Anonymous+Pro) - Mark Simonson 2d art ------ -[scarfy spritesheet](https://github.com/raysan5/raylib/blob/master/examples/textures/resources/scarfy.png) and [fudesumi image](https://github.com/raysan5/raylib/blob/master/examples/textures/resources/fudesumi.png) have been created by [Eiden Marsal](https://www.artstation.com/artist/marshall_z) and are licensed as [Creative Commons Attribution-NonCommercial 3.0](https://creativecommons.org/licenses/by-nc/3.0/legalcode) + * [Scarfy](https://github.com/raysan5/raylib/blob/master/examples/textures/resources/scarfy.png) - [Eiden Marsal](https://www.artstation.com/artist/marshall_z), licensed as [Creative Commons Attribution-NonCommercial 3.0](https://creativecommons.org/licenses/by-nc/3.0/legalcode) + * [Fudesumi](https://github.com/raysan5/raylib/blob/master/examples/textures/resources/fudesumi.png) - [Eiden Marsal](https://www.artstation.com/artist/marshall_z), licensed as [Creative Commons Attribution-NonCommercial 3.0](https://creativecommons.org/licenses/by-nc/3.0/legalcode) + * [Cyberpunk Street Environment](https://ansimuz.itch.io/cyberpunk-street-environment) - Luis Zuno ([@ansimuz](https://twitter.com/ansimuz)), licensed as [CC-BY-3.0](http://creativecommons.org/licenses/by/3.0/) 3d models --------- -[medieval city 3d models and textures](https://github.com/raysan5/raylib/tree/master/examples/models/resources/medieval) have been created by Alberto Cano and are licensed as [Creative Commons Attribution-NonCommercial 4.0](https://creativecommons.org/licenses/by-nc/4.0/legalcode) + * [Medieval City](https://github.com/raysan5/raylib/tree/master/examples/models/resources/models) - Alberto Cano, licensed as [Creative Commons Attribution-NonCommercial 4.0](https://creativecommons.org/licenses/by-nc/4.0/legalcode) diff --git a/README.md b/README.md index a241bf992..c8a3ac47f 100644 --- a/README.md +++ b/README.md @@ -4,12 +4,11 @@ raylib is highly inspired by Borland BGI graphics lib and by XNA framework and it's specially well suited for prototyping, tooling, graphical applications, embedded systems and education. -*NOTE for ADVENTURERS: raylib is a programming library to enjoy videogames programming; -no fancy interface, no visual helpers, no auto-debugging... just coding in the most -pure spartan-programmers way.* +*NOTE for ADVENTURERS: raylib is a programming library to enjoy videogames programming; no fancy interface, no visual helpers, no auto-debugging... just coding in the most pure spartan-programmers way.* Ready to learn? Jump to [code examples!](http://www.raylib.com/examples.html) + [![Build Status](https://travis-ci.org/raysan5/raylib.svg?branch=master)](https://travis-ci.org/raysan5/raylib) [![https://ci.appveyor.com/api/projects/status/github/raysan5/raylib?svg=true](https://ci.appveyor.com/api/projects/status/github/raysan5/raylib?svg=true)](https://ci.appveyor.com/project/raysan5/raylib) [![Chat on Discord](https://img.shields.io/discord/426912293134270465.svg?logo=discord)](https://discord.gg/VkzNHUE) @@ -23,21 +22,24 @@ features - Written in plain C code (C99) in PascalCase/camelCase notation - Hardware accelerated with OpenGL (**1.1, 2.1, 3.3 or ES 2.0**) - **Unique OpenGL abstraction layer** (usable as standalone module): [rlgl](https://github.com/raysan5/raylib/blob/master/src/rlgl.h) - - Multiple Fonts formats supported (XNA fonts, AngelCode fonts, TTF) + - Multiple **Fonts** formats supported (XNA fonts, AngelCode fonts, TTF) - Outstanding texture formats support, including compressed formats (DXT, ETC, ASTC) - **Full 3D support**, including 3D Shapes, Models, Billboards, Heightmaps and more! - Flexible Materials system, supporting classic maps and **PBR maps** - - Custom shaders, including model and postprocessing shaders. + - **Animated 3D models** supported (skeletal bones animation) + - Shaders support, including model and postprocessing shaders. - **Powerful math module** for Vector, Matrix and Quaternion operations: [raymath](https://github.com/raysan5/raylib/blob/master/src/raymath.h) - Audio loading and playing with streaming support (WAV, OGG, MP3, FLAC, XM, MOD) - **VR stereo rendering** support with configurable HMD device parameters - - Bindings to [multiple code languages](https://github.com/raysan5/raylib/blob/master/BINDINGS.md)! + - Huge examples collection with [+95 code examples](https://www.raylib.com/examples.html)! + - Bindings to [+25 programming languages](https://github.com/raysan5/raylib/blob/master/BINDINGS.md)! -raylib uses on its [core](https://github.com/raysan5/raylib/blob/master/src/core.c) module the outstanding [GLFW3](http://www.glfw.org/) library, embedded inside raylib in the form of [rglfw](https://github.com/raysan5/raylib/blob/master/src/rglfw.c) module, to avoid external dependencies. -raylib uses on its [raudio](https://github.com/raysan5/raylib/blob/master/src/raudio.c) module, the amazing [miniaudio](https://github.com/dr-soft/miniaudio) audio library to support multiple platforms and multiple audio backends. +raylib uses on its [core](https://github.com/raysan5/raylib/blob/master/src/core.c) module the outstanding [GLFW3](http://www.glfw.org/) library, embedded in the form of [rglfw](https://github.com/raysan5/raylib/blob/master/src/rglfw.c) module, to avoid external dependencies. -raylib uses internally multiple single-file header-only libraries to support multiple fileformats loading and saving, all those libraries are embedded with raylib and available in [src/external](https://github.com/raysan5/raylib/tree/master/src/external) directory. Check [raylib Wiki](https://github.com/raysan5/raylib/wiki/raylib-dependencies) for a detailed list. +raylib uses on its [raudio](https://github.com/raysan5/raylib/blob/master/src/raudio.c) module, the amazing [miniaudio](https://github.com/dr-soft/miniaudio) library to support multiple platforms and multiple audio backends. + +raylib uses internally multiple single-file header-only libraries to support different fileformats loading and saving, all those libraries are embedded with raylib and available in [src/external](https://github.com/raysan5/raylib/tree/master/src/external) directory. Check [raylib Wiki](https://github.com/raysan5/raylib/wiki/raylib-dependencies) for a detailed list. *On Android platform, `native_app_glue module` module (provided by Android NDK) and native Android libraries are used to manage window/context, inputs and activity life cycle.* @@ -63,9 +65,8 @@ contact * Webpage: [http://www.raylib.com](http://www.raylib.com) * Discord: [https://discord.gg/raylib](https://discord.gg/VkzNHUE) * Twitter: [http://www.twitter.com/raysan5](http://www.twitter.com/raysan5) - * Facebook: [http://www.facebook.com/raylibgames](http://www.facebook.com/raylibgames) - * Reddit: [https://www.reddit.com/r/raylib](https://www.reddit.com/r/raylib) * Twitch: [http://www.twitch.tv/raysan5](http://www.twitch.tv/raysan5) + * Reddit: [https://www.reddit.com/r/raylib](https://www.reddit.com/r/raylib) * Patreon: [https://www.patreon.com/raylib](https://www.patreon.com/raylib) * YouTube: [https://www.youtube.com/channel/raylib](https://www.youtube.com/channel/UC8WIBkhYb5sBNqXO1mZ7WSQ) diff --git a/ROADMAP.md b/ROADMAP.md index ae4706076..6f6feb4db 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -1,16 +1,25 @@ roadmap ------- -Current version of raylib is complete and functional but there is still a lot of room for improvement. -Here it is a wish-list with features and ideas to improve the library. +Here it is a wish-list with features and ideas to improve the library. Note that features listed here are quite high-level and could be long term additions for the library. Current version of raylib is complete and functional but there is a lot of room for improvement. -Note that [raylib source code](https://github.com/raysan5/raylib/tree/master/src) has some *TODO* marks around code with pending things to review and improve. Check [GitHub Issues](https://github.com/raysan5/raylib/issues) for further details! +[raylib source code](https://github.com/raysan5/raylib/tree/master/src) has some *TODO* marks around code with pending things to review and improve. +Also, check [GitHub Issues](https://github.com/raysan5/raylib/issues) for further details! **raylib 2.x** - - [ ] rnet: Network module - - [ ] Support Vulkan API (GRAPHICS_API_VULKAN) + - [ ] rnet: raylib network module + - [ ] rres: raylib resource packer + - [ ] rlvk: raylib Vulkan API support (GRAPHICS_API_VULKAN) - [ ] Basic CPU/GPU stats sytem (memory, draws, time...) - - [x] Support Animated models (2.5) + +**raylib 2.5** + - [x] Support Animated models + - [x] Support glTF models file format + - [x] Unicode support on text drawing + +**raylib 2.0** + - [x] Removed external dependencies (GLFW3 and OpenAL) + - [x] Support TCC compiler (32bit and 64bit) **raylib 1.8** - [x] Improved Materials system with PBR support @@ -47,7 +56,3 @@ Note that [raylib source code](https://github.com/raysan5/raylib/tree/master/src - [x] Redesign gestures module to be multiplatform - [x] Module raymath as header-only and functions inline - [x] Add Easings module (easings.h) - -Any feature missing? Do you have a request? [Let me know!][raysan5] - -[raysan5]: mailto:ray@raylib.com "Ramon Santamaria - Ray San" diff --git a/SPONSORS.md b/SPONSORS.md new file mode 100644 index 000000000..978c7ea2f --- /dev/null +++ b/SPONSORS.md @@ -0,0 +1,13 @@ +The following people has contributed with a generous donation to raylib project. + +## 🥇 Gold Contributors + +... + +## 🥈 Silver Contributors + +... + +## 🥉 Bronce Contributors + +... diff --git a/cmake/raylib-config.cmake b/cmake/raylib-config.cmake index 5ad55b169..b5358740f 100644 --- a/cmake/raylib-config.cmake +++ b/cmake/raylib-config.cmake @@ -12,12 +12,14 @@ # raylib_DEFINITIONS - Compiler switches required for using raylib set(XPREFIX PC_RAYLIB) + +find_package(PkgConfig QUIET) +pkg_check_modules(${XPREFIX} QUIET raylib) + if (raylib_USE_STATIC_LIBS) set(XPREFIX ${XPREFIX}_STATIC) endif() -find_package(PkgConfig QUIET) -pkg_check_modules(${XPREFIX} QUIET raylib) set(raylib_DEFINITIONS ${${XPREFIX}_CFLAGS}) find_path(raylib_INCLUDE_DIR @@ -25,17 +27,16 @@ find_path(raylib_INCLUDE_DIR HINTS ${${XPREFIX}_INCLUDE_DIRS} ) +set(RAYLIB_NAMES raylib) + if (raylib_USE_STATIC_LIBS) - find_library(raylib_LIBRARY - NAMES raylib_static - HINTS ${${XPREFIX}_LIBRARY_DIRS} - ) -else () - find_library(raylib_LIBRARY - NAMES raylib - HINTS ${${XPREFIX}_LIBRARY_DIRS} - ) -endif () + set(RAYLIB_NAMES libraylib.a raylib.lib ${RAYLIB_NAMES}) +endif() + +find_library(raylib_LIBRARY + NAMES ${RAYLIB_NAMES} + HINTS ${${XPREFIX}_LIBRARY_DIRS} +) set(raylib_LIBRARIES ${raylib_LIBRARY}) set(raylib_LIBRARY_DIRS ${${XPREFIX}_LIBRARY_DIRS}) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index fd8a02551..2879320c4 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -24,7 +24,7 @@ foreach(example_dir ${example_dirs}) list(APPEND example_resources ${resources}) endforeach() -if (NOT CMAKE_SYSTEM STRLESS "Darwin-18.0.0") +if (APPLE AND NOT CMAKE_SYSTEM STRLESS "Darwin-18.0.0") add_definitions(-DGL_SILENCE_DEPRECATION) MESSAGE(AUTHOR_WARNING "OpenGL is deprecated starting with macOS 10.14 (Mojave)!") endif() @@ -67,6 +67,8 @@ if(${PLATFORM} MATCHES "Android") list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/models/models_heightmap.c) list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/models/models_billboard.c) list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/models/models_rlgl_solar_system.c) + list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/models/models_rlgl_full_solar_system.c) + list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/models/models_solar_system.c) list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/models/models_obj_viewer.c) list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/models/models_animation.c) list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/models/models_first_person_maze.c) @@ -76,15 +78,19 @@ if(${PLATFORM} MATCHES "Android") list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/shaders/shaders_postprocessing.c) list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/shaders/shaders_raymarching.c) list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/shaders/shaders_palette_switch.c) + list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/shaders/shaders_basic_lighting.c) elseif(${PLATFORM} MATCHES "Web") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Os -s USE_GLFW=3 -s ASSERTIONS=1 -s WASM=1 -s EMTERPRETIFY=1 -s EMTERPRETIFY_ASYNC=1") # Since WASM is used, ALLOW_MEMORY_GROWTH has no extra overheads set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -s ALLOW_MEMORY_GROWTH=1 --no-heap-copy") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --shell-file ${CMAKE_SOURCE_DIR}/templates/web_shell/shell.html") - + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --shell-file ${CMAKE_SOURCE_DIR}/src/shell.html") set(OUTPUT_EXT ".html") + # Remove the -rdynamic flag because otherwise emscripten + # does not generate HTML+JS+WASM files, only a non-working + # and fat HTML + string(REPLACE "-rdynamic" "" CMAKE_SHARED_LIBRARY_LINK_C_FLAGS ${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS}) endif() include_directories(BEFORE SYSTEM others/external/include) diff --git a/examples/Makefile b/examples/Makefile index 083afd92b..c71758497 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -26,7 +26,7 @@ # Define required raylib variables PROJECT_NAME ?= raylib_examples RAYLIB_VERSION ?= 2.5.0 -RAYLIB_API_VERSION ?= 1 +RAYLIB_API_VERSION ?= 2 RAYLIB_PATH ?= .. # Define default options @@ -52,7 +52,7 @@ RAYLIB_H_INSTALL_PATH ?= $(DESTDIR)/include RAYLIB_LIBTYPE ?= STATIC # Build mode for project: DEBUG or RELEASE -RAYLIB_BUILD_MODE ?= RELEASE +BUILD_MODE ?= RELEASE # Use external GLFW library instead of rglfw module # TODO: Review usage on Linux. Target version of choice. Switch on -lglfw or -lglfw3 @@ -62,8 +62,6 @@ USE_EXTERNAL_GLFW ?= FALSE # by default it uses X11 windowing system USE_WAYLAND_DISPLAY ?= FALSE -# NOTE: On PLATFORM_WEB OpenAL Soft backend is used by default (check raylib/src/Makefile) - # Determine PLATFORM_OS in case PLATFORM_DESKTOP selected ifeq ($(PLATFORM),PLATFORM_DESKTOP) # No uname.exe on MinGW!, but OS=Windows_NT on Windows! @@ -117,9 +115,9 @@ endif ifeq ($(PLATFORM),PLATFORM_WEB) # Emscripten required variables - EMSDK_PATH = C:/emsdk - EMSCRIPTEN_VERSION = 1.38.30 - CLANG_VERSION = e1.38.30_64bit + EMSDK_PATH ?= C:/emsdk + EMSCRIPTEN_VERSION ?= 1.38.31 + CLANG_VERSION = e$(EMSCRIPTEN_VERSION)_64bit PYTHON_VERSION = 2.7.13.1_64bit\python-2.7.13.amd64 NODE_VERSION = 8.9.1_64bit export PATH = $(EMSDK_PATH);$(EMSDK_PATH)\clang\$(CLANG_VERSION);$(EMSDK_PATH)\node\$(NODE_VERSION)\bin;$(EMSDK_PATH)\python\$(PYTHON_VERSION);$(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION);C:\raylib\MinGW\bin:$$(PATH) @@ -127,27 +125,8 @@ ifeq ($(PLATFORM),PLATFORM_WEB) endif # Define raylib release directory for compiled library. -# RAYLIB_RELEASE_PATH points to provided binaries or your freshly built version. -ifeq ($(PLATFORM),PLATFORM_DESKTOP) - ifeq ($(PLATFORM_OS),WINDOWS) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/src - endif - ifeq ($(PLATFORM_OS),LINUX) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/src - endif - ifeq ($(PLATFORM_OS),OSX) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/src - endif - ifeq ($(PLATFORM_OS),BSD) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/src - endif -endif -ifeq ($(PLATFORM),PLATFORM_RPI) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/src -endif -ifeq ($(PLATFORM),PLATFORM_WEB) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/src -endif +# RAYLIB_RELEASE_PATH points to provided binaries or your freshly built version +RAYLIB_RELEASE_PATH ?= $(RAYLIB_PATH)/src # EXAMPLE_RUNTIME_PATH embeds a custom runtime location of libraylib.so or other desired libraries # into each example binary compiled with RAYLIB_LIBTYPE=SHARED. It defaults to RAYLIB_RELEASE_PATH @@ -155,7 +134,7 @@ endif # without formal installation from ../src/Makefile. It aids portability and is useful if you have # multiple versions of raylib, have raylib installed to a non-standard location, or want to # bundle libraylib.so with your game. Change it to your liking. -# Note: If, at runtime, there is a libraylib.so at both EXAMPLE_RUNTIME_PATH and RAYLIB_INSTALL_PATH, +# NOTE: If, at runtime, there is a libraylib.so at both EXAMPLE_RUNTIME_PATH and RAYLIB_INSTALL_PATH, # The library at EXAMPLE_RUNTIME_PATH, if present, will take precedence over RAYLIB_INSTALL_PATH, # Implemented for LINUX below with CFLAGS += -Wl,-rpath,$(EXAMPLE_RUNTIME_PATH) # To see the result, run readelf -d core/core_basic_window; looking at the RPATH or RUNPATH attribute. @@ -185,8 +164,9 @@ ifeq ($(PLATFORM),PLATFORM_RPI) endif endif ifeq ($(PLATFORM),PLATFORM_WEB) - # WARNING: To compile to HTML5, code must be redesigned to use emscripten.h and emscripten_set_main_loop() # HTML5 emscripten compiler + # WARNING: To compile to HTML5, code must be redesigned + # to use emscripten.h and emscripten_set_main_loop() CC = emcc endif @@ -201,14 +181,21 @@ endif # Define compiler flags: # -O1 defines optimization level -# -g enable debugging +# -g include debug information on compilation # -s strip unnecessary data from build # -Wall turns on most, but not all, compiler warnings # -std=c99 defines C language mode (standard C from 1999 revision) # -std=gnu99 defines C language mode (GNU C from 1999 revision) # -Wno-missing-braces ignore invalid warning (GCC bug 53119) # -D_DEFAULT_SOURCE use with -std=c99 on Linux and PLATFORM_WEB, required for timespec -CFLAGS += -O1 -s -Wall -std=c99 -D_DEFAULT_SOURCE -Wno-missing-braces +CFLAGS += -Wall -std=c99 -D_DEFAULT_SOURCE -Wno-missing-braces + +ifeq ($(BUILD_MODE),DEBUG) + CFLAGS += -g +endif +ifeq ($(RAYLIB_BUILD_MODE),RELEASE) + CFLAGS += -O1 -s +endif # Additional flags for compiler (if desired) #CFLAGS += -Wextra -Wmissing-prototypes -Wstrict-prototypes @@ -216,19 +203,15 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),WINDOWS) # resource file contains windows executable icon and properties # -Wl,--subsystem,windows hides the console window - CFLAGS += $(RAYLIB_PATH)/raylib.rc.data -Wl,--subsystem,windows + CFLAGS += $(RAYLIB_PATH)/src/raylib.rc.data -Wl,--subsystem,windows endif ifeq ($(PLATFORM_OS),LINUX) - ifeq ($(RAYLIB_BUILD_MODE),DEBUG) - CFLAGS += -g - #CC = clang - endif ifeq ($(RAYLIB_LIBTYPE),STATIC) - CFLAGS += -D_DEFAULT_SOURCE + CFLAGS += -D_DEFAULT_SOURCE endif ifeq ($(RAYLIB_LIBTYPE),SHARED) - # Explicitly enable runtime link to libraylib.so - CFLAGS += -Wl,-rpath,$(EXAMPLE_RUNTIME_PATH) + # Explicitly enable runtime link to libraylib.so + CFLAGS += -Wl,-rpath,$(EXAMPLE_RUNTIME_PATH) endif endif endif @@ -238,34 +221,35 @@ endif ifeq ($(PLATFORM),PLATFORM_WEB) # -Os # size optimization # -O2 # optimization level 2, if used, also set --memory-init-file 0 - # --memory-init-file 0 # to avoid an external memory initialization code file (.mem) # -s USE_GLFW=3 # Use glfw3 library (context/input management) - # -s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing + # -s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing -> WARNING: Audio buffers could FAIL! # -s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB) # -s USE_PTHREADS=1 # multithreading support - # -s WASM=1 # support Web Assembly (https://github.com/kripken/emscripten/wiki/WebAssembly) + # -s WASM=0 # disable Web Assembly, emitted by default # -s EMTERPRETIFY=1 # enable emscripten code interpreter (very slow) # -s EMTERPRETIFY_ASYNC=1 # support synchronous loops by emterpreter # -s FORCE_FILESYSTEM=1 # force filesystem to load/save files data + # -s ASSERTIONS=1 # enable runtime checks for common memory allocation errors (-O1 and above turn it off) # --profiling # include information for code profiling + # --memory-init-file 0 # to avoid an external memory initialization code file (.mem) # --preload-file resources # specify a resources folder for data compilation - CFLAGS += -Os -s USE_GLFW=3 -s ASSERTIONS=2 -s WASM=1 -s FORCE_FILESYSTEM=1 - # -s EMTERPRETIFY=1 -s EMTERPRETIFY_ASYNC=1 --preload-file audio/resources@resources - + CFLAGS += -Os -s USE_GLFW=3 -s FORCE_FILESYSTEM=1 -s EMTERPRETIFY=1 -s EMTERPRETIFY_ASYNC=1 --preload-file $(dir $<)resources@resources + ifeq ($(BUILD_MODE), DEBUG) + CFLAGS += -s ASSERTIONS=1 --profiling + endif # NOTE: Simple raylib examples are compiled to be interpreter by emterpreter, that way, # we can compile same code for ALL platforms with no change required, but, working on bigger # projects, code needs to be refactored to avoid a blocking while() loop, moving Update and Draw # logic to a self contained function: UpdateDrawFrame(), check core_basic_window_web.c for reference. # Define a custom shell .html and output extension - CFLAGS += --shell-file $(RAYLIB_PATH)\templates\web_shell\shell.html + CFLAGS += --shell-file $(RAYLIB_PATH)/src/shell.html EXT = .html endif -# Define include paths for required headers. -# Precedence: immediately local, raysan5 provided sources +# Define include paths for required headers # NOTE: Several external required libraries (stb and others) -INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/release/include -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external +INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external # Define additional directories containing required header files ifeq ($(PLATFORM),PLATFORM_RPI) @@ -287,7 +271,6 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) endif # Define library paths containing required libs. -# Precedence: immediately local, then raysan5 provided libs LDFLAGS = -L. -L$(RAYLIB_RELEASE_PATH) -L$(RAYLIB_PATH)/src ifeq ($(PLATFORM),PLATFORM_DESKTOP) @@ -298,7 +281,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),LINUX) # Reset everything. # Precedence: immediately local, installed version, raysan5 provided libs - LDFLAGS = -L. -L$(RAYLIB_INSTALL_PATH) -L$(RAYLIB_RELEASE_PATH) -L$(RAYLIB_PATH)/src + LDFLAGS = -L. -L$(RAYLIB_INSTALL_PATH) -L$(RAYLIB_RELEASE_PATH) endif endif @@ -320,10 +303,12 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) # Libraries for Debian GNU/Linux desktop compiling # NOTE: Required packages: libegl1-mesa-dev LDLIBS = -lraylib -lGL -lm -lpthread -ldl -lrt + # On X11 requires also below libraries LDLIBS += -lX11 # NOTE: It seems additional libraries are not required any more, latest GLFW just dlopen them #LDLIBS += -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor + # On Wayland windowing system, additional libraries requires ifeq ($(USE_WAYLAND_DISPLAY),TRUE) LDLIBS += -lwayland-client -lwayland-cursor -lwayland-egl -lxkbcommon @@ -342,6 +327,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) # Libraries for FreeBSD, OpenBSD, NetBSD, DragonFly desktop compiling # NOTE: Required packages: mesa-libs LDLIBS = -lraylib -lGL -lpthread -lm + # On XWindow requires also below libraries LDLIBS += -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor endif @@ -360,78 +346,109 @@ ifeq ($(PLATFORM),PLATFORM_WEB) LDLIBS = $(RAYLIB_RELEASE_PATH)/libraylib.bc endif -# Define all object files required +# Define all source files required EXAMPLES = \ core/core_basic_window \ core/core_input_keys \ core/core_input_mouse \ - core/core_mouse_wheel \ + core/core_input_mouse_wheel \ core/core_input_gamepad \ - core/core_random_values \ - core/core_color_select \ - core/core_drop_files \ - core/core_storage_values \ - core/core_gestures_detection \ - core/core_3d_mode \ - core/core_3d_picking \ + core/core_input_multitouch \ + core/core_input_gestures \ + core/core_2d_camera \ + core/core_3d_camera_mode \ core/core_3d_camera_free \ core/core_3d_camera_first_person \ - core/core_2d_camera \ + core/core_3d_picking \ core/core_world_screen \ + core/core_custom_logging \ + core/core_window_letterbox \ + core/core_drop_files \ + core/core_random_values \ + core/core_scissor_test \ + core/core_storage_values \ core/core_vr_simulator \ - core/core_input_multitouch \ - shapes/shapes_logo_raylib \ + core/core_loading_thread \ shapes/shapes_basic_shapes \ + shapes/shapes_bouncing_ball \ shapes/shapes_colors_palette \ + shapes/shapes_logo_raylib \ shapes/shapes_logo_raylib_anim \ + shapes/shapes_rectangle_scaling \ shapes/shapes_lines_bezier \ + shapes/shapes_collision_area \ + shapes/shapes_following_eyes \ + shapes/shapes_easings_ball_anim \ + shapes/shapes_easings_box_anim \ + shapes/shapes_easings_rectangle_array \ + shapes/shapes_draw_ring \ + shapes/shapes_draw_circle_sector \ + shapes/shapes_draw_rectangle_rounded \ + text/text_raylib_fonts \ + text/text_font_spritefont \ + text/text_font_loading \ + text/text_font_filters \ + text/text_font_sdf \ + text/text_format_text \ + text/text_input_box \ + text/text_writing_anim \ + text/text_rectangle_bounds \ + text/text_unicode \ textures/textures_logo_raylib \ - textures/textures_image_loading \ + textures/textures_mouse_painting \ textures/textures_rectangle \ textures/textures_srcrec_dstrec \ + textures/textures_image_drawing \ + textures/textures_image_generation \ + textures/textures_image_loading \ + textures/textures_image_processing \ + textures/textures_image_text \ textures/textures_to_image \ textures/textures_raw_data \ textures/textures_particles_blending \ - textures/textures_image_processing \ - textures/textures_image_drawing \ - textures/textures_image_generation \ - textures/textures_image_text \ - text/text_sprite_fonts \ - text/text_bmfont_ttf \ - text/text_raylib_fonts \ - text/text_format_text \ - text/text_writing_anim \ - text/text_ttf_loading \ - text/text_bmfont_unordered \ - text/text_input_box \ - text/text_font_sdf \ - models/models_geometric_shapes \ - models/models_box_collisions \ + textures/textures_npatch_drawing \ + textures/textures_background_scrolling \ + textures/textures_sprite_button \ + textures/textures_sprite_explosion \ + textures/textures_bunnymark \ + models/models_animation \ models/models_billboard \ - models/models_obj_loading \ - models/models_obj_viewer \ - models/models_heightmap \ + models/models_box_collisions \ models/models_cubicmap \ - models/models_mesh_picking \ - models/models_mesh_generation \ + models/models_first_person_maze \ + models/models_geometric_shapes \ models/models_material_pbr \ + models/models_mesh_generation \ + models/models_mesh_picking \ + models/models_loading \ + models/models_orthographic_projection \ + models/models_rlgl_solar_system \ models/models_skybox \ models/models_yaw_pitch_roll \ + models/models_heightmap \ shaders/shaders_model_shader \ shaders/shaders_shapes_textures \ shaders/shaders_custom_uniform \ shaders/shaders_postprocessing \ - shaders/shaders_raymarching \ shaders/shaders_palette_switch \ - audio/audio_sound_loading \ - audio/audio_music_stream \ + shaders/shaders_raymarching \ + shaders/shaders_texture_drawing \ + shaders/shaders_texture_waves \ + shaders/shaders_julia_set \ + shaders/shaders_eratosthenes \ + shaders/shaders_basic_lighting \ + shaders/shaders_fog \ + shaders/shaders_simple_mask \ audio/audio_module_playing \ + audio/audio_music_stream \ audio/audio_raw_stream \ + audio/audio_sound_loading \ + audio/audio_multichannel_sound \ physac/physics_demo \ physac/physics_friction \ physac/physics_movement \ physac/physics_restitution \ - physac/physics_shatter \ + physac/physics_shatter CURRENT_MAKEFILE = $(lastword $(MAKEFILE_LIST)) @@ -448,12 +465,6 @@ else $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) endif -# fix dylib install path name for each executable (MAC) -fix_dylib: -ifeq ($(PLATFORM_OS),OSX) - find . -type f -perm +ugo+x -print0 | xargs -t -0 -R 1 -I file install_name_tool -change libglfw.3.0.dylib ../external/glfw3/lib/osx/libglfw.3.0.dylib file -endif - # Clean everything clean: ifeq ($(PLATFORM),PLATFORM_DESKTOP) @@ -461,7 +472,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) del *.o *.exe /s endif ifeq ($(PLATFORM_OS),LINUX) - find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -fv + find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable|x-pie-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -fv endif ifeq ($(PLATFORM_OS),OSX) find . -type f -perm +ugo+x -delete @@ -476,3 +487,4 @@ ifeq ($(PLATFORM),PLATFORM_WEB) del *.o *.html *.js endif @echo Cleaning done + diff --git a/examples/Makefile.Android b/examples/Makefile.Android index b6c68417f..29d437b1b 100644 --- a/examples/Makefile.Android +++ b/examples/Makefile.Android @@ -22,33 +22,33 @@ #************************************************************************************************** # Define required raylib variables -PLATFORM ?= PLATFORM_ANDROID -RAYLIB_PATH ?= ..\.. +PLATFORM ?= PLATFORM_ANDROID +RAYLIB_PATH ?= ..\.. # Define Android architecture (armeabi-v7a, arm64-v8a, x86, x86-64) and API version -ANDROID_ARCH ?= ARM -ANDROID_API_VERSION = 21 +ANDROID_ARCH ?= ARM +ANDROID_API_VERSION = 21 ifeq ($(ANDROID_ARCH),ARM) - ANDROID_ARCH_NAME = armeabi-v7a + ANDROID_ARCH_NAME = armeabi-v7a endif ifeq ($(ANDROID_ARCH),ARM64) - ANDROID_ARCH_NAME = arm64-v8a + ANDROID_ARCH_NAME = arm64-v8a endif # Required path variables # NOTE: JAVA_HOME must be set to JDK -JAVA_HOME ?= C:/JavaJDK -ANDROID_HOME = C:/android-sdk -ANDROID_TOOLCHAIN = C:/android_toolchain_$(ANDROID_ARCH)_API$(ANDROID_API_VERSION) -ANDROID_BUILD_TOOLS = $(ANDROID_HOME)/build-tools/28.0.1 -ANDROID_PLATFORM_TOOLS = $(ANDROID_HOME)/platform-tools +JAVA_HOME ?= C:/JavaJDK +ANDROID_HOME = C:/android-sdk +ANDROID_TOOLCHAIN = C:/android_toolchain_$(ANDROID_ARCH)_API$(ANDROID_API_VERSION) +ANDROID_BUILD_TOOLS = $(ANDROID_HOME)/build-tools/28.0.1 +ANDROID_PLATFORM_TOOLS = $(ANDROID_HOME)/platform-tools # Android project configuration variables -PROJECT_NAME ?= raylib_game -PROJECT_LIBRARY_NAME ?= main -PROJECT_BUILD_PATH ?= android.$(PROJECT_NAME) +PROJECT_NAME ?= raylib_game +PROJECT_LIBRARY_NAME ?= main +PROJECT_BUILD_PATH ?= android.$(PROJECT_NAME) PROJECT_RESOURCES_PATH ?= resources -PROJECT_SOURCE_FILES ?= raylib_game.c +PROJECT_SOURCE_FILES ?= raylib_game.c # Some source files are placed in directories, when compiling to some # output directory other than source, that directory must pre-exist. @@ -70,7 +70,9 @@ APP_KEYSTORE_PASS ?= raylib # Library type used for raylib: STATIC (.a) or SHARED (.so/.dll) RAYLIB_LIBTYPE ?= STATIC -RAYLIB_LIB_PATH = $(RAYLIB_PATH)\release\libs\android\$(ANDROID_ARCH_NAME) + +# Library path for libraylib.a/libraylib.so +RAYLIB_LIB_PATH = $(RAYLIB_PATH)\src # Shared libs must be added to APK if required # NOTE: Generated NativeLoader.java automatically load those libraries @@ -104,7 +106,7 @@ CFLAGS += -Wall -Wa,--noexecstack -Wformat -Werror=format-security -no-canonical CFLAGS += -DANDROID -DPLATFORM_ANDROID -D__ANDROID_API__=$(ANDROID_API_VERSION) # Paths containing required header files -INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/release/include -I$(RAYLIB_PATH)/src/external/android/native_app_glue +INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external/android/native_app_glue # Linker options LDFLAGS = -Wl,-soname,lib$(PROJECT_LIBRARY_NAME).so -Wl,--exclude-libs,libatomic.a diff --git a/examples/audio/audio_module_playing.c b/examples/audio/audio_module_playing.c index 54bfa3d21..557fcb092 100644 --- a/examples/audio/audio_module_playing.c +++ b/examples/audio/audio_module_playing.c @@ -2,8 +2,6 @@ * * raylib [audio] example - Module playing (streaming) * -* NOTE: This example requires OpenAL Soft library installed -* * This example has been created using raylib 1.5 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * @@ -23,38 +21,38 @@ typedef struct { Color color; } CircleWave; -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; SetConfigFlags(FLAG_MSAA_4X_HINT); // NOTE: Try to enable MSAA 4X - + InitWindow(screenWidth, screenHeight, "raylib [audio] example - module playing (streaming)"); InitAudioDevice(); // Initialize audio device - + Color colors[14] = { ORANGE, RED, GOLD, LIME, BLUE, VIOLET, BROWN, LIGHTGRAY, PINK, YELLOW, GREEN, SKYBLUE, PURPLE, BEIGE }; - + // Creates ome circles for visual effect - CircleWave circles[MAX_CIRCLES]; - + CircleWave circles[MAX_CIRCLES] = { 0 }; + for (int i = MAX_CIRCLES - 1; i >= 0; i--) { circles[i].alpha = 0.0f; circles[i].radius = GetRandomValue(10, 40); circles[i].position.x = GetRandomValue(circles[i].radius, screenWidth - circles[i].radius); circles[i].position.y = GetRandomValue(circles[i].radius, screenHeight - circles[i].radius); - circles[i].speed = (float)GetRandomValue(1, 100)/20000.0f; + circles[i].speed = (float)GetRandomValue(1, 100)/2000.0f; circles[i].color = colors[GetRandomValue(0, 13)]; } - Music xm = LoadMusicStream("resources/chiptun1.mod"); - - PlayMusicStream(xm); + Music music = LoadMusicStream("resources/mini1111.xm"); + + PlayMusicStream(music); float timePlayed = 0.0f; bool pause = false; @@ -67,35 +65,35 @@ int main() { // Update //---------------------------------------------------------------------------------- - UpdateMusicStream(xm); // Update music buffer with new stream data - + UpdateMusicStream(music); // Update music buffer with new stream data + // Restart music playing (stop and play) - if (IsKeyPressed(KEY_SPACE)) + if (IsKeyPressed(KEY_SPACE)) { - StopMusicStream(xm); - PlayMusicStream(xm); + StopMusicStream(music); + PlayMusicStream(music); } - - // Pause/Resume music playing + + // Pause/Resume music playing if (IsKeyPressed(KEY_P)) { pause = !pause; - - if (pause) PauseMusicStream(xm); - else ResumeMusicStream(xm); + + if (pause) PauseMusicStream(music); + else ResumeMusicStream(music); } - + // Get timePlayed scaled to bar dimensions - timePlayed = GetMusicTimePlayed(xm)/GetMusicTimeLength(xm)*(screenWidth - 40); - + timePlayed = GetMusicTimePlayed(music)/GetMusicTimeLength(music)*(screenWidth - 40); + // Color circles animation for (int i = MAX_CIRCLES - 1; (i >= 0) && !pause; i--) { circles[i].alpha += circles[i].speed; circles[i].radius += circles[i].speed*10.0f; - + if (circles[i].alpha > 1.0f) circles[i].speed *= -1; - + if (circles[i].alpha <= 0.0f) { circles[i].alpha = 0.0f; @@ -103,7 +101,7 @@ int main() circles[i].position.x = GetRandomValue(circles[i].radius, screenWidth - circles[i].radius); circles[i].position.y = GetRandomValue(circles[i].radius, screenHeight - circles[i].radius); circles[i].color = colors[GetRandomValue(0, 13)]; - circles[i].speed = (float)GetRandomValue(1, 100)/20000.0f; + circles[i].speed = (float)GetRandomValue(1, 100)/2000.0f; } } //---------------------------------------------------------------------------------- @@ -113,12 +111,12 @@ int main() BeginDrawing(); ClearBackground(RAYWHITE); - + for (int i = MAX_CIRCLES - 1; i >= 0; i--) { DrawCircleV(circles[i].position, circles[i].radius, Fade(circles[i].color, circles[i].alpha)); } - + // Draw time bar DrawRectangle(20, screenHeight - 20 - 12, screenWidth - 40, 12, LIGHTGRAY); DrawRectangle(20, screenHeight - 20 - 12, (int)timePlayed, 12, MAROON); @@ -130,8 +128,8 @@ int main() // De-Initialization //-------------------------------------------------------------------------------------- - UnloadMusicStream(xm); // Unload music stream buffers from RAM - + UnloadMusicStream(music); // Unload music stream buffers from RAM + CloseAudioDevice(); // Close audio device (music streaming is automatically stopped) CloseWindow(); // Close window and OpenGL context diff --git a/examples/audio/audio_multichannel_sound.c b/examples/audio/audio_multichannel_sound.c new file mode 100644 index 000000000..f3db341e0 --- /dev/null +++ b/examples/audio/audio_multichannel_sound.c @@ -0,0 +1,100 @@ +/******************************************************************************************* +* +* raylib [audio] example - Multichannel sound playing +* +* This example has been created using raylib 2.6 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Example contributed by Chris Camacho (@codifies) and reviewed by Ramon Santamaria (@raysan5) +* +* Copyright (c) 2019 Chris Camacho (@codifies) and Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [audio] example - Multichannel sound playing"); + + InitAudioDevice(); // Initialize audio device + + Sound fxWav = LoadSound("resources/sound.wav"); // Load WAV audio file + Sound fxOgg = LoadSound("resources/tanatana.ogg"); // Load OGG audio file + + int frame = 0; + + SetSoundVolume(fxWav, 0.2); + PlaySound(fxOgg); + + bool inhibitWav = false; + bool inhibitOgg = false; + int maxFrame = 60; + + int soundsCounter = 0; + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + frame++; + + if (IsKeyDown(KEY_ENTER)) inhibitWav = !inhibitWav; + if (IsKeyDown(KEY_SPACE)) inhibitOgg = !inhibitOgg; + + // Deliberatly hammer the play pool to see what dropping old pool entries sounds like.... + if ((frame%5) == 0) + { + if (!inhibitWav) PlaySoundMulti(fxWav); + } + + if (frame == maxFrame) + { + if (!inhibitOgg) PlaySoundMulti(fxOgg); + + frame = 0; + maxFrame = GetRandomValue(6,12); + } + + soundsCounter = GetSoundsPlaying(); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + DrawText("Multichannel sound abuse!", 200, 180, 20, LIGHTGRAY); + DrawText("Space to inhibit new ogg triggering", 200, 200, 20, LIGHTGRAY); + DrawText("Enter to inhibit new wav triggering", 200, 220, 20, LIGHTGRAY); + + DrawText(FormatText("Number of concurrentsounds: %i", soundsCounter), 200, 280, 20, LIGHTGRAY); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + StopSoundMulti(); // We must stop the buffer pool before unloading + + UnloadSound(fxWav); // Unload sound data + UnloadSound(fxOgg); // Unload sound data + + CloseAudioDevice(); // Close audio device + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} diff --git a/examples/audio/audio_music_stream.c b/examples/audio/audio_music_stream.c index 26450a869..bc069dccf 100644 --- a/examples/audio/audio_music_stream.c +++ b/examples/audio/audio_music_stream.c @@ -2,8 +2,6 @@ * * raylib [audio] example - Music playing (streaming) * -* NOTE: This example requires OpenAL Soft library installed -* * This example has been created using raylib 1.3 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * @@ -13,19 +11,19 @@ #include "raylib.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [audio] example - music playing (streaming)"); InitAudioDevice(); // Initialize audio device Music music = LoadMusicStream("resources/guitar_noodling.ogg"); - + PlayMusicStream(music); float timePlayed = 0.0f; @@ -39,27 +37,27 @@ int main() { // Update //---------------------------------------------------------------------------------- - UpdateMusicStream(music); // Update music buffer with new stream data - + UpdateMusicStream(music); // Update music buffer with new stream data + // Restart music playing (stop and play) - if (IsKeyPressed(KEY_SPACE)) + if (IsKeyPressed(KEY_SPACE)) { StopMusicStream(music); PlayMusicStream(music); } - - // Pause/Resume music playing + + // Pause/Resume music playing if (IsKeyPressed(KEY_P)) { pause = !pause; - + if (pause) PauseMusicStream(music); else ResumeMusicStream(music); } - + // Get timePlayed scaled to bar dimensions (400 pixels) timePlayed = GetMusicTimePlayed(music)/GetMusicTimeLength(music)*400; - + if (timePlayed > 400) StopMusicStream(music); //---------------------------------------------------------------------------------- @@ -74,7 +72,7 @@ int main() DrawRectangle(200, 200, 400, 12, LIGHTGRAY); DrawRectangle(200, 200, (int)timePlayed, 12, MAROON); DrawRectangleLines(200, 200, 400, 12, GRAY); - + DrawText("PRESS SPACE TO RESTART MUSIC", 215, 250, 20, LIGHTGRAY); DrawText("PRESS P TO PAUSE/RESUME MUSIC", 208, 280, 20, LIGHTGRAY); diff --git a/examples/audio/audio_raw_stream.c b/examples/audio/audio_raw_stream.c index d7fa5d790..85a77bc0a 100644 --- a/examples/audio/audio_raw_stream.c +++ b/examples/audio/audio_raw_stream.c @@ -2,11 +2,11 @@ * * raylib [audio] example - Raw audio streaming * -* NOTE: This example requires OpenAL Soft library installed -* * This example has been created using raylib 1.6 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * +* Example created by Ramon Santamaria (@raysan5) and reviewed by James Hofmann (@triplefox) +* * Copyright (c) 2015-2019 Ramon Santamaria (@raysan5) and James Hofmann (@triplefox) * ********************************************************************************************/ @@ -20,12 +20,12 @@ #define MAX_SAMPLES 512 #define MAX_SAMPLES_PER_UPDATE 4096 -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [audio] example - raw audio streaming"); @@ -33,30 +33,30 @@ int main() // Init raw audio stream (sample rate: 22050, sample size: 16bit-short, channels: 1-mono) AudioStream stream = InitAudioStream(22050, 16, 1); - + // Buffer for the single cycle waveform we are synthesizing short *data = (short *)malloc(sizeof(short)*MAX_SAMPLES); // Frame buffer, describing the waveform when repeated over the course of a frame short *writeBuf = (short *)malloc(sizeof(short)*MAX_SAMPLES_PER_UPDATE); - + PlayAudioStream(stream); // Start processing stream buffer (no data loaded currently) - + // Position read in to determine next frequency Vector2 mousePosition = { -100.0f, -100.0f }; - + // Cycles per second (hz) float frequency = 440.0f; - + // Previous value, used to test if sine needs to be rewritten, and to smoothly modulate frequency float oldFrequency = 1.0f; - + // Cursor to read and copy the samples of the sine wave buffer int readCursor = 0; - + // Computed size in samples of the sine wave int waveLength = 1; - + Vector2 position = { 0, 0 }; SetTargetFPS(30); // Set our game to run at 30 frames-per-second @@ -67,62 +67,62 @@ int main() { // Update //---------------------------------------------------------------------------------- - + // Sample mouse input. mousePosition = GetMousePosition(); - - if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) + + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) { float fp = (float)(mousePosition.y); frequency = 40.0f + (float)(fp); } - + // Rewrite the sine wave. // Compute two cycles to allow the buffer padding, simplifying any modulation, resampling, etc. - if (frequency != oldFrequency) + if (frequency != oldFrequency) { // Compute wavelength. Limit size in both directions. int oldWavelength = waveLength; waveLength = (int)(22050/frequency); if (waveLength > MAX_SAMPLES/2) waveLength = MAX_SAMPLES/2; if (waveLength < 1) waveLength = 1; - + // Write sine wave. for (int i = 0; i < waveLength*2; i++) { data[i] = (short)(sinf(((2*PI*(float)i/waveLength)))*32000); } - + // Scale read cursor's position to minimize transition artifacts readCursor = (int)(readCursor * ((float)waveLength / (float)oldWavelength)); oldFrequency = frequency; } - + // Refill audio stream if required - if (IsAudioBufferProcessed(stream)) + if (IsAudioStreamProcessed(stream)) { // Synthesize a buffer that is exactly the requested size int writeCursor = 0; - - while (writeCursor < MAX_SAMPLES_PER_UPDATE) + + while (writeCursor < MAX_SAMPLES_PER_UPDATE) { // Start by trying to write the whole chunk at once int writeLength = MAX_SAMPLES_PER_UPDATE-writeCursor; - + // Limit to the maximum readable size int readLength = waveLength-readCursor; - + if (writeLength > readLength) writeLength = readLength; // Write the slice memcpy(writeBuf + writeCursor, data + readCursor, writeLength*sizeof(short)); - + // Update cursors and loop audio readCursor = (readCursor + writeLength) % waveLength; - + writeCursor += writeLength; } - + // Copy finished frame to audio stream UpdateAudioStream(stream, writeBuf, MAX_SAMPLES_PER_UPDATE); } @@ -136,13 +136,13 @@ int main() DrawText(FormatText("sine frequency: %i",(int)frequency), GetScreenWidth() - 220, 10, 20, RED); DrawText("click mouse button to change frequency", 10, 10, 20, DARKGRAY); - + // Draw the current buffer state proportionate to the screen for (int i = 0; i < screenWidth; i++) { position.x = i; position.y = 250 + 50*data[i*MAX_SAMPLES/screenWidth]/32000; - + DrawPixelV(position, RED); } @@ -154,7 +154,7 @@ int main() //-------------------------------------------------------------------------------------- free(data); // Unload sine wave data free(writeBuf); // Unload write buffer - + CloseAudioStream(stream); // Close raw audio stream and delete buffers from RAM CloseAudioDevice(); // Close audio device (music streaming is automatically stopped) diff --git a/examples/audio/audio_sound_loading.c b/examples/audio/audio_sound_loading.c index 00e583264..5b0fc0d4d 100644 --- a/examples/audio/audio_sound_loading.c +++ b/examples/audio/audio_sound_loading.c @@ -2,8 +2,6 @@ * * raylib [audio] example - Sound loading and playing * -* NOTE: This example requires OpenAL Soft library installed -* * 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) * @@ -13,12 +11,12 @@ #include "raylib.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [audio] example - sound loading and playing"); @@ -26,8 +24,8 @@ int main() Sound fxWav = LoadSound("resources/sound.wav"); // Load WAV audio file Sound fxOgg = LoadSound("resources/tanatana.ogg"); // Load OGG audio file - - SetTargetFPS(60); + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop @@ -46,7 +44,6 @@ int main() ClearBackground(RAYWHITE); DrawText("Press SPACE to PLAY the WAV sound!", 200, 180, 20, LIGHTGRAY); - DrawText("Press ENTER to PLAY the OGG sound!", 200, 220, 20, LIGHTGRAY); EndDrawing(); diff --git a/examples/audio/resources/applause.mp3 b/examples/audio/resources/applause.mp3 deleted file mode 100644 index 084a7d1f8..000000000 Binary files a/examples/audio/resources/applause.mp3 and /dev/null differ diff --git a/examples/core/core_2d_camera.c b/examples/core/core_2d_camera.c index 6a0b11ad9..d6c85079e 100644 --- a/examples/core/core_2d_camera.c +++ b/examples/core/core_2d_camera.c @@ -13,21 +13,21 @@ #define MAX_BUILDINGS 100 -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - 2d camera"); - + Rectangle player = { 400, 280, 40, 40 }; - Rectangle buildings[MAX_BUILDINGS]; - Color buildColors[MAX_BUILDINGS]; - + Rectangle buildings[MAX_BUILDINGS] = { 0 }; + Color buildColors[MAX_BUILDINGS] = { 0 }; + int spacing = 0; - + for (int i = 0; i < MAX_BUILDINGS; i++) { buildings[i].width = GetRandomValue(50, 200); @@ -36,55 +36,48 @@ int main() buildings[i].x = -6000 + spacing; spacing += buildings[i].width; - + buildColors[i] = (Color){ GetRandomValue(200, 240), GetRandomValue(200, 240), GetRandomValue(200, 250), 255 }; } - - Camera2D camera; - + + Camera2D camera = { 0 }; camera.target = (Vector2){ player.x + 20, player.y + 20 }; - camera.offset = (Vector2){ 0, 0 }; + camera.offset = (Vector2){ screenWidth/2, screenHeight/2 }; camera.rotation = 0.0f; camera.zoom = 1.0f; - - SetTargetFPS(60); + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop - while (!WindowShouldClose()) // Detect window close button or ESC key + while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- - if (IsKeyDown(KEY_RIGHT)) - { - player.x += 2; // Player movement - camera.offset.x -= 2; // Camera displacement with player movement - } - else if (IsKeyDown(KEY_LEFT)) - { - player.x -= 2; // Player movement - camera.offset.x += 2; // Camera displacement with player movement - } + // Player movement + if (IsKeyDown(KEY_RIGHT)) player.x += 2; + else if (IsKeyDown(KEY_LEFT)) player.x -= 2; + // Camera target follows player camera.target = (Vector2){ player.x + 20, player.y + 20 }; - + // Camera rotation controls if (IsKeyDown(KEY_A)) camera.rotation--; else if (IsKeyDown(KEY_S)) camera.rotation++; - + // Limit camera rotation to 80 degrees (-40 to 40) - if (camera.rotation > 40) camera.rotation = 40; + if (camera.rotation > 40) camera.rotation = 40; else if (camera.rotation < -40) camera.rotation = -40; - + // Camera zoom controls camera.zoom += ((float)GetMouseWheelMove()*0.05f); - + if (camera.zoom > 3.0f) camera.zoom = 3.0f; else if (camera.zoom < 0.1f) camera.zoom = 0.1f; - + // Camera reset (zoom and rotation) - if (IsKeyPressed(KEY_R)) + if (IsKeyPressed(KEY_R)) { camera.zoom = 1.0f; camera.rotation = 0.0f; @@ -94,32 +87,32 @@ int main() // Draw //---------------------------------------------------------------------------------- BeginDrawing(); - + ClearBackground(RAYWHITE); - + BeginMode2D(camera); DrawRectangle(-6000, 320, 13000, 8000, DARKGRAY); - + for (int i = 0; i < MAX_BUILDINGS; i++) DrawRectangleRec(buildings[i], buildColors[i]); - + DrawRectangleRec(player, RED); - + DrawLine(camera.target.x, -screenHeight*10, camera.target.x, screenHeight*10, GREEN); DrawLine(-screenWidth*10, camera.target.y, screenWidth*10, camera.target.y, GREEN); - + EndMode2D(); - + DrawText("SCREEN AREA", 640, 10, 20, RED); - + DrawRectangle(0, 0, screenWidth, 5, RED); DrawRectangle(0, 5, 5, screenHeight - 10, RED); DrawRectangle(screenWidth - 5, 5, 5, screenHeight - 10, RED); DrawRectangle(0, screenHeight - 5, screenWidth, 5, RED); - + DrawRectangle( 10, 10, 250, 113, Fade(SKYBLUE, 0.5f)); DrawRectangleLines( 10, 10, 250, 113, BLUE); - + DrawText("Free 2d camera controls:", 20, 20, 10, BLACK); DrawText("- Right/Left to move Offset", 40, 40, 10, DARKGRAY); DrawText("- Mouse Wheel to Zoom in-out", 40, 60, 10, DARKGRAY); @@ -131,9 +124,9 @@ int main() } // De-Initialization - //-------------------------------------------------------------------------------------- + //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; -} \ No newline at end of file +} diff --git a/examples/core/core_2d_camera_ext.c b/examples/core/core_2d_camera_ext.c new file mode 100644 index 000000000..330e39ef9 --- /dev/null +++ b/examples/core/core_2d_camera_ext.c @@ -0,0 +1,284 @@ +/******************************************************************************************* +* +* raylib [core] example - 2d camera extended +* +* This example has been created using raylib 1.5 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2016 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" +#include "raymath.h" + +#define G 400 +#define PLAYER_JUMP_SPD 350.f +#define PLAYER_HOR_SPD 200.f + +typedef struct Player { + Vector2 pos; + float vel; + int canJump; +} Player; + +typedef struct EnvItem { + Rectangle rect; + int blocking; + Color color; +} EnvItem; + +void updateCameraCenter( + float delta, + Camera2D *camera, + Player *player, + EnvItem *envItems, + int envItemsLength, + int width, int height +) { + camera->offset = (Vector2){ width/2, height/2 }; + camera->target = player->pos; +} + +void updateCameraCenterInsideMap( + float delta, + Camera2D *camera, + Player *player, + EnvItem *envItems, + int envItemsLength, + int width, int height +) { + camera->target = player->pos; + camera->offset = (Vector2){ width/2, height/2 }; + float minX = 1000, minY = 1000, maxX = -1000, maxY = -1000; + for (int i = 0; i < envItemsLength; i++) { + EnvItem *ei = envItems + i; + minX = fminf(ei->rect.x, minX); + maxX = fmaxf(ei->rect.x + ei->rect.width, maxX); + minY = fminf(ei->rect.y, minY); + maxY = fmaxf(ei->rect.y + ei->rect.height, maxY); + } + Vector2 max = GetWorldToScreen2D((Vector2){ maxX, maxY }, *camera); + Vector2 min = GetWorldToScreen2D((Vector2){ minX, minY }, *camera); + if (max.x < width) { + camera->offset.x = width - (max.x - width/2); + } + if (max.y < height) { + camera->offset.y = height - (max.y - height/2); + } + if (min.x > 0) { + camera->offset.x = width/2 - min.x; + } + if (min.y > 0) { + camera->offset.y = height/2- min.y; + } +} + +void updateCameraCenterSmoothFollow( + float delta, + Camera2D *camera, + Player *player, + EnvItem *envItems, + int envItemsLength, + int width, int height +) { + static float minSpeed = 30; + static float minEffectLength = 10; + static float fractionSpeed = 0.8f; + camera->offset = (Vector2){ width/2, height/2 }; + Vector2 diff = Vector2Subtract(player->pos, camera->target); + float length = Vector2Length(diff); + if (length > minEffectLength) { + float speed = fmaxf(fractionSpeed * length, minSpeed); + camera->target = Vector2Add(camera->target, Vector2Scale(diff, speed*delta/length)); + } +} + +void updateCameraEvenOutOnLanding( + float delta, + Camera2D *camera, + Player *player, + EnvItem *envItems, + int envItemsLength, + int width, int height +) { + static float evenOutSpeed = 700; + static int eveningOut = false; + static float evenOutTarget; + camera->offset = (Vector2){ width/2, height/2 }; + camera->target.x = player->pos.x; + if (eveningOut) { + if (evenOutTarget > camera->target.y) { + camera->target.y += evenOutSpeed * delta; + if (camera->target.y > evenOutTarget) { + camera->target.y = evenOutTarget; + eveningOut = 0; + } + } else { + camera->target.y -= evenOutSpeed * delta; + if (camera->target.y < evenOutTarget) { + camera->target.y = evenOutTarget; + eveningOut = 0; + } + } + } else { + if (player->canJump && + player->vel == 0 && + player->pos.y != camera->target.y + ) { + eveningOut = 1; + evenOutTarget = player->pos.y; + } + } +} + +void updateCameraPlayerBoundsPush( + float delta, + Camera2D *camera, + Player *player, + EnvItem *envItems, + int envItemsLength, + int width, int height +) { + static Vector2 bbox = { 0.2f, 0.2f }; + + Vector2 bboxWorldMin = GetScreenToWorld2D((Vector2){ (1 - bbox.x) * 0.5 * width, (1 - bbox.y) * 0.5 * height }, *camera); + Vector2 bboxWorldMax = GetScreenToWorld2D((Vector2){ (1 + bbox.x) * 0.5 * width, (1 + bbox.y) * 0.5 * height }, *camera); + camera->offset = (Vector2){ (1 - bbox.x) * 0.5 * width, (1 - bbox.y) * 0.5 * height }; + + if (player->pos.x < bboxWorldMin.x) { + camera->target.x = player->pos.x; + } + if (player->pos.y < bboxWorldMin.y) { + camera->target.y = player->pos.y; + } + if (player->pos.x > bboxWorldMax.x) { + camera->target.x = bboxWorldMin.x + (player->pos.x - bboxWorldMax.x); + } + if (player->pos.y > bboxWorldMax.y) { + camera->target.y = bboxWorldMin.y + (player->pos.y - bboxWorldMax.y); + } +} + + +void updatePlayer(float delta, Player *player, EnvItem *envItems, int envItemsLength) { + if (IsKeyDown(KEY_LEFT)) player->pos.x -= PLAYER_HOR_SPD*delta; + if (IsKeyDown(KEY_RIGHT)) player->pos.x += PLAYER_HOR_SPD*delta; + if (IsKeyDown(KEY_SPACE) && player->canJump) { + player->vel = -PLAYER_JUMP_SPD; + player->canJump = 0; + } + + int hitObstacle = 0; + for (int i = 0; i < envItemsLength; i++) { + EnvItem *ei = envItems + i; + Vector2 *p = &(player->pos); + if (ei->blocking && + ei->rect.x <= p->x && + ei->rect.x + ei->rect.width >= p->x && + ei->rect.y >= p->y && + ei->rect.y < p->y + player->vel * delta) + { + hitObstacle = 1; + player->vel = 0.0f; + p->y = ei->rect.y; + } + } + if (!hitObstacle) { + player->pos.y += player->vel * delta; + player->vel += G * delta; + player->canJump = 0; + } else { + player->canJump = 1; + } +} + +void renderWorld(Player *player, EnvItem *envItems, int envItemsLength) { + for (int i = 0; i < envItemsLength; i++) { + DrawRectangleRec(envItems[i].rect, envItems[i].color); + } + Rectangle playerRect = { player->pos.x - 20, player->pos.y - 40, 40, 40 }; + DrawRectangleRec(playerRect, RED); +} + +int main(void) +{ + const int screenWidth = 800; + const int screenHeight = 450; + InitWindow(screenWidth, screenHeight, "raylib [core] example - 2d camera"); + SetTargetFPS(60); + + Player player; + player.pos = (Vector2){ 400, 280 }; + player.vel = 0; + player.canJump = 0; + EnvItem envItems[] = { + {{ 0, 0, 1000, 400 }, 0, LIGHTGRAY }, + {{ 0, 400, 1000, 200 }, 1, GRAY }, + {{ 300, 200, 400, 10 }, 1, GRAY }, + {{ 250, 300, 100, 10 }, 1, GRAY }, + {{ 650, 300, 100, 10 }, 1, GRAY } + }; + int envItemsLength = sizeof(envItems) / sizeof (envItems[0]); + + Camera2D camera = { 0 }; + camera.target = player.pos; + camera.offset = (Vector2){ screenWidth/2, screenHeight/2 }; + camera.rotation = 0.0f; + camera.zoom = 1.0f; + + int cameraOption = 0; + void (*cameraUpdaters[])(float, Camera2D*, Player*, EnvItem*, int, int, int) = { + updateCameraCenter, + updateCameraCenterInsideMap, + updateCameraCenterSmoothFollow, + updateCameraEvenOutOnLanding, + updateCameraPlayerBoundsPush + }; + int cameraUpdatersLength = sizeof(cameraUpdaters) / sizeof(cameraUpdaters[0]); + char* cameraDescriptions[] = { + "Follow player center", + "Follow player center, but clamp to map edges", + "Follow player center; smoothed", + "Follow player center horizontally; updateplayer center vertically after landing", + "Player push camera on getting too close to screen edge" + }; + + while (!WindowShouldClose()) { + float delta = GetFrameTime(); + updatePlayer(delta, &player, envItems, envItemsLength); + + camera.zoom += ((float)GetMouseWheelMove()*0.05f); + if (camera.zoom > 3.0f) camera.zoom = 3.0f; + else if (camera.zoom < 0.25f) camera.zoom = 0.25f; + if (IsKeyPressed(KEY_R)) + { + camera.zoom = 1.0f; + } + + if (IsKeyPressed(KEY_C)) { + cameraOption = (cameraOption + 1) % cameraUpdatersLength; + } + cameraUpdaters[cameraOption](delta, &camera, &player, envItems, envItemsLength, screenWidth, screenHeight); + + BeginDrawing(); + ClearBackground(RAYWHITE); + + BeginMode2D(camera); + renderWorld(&player, envItems, envItemsLength); + EndMode2D(); + + DrawText("Controls:", 20, 20, 10, BLACK); + DrawText("- Right/Left to move", 40, 40, 10, DARKGRAY); + DrawText("- Space to jump", 40, 60, 10, DARKGRAY); + DrawText("- Mouse Wheel to Zoom in-out, R to reset zoom", 40, 80, 10, DARKGRAY); + DrawText("- C to change camera mode", 40, 100, 10, DARKGRAY); + DrawText("Current camera mode:", 20, 120, 10, BLACK); + DrawText(cameraDescriptions[cameraOption], 40, 140, 10, DARKGRAY); + EndDrawing(); + } + + CloseWindow(); // Close window and OpenGL context + + return 0; +} diff --git a/examples/core/core_3d_camera_first_person.c b/examples/core/core_3d_camera_first_person.c index d3a8f2e4b..39fbfb2eb 100644 --- a/examples/core/core_3d_camera_first_person.c +++ b/examples/core/core_3d_camera_first_person.c @@ -13,15 +13,15 @@ #define MAX_COLUMNS 20 -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d camera first person"); - + // Define the camera to look into our 3d world (position, target, up vector) Camera camera = { 0 }; camera.position = (Vector3){ 4.0f, 2.0f, 4.0f }; @@ -31,17 +31,17 @@ int main() camera.type = CAMERA_PERSPECTIVE; // Generates some random columns - float heights[MAX_COLUMNS]; - Vector3 positions[MAX_COLUMNS]; - Color colors[MAX_COLUMNS]; - + float heights[MAX_COLUMNS] = { 0.0f }; + Vector3 positions[MAX_COLUMNS] = { 0 }; + Color colors[MAX_COLUMNS] = { 0 }; + for (int i = 0; i < MAX_COLUMNS; i++) { heights[i] = (float)GetRandomValue(1, 12); positions[i] = (Vector3){ GetRandomValue(-15, 15), heights[i]/2, GetRandomValue(-15, 15) }; colors[i] = (Color){ GetRandomValue(20, 255), GetRandomValue(10, 55), 30, 255 }; } - + SetCameraMode(camera, CAMERA_FIRST_PERSON); // Set a first person camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second @@ -67,7 +67,7 @@ int main() DrawCube((Vector3){ -16.0f, 2.5f, 0.0f }, 1.0f, 5.0f, 32.0f, BLUE); // Draw a blue wall DrawCube((Vector3){ 16.0f, 2.5f, 0.0f }, 1.0f, 5.0f, 32.0f, LIME); // Draw a green wall DrawCube((Vector3){ 0.0f, 2.5f, 16.0f }, 32.0f, 5.0f, 1.0f, GOLD); // Draw a yellow wall - + // Draw some cubes around for (int i = 0; i < MAX_COLUMNS; i++) { @@ -76,7 +76,7 @@ int main() } EndMode3D(); - + DrawRectangle( 10, 10, 220, 70, Fade(SKYBLUE, 0.5f)); DrawRectangleLines( 10, 10, 220, 70, BLUE); @@ -89,7 +89,7 @@ int main() } // De-Initialization - //-------------------------------------------------------------------------------------- + //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/core/core_3d_camera_free.c b/examples/core/core_3d_camera_free.c index 9131ddf87..5053fd63a 100644 --- a/examples/core/core_3d_camera_free.c +++ b/examples/core/core_3d_camera_free.c @@ -11,25 +11,25 @@ #include "raylib.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d camera free"); // Define the camera to look into our 3d world - Camera3D camera; + Camera3D camera = { 0 }; camera.position = (Vector3){ 10.0f, 10.0f, 10.0f }; // Camera position camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target) camera.fovy = 45.0f; // Camera field-of-view Y camera.type = CAMERA_PERSPECTIVE; // Camera mode type - + Vector3 cubePosition = { 0.0f, 0.0f, 0.0f }; - + SetCameraMode(camera, CAMERA_FREE); // Set a free camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second @@ -41,7 +41,7 @@ int main() // Update //---------------------------------------------------------------------------------- UpdateCamera(&camera); // Update camera - + if (IsKeyDown('Z')) camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; //---------------------------------------------------------------------------------- @@ -59,10 +59,10 @@ int main() DrawGrid(10, 1.0f); EndMode3D(); - + DrawRectangle( 10, 10, 320, 133, Fade(SKYBLUE, 0.5f)); DrawRectangleLines( 10, 10, 320, 133, BLUE); - + DrawText("Free camera default controls:", 20, 20, 10, BLACK); DrawText("- Mouse Wheel to Zoom in-out", 40, 40, 10, DARKGRAY); DrawText("- Mouse Wheel Pressed to Pan", 40, 60, 10, DARKGRAY); diff --git a/examples/core/core_3d_mode.c b/examples/core/core_3d_camera_mode.c similarity index 90% rename from examples/core/core_3d_mode.c rename to examples/core/core_3d_camera_mode.c index 39c0752ab..eae6c888c 100644 --- a/examples/core/core_3d_mode.c +++ b/examples/core/core_3d_camera_mode.c @@ -1,6 +1,6 @@ /******************************************************************************************* * -* raylib [core] example - Initialize 3d mode +* raylib [core] example - Initialize 3d camera mode * * 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) @@ -11,17 +11,17 @@ #include "raylib.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; - InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d mode"); + InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d camera mode"); // Define the camera to look into our 3d world - Camera3D camera; + Camera3D camera = { 0 }; camera.position = (Vector3){ 0.0f, 10.0f, 10.0f }; // Camera position camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target) @@ -30,7 +30,7 @@ int main() Vector3 cubePosition = { 0.0f, 0.0f, 0.0f }; - SetTargetFPS(60); // Set our game to run at 60 frames-per-second + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop diff --git a/examples/core/core_3d_mode.png b/examples/core/core_3d_camera_mode.png similarity index 100% rename from examples/core/core_3d_mode.png rename to examples/core/core_3d_camera_mode.png diff --git a/examples/core/core_3d_picking.c b/examples/core/core_3d_picking.c index 1c63e2a7f..baf35036e 100644 --- a/examples/core/core_3d_picking.c +++ b/examples/core/core_3d_picking.c @@ -11,17 +11,17 @@ #include "raylib.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d picking"); // Define the camera to look into our 3d world - Camera camera; + Camera camera = { 0 }; camera.position = (Vector3){ 10.0f, 10.0f, 10.0f }; // Camera position camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target) @@ -31,7 +31,7 @@ int main() Vector3 cubePosition = { 0.0f, 1.0f, 0.0f }; Vector3 cubeSize = { 2.0f, 2.0f, 2.0f }; - Ray ray = {0.0f, 0.0f, 0.0f}; // Picking line ray + Ray ray = { 0 }; // Picking line ray bool collision = false; @@ -49,12 +49,16 @@ int main() if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) { - ray = GetMouseRay(GetMousePosition(), camera); + if (!collision) + { + ray = GetMouseRay(GetMousePosition(), camera); - // Check collision between ray and box - collision = CheckCollisionRayBox(ray, - (BoundingBox){(Vector3){ cubePosition.x - cubeSize.x/2, cubePosition.y - cubeSize.y/2, cubePosition.z - cubeSize.z/2 }, - (Vector3){ cubePosition.x + cubeSize.x/2, cubePosition.y + cubeSize.y/2, cubePosition.z + cubeSize.z/2 }}); + // Check collision between ray and box + collision = CheckCollisionRayBox(ray, + (BoundingBox){(Vector3){ cubePosition.x - cubeSize.x/2, cubePosition.y - cubeSize.y/2, cubePosition.z - cubeSize.z/2 }, + (Vector3){ cubePosition.x + cubeSize.x/2, cubePosition.y + cubeSize.y/2, cubePosition.z + cubeSize.z/2 }}); + } + else collision = false; } //---------------------------------------------------------------------------------- diff --git a/examples/core/core_basic_window.c b/examples/core/core_basic_window.c index b30f05dec..3c103a5f2 100644 --- a/examples/core/core_basic_window.c +++ b/examples/core/core_basic_window.c @@ -21,16 +21,16 @@ #include "raylib.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window"); - - SetTargetFPS(60); + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop @@ -54,7 +54,7 @@ int main() } // De-Initialization - //-------------------------------------------------------------------------------------- + //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/core/core_basic_window.cpp b/examples/core/core_basic_window.cpp index fa12026a0..414f91852 100644 --- a/examples/core/core_basic_window.cpp +++ b/examples/core/core_basic_window.cpp @@ -23,40 +23,40 @@ int main(int argc, char* argv[]) { - // Initialization - //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + // Initialization + //-------------------------------------------------------------------------------------- + int screenWidth = 800; + int screenHeight = 450; - InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window"); + InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window"); - SetTargetFPS(60); - //-------------------------------------------------------------------------------------- - - // Main game loop - while (!WindowShouldClose()) // Detect window close button or ESC key - { - // Update - //---------------------------------------------------------------------------------- - // TODO: Update your variables here - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - BeginDrawing(); - - ClearBackground(RAYWHITE); - - DrawText("Congrats! You created your first window!", 190, 200, 20, LIGHTGRAY); - - EndDrawing(); - //---------------------------------------------------------------------------------- - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - CloseWindow(); // Close window and OpenGL context + SetTargetFPS(60); //-------------------------------------------------------------------------------------- - return 0; + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + // TODO: Update your variables here + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + DrawText("Congrats! You created your first window!", 190, 200, 20, LIGHTGRAY); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; } \ No newline at end of file diff --git a/examples/core/core_color_select.c b/examples/core/core_color_select.c deleted file mode 100644 index 002a69312..000000000 --- a/examples/core/core_color_select.c +++ /dev/null @@ -1,94 +0,0 @@ -/******************************************************************************************* -* -* raylib [core] example - Color selection by mouse (collision detection) -* -* 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 (@raysan5) -* -********************************************************************************************/ - -#include "raylib.h" - -int main() -{ - // Initialization - //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; - - InitWindow(screenWidth, screenHeight, "raylib [core] example - color selection (collision detection)"); - - Color colors[21] = { DARKGRAY, MAROON, ORANGE, DARKGREEN, DARKBLUE, DARKPURPLE, DARKBROWN, - GRAY, RED, GOLD, LIME, BLUE, VIOLET, BROWN, LIGHTGRAY, PINK, YELLOW, - GREEN, SKYBLUE, PURPLE, BEIGE }; - - Rectangle colorsRecs[21]; // Rectangles array - - // Fills colorsRecs data (for every rectangle) - for (int i = 0; i < 21; i++) - { - colorsRecs[i].x = 20 + 100*(i%7) + 10*(i%7); - colorsRecs[i].y = 60 + 100*(i/7) + 10*(i/7); - colorsRecs[i].width = 100; - colorsRecs[i].height = 100; - } - - bool selected[21] = { false }; // Selected rectangles indicator - - Vector2 mousePoint; - - SetTargetFPS(60); // Set our game to run at 60 frames-per-second - //-------------------------------------------------------------------------------------- - - // Main game loop - while (!WindowShouldClose()) // Detect window close button or ESC key - { - // Update - //---------------------------------------------------------------------------------- - mousePoint = GetMousePosition(); - - for (int i = 0; i < 21; i++) // Iterate along all the rectangles - { - if (CheckCollisionPointRec(mousePoint, colorsRecs[i])) - { - colors[i].a = 120; - - if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) selected[i] = !selected[i]; - } - else colors[i].a = 255; - } - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - BeginDrawing(); - - ClearBackground(RAYWHITE); - - for (int i = 0; i < 21; i++) // Draw all rectangles - { - DrawRectangleRec(colorsRecs[i], colors[i]); - - // Draw four rectangles around selected rectangle - if (selected[i]) - { - DrawRectangle(colorsRecs[i].x, colorsRecs[i].y, 100, 10, RAYWHITE); // Square top rectangle - DrawRectangle(colorsRecs[i].x, colorsRecs[i].y, 10, 100, RAYWHITE); // Square left rectangle - DrawRectangle(colorsRecs[i].x + 90, colorsRecs[i].y, 10, 100, RAYWHITE); // Square right rectangle - DrawRectangle(colorsRecs[i].x, colorsRecs[i].y + 90, 100, 10, RAYWHITE); // Square bottom rectangle - } - } - - EndDrawing(); - //---------------------------------------------------------------------------------- - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} \ No newline at end of file diff --git a/examples/core/core_color_select.png b/examples/core/core_color_select.png deleted file mode 100644 index 93ab83ae3..000000000 Binary files a/examples/core/core_color_select.png and /dev/null differ diff --git a/examples/core/core_custom_logging.c b/examples/core/core_custom_logging.c index 4c4caf5d7..56e168eed 100644 --- a/examples/core/core_custom_logging.c +++ b/examples/core/core_custom_logging.c @@ -5,7 +5,9 @@ * This example has been created using raylib 2.1 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * -* Copyright (c) 2018 Ramon Santamaria (@raysan5) and Pablo Marcos Oltra (@pamarcos) +* Example contributed by Pablo Marcos Oltra (@pamarcos) and reviewed by Ramon Santamaria (@raysan5) +* +* Copyright (c) 2018 Pablo Marcos Oltra (@pamarcos) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ @@ -17,66 +19,66 @@ // Custom logging funtion void LogCustom(int msgType, const char *text, va_list args) { - char timeStr[64]; - time_t now = time(NULL); - struct tm *tm_info = localtime(&now); + char timeStr[64] = { 0 }; + time_t now = time(NULL); + struct tm *tm_info = localtime(&now); - strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", tm_info); - printf("[%s] ", timeStr); + strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", tm_info); + printf("[%s] ", timeStr); - switch (msgType) - { - case LOG_INFO: printf("[INFO] : "); break; - case LOG_ERROR: printf("[ERROR]: "); break; - case LOG_WARNING: printf("[WARN] : "); break; - case LOG_DEBUG: printf("[DEBUG]: "); break; - default: break; - } - - vprintf(text, args); - printf("\n"); + switch (msgType) + { + case LOG_INFO: printf("[INFO] : "); break; + case LOG_ERROR: printf("[ERROR]: "); break; + case LOG_WARNING: printf("[WARN] : "); break; + case LOG_DEBUG: printf("[DEBUG]: "); break; + default: break; + } + + vprintf(text, args); + printf("\n"); } int main(int argc, char* argv[]) { - // Initialization - //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; - // First thing we do is setting our custom logger to ensure everything raylib logs - // will use our own logger instead of its internal one - SetTraceLogCallback(LogCustom); + // First thing we do is setting our custom logger to ensure everything raylib logs + // will use our own logger instead of its internal one + SetTraceLogCallback(LogCustom); - InitWindow(screenWidth, screenHeight, "raylib [core] example - custom logging"); + InitWindow(screenWidth, screenHeight, "raylib [core] example - custom logging"); - SetTargetFPS(60); - //-------------------------------------------------------------------------------------- + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + //-------------------------------------------------------------------------------------- - // Main game loop - while (!WindowShouldClose()) // Detect window close button or ESC key - { - // Update - //---------------------------------------------------------------------------------- - // TODO: Update your variables here - //---------------------------------------------------------------------------------- + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + // TODO: Update your variables here + //---------------------------------------------------------------------------------- - // Draw - //---------------------------------------------------------------------------------- - BeginDrawing(); + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); - ClearBackground(RAYWHITE); + ClearBackground(RAYWHITE); - DrawText("Check out the console output to see the custom logger in action!", 60, 200, 20, LIGHTGRAY); + DrawText("Check out the console output to see the custom logger in action!", 60, 200, 20, LIGHTGRAY); - EndDrawing(); - //---------------------------------------------------------------------------------- - } + EndDrawing(); + //---------------------------------------------------------------------------------- + } - // De-Initialization - //-------------------------------------------------------------------------------------- - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- + // De-Initialization + //-------------------------------------------------------------------------------------- + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- - return 0; + return 0; } diff --git a/examples/core/core_drop_files.c b/examples/core/core_drop_files.c index 5c1501b83..5c3af6ab2 100644 --- a/examples/core/core_drop_files.c +++ b/examples/core/core_drop_files.c @@ -13,19 +13,19 @@ #include "raylib.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - drop files"); - + int count = 0; char **droppedFiles = { 0 }; - - SetTargetFPS(60); + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop @@ -49,15 +49,15 @@ int main() else { DrawText("Dropped files:", 100, 40, 20, DARKGRAY); - + for (int i = 0; i < count; i++) { if (i%2 == 0) DrawRectangle(0, 85 + 40*i, screenWidth, 40, Fade(LIGHTGRAY, 0.5f)); else DrawRectangle(0, 85 + 40*i, screenWidth, 40, Fade(LIGHTGRAY, 0.3f)); - + DrawText(droppedFiles[i], 120, 100 + 40*i, 10, GRAY); } - + DrawText("Drop new files...", 100, 110 + 40*count, 20, DARKGRAY); } @@ -68,7 +68,7 @@ int main() // De-Initialization //-------------------------------------------------------------------------------------- ClearDroppedFiles(); // Clear internal buffers - + CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/core/core_input_gamepad.c b/examples/core/core_input_gamepad.c index e8a1c0511..51646aab8 100644 --- a/examples/core/core_input_gamepad.c +++ b/examples/core/core_input_gamepad.c @@ -3,15 +3,15 @@ * raylib [core] example - Gamepad input * * NOTE: This example requires a Gamepad connected to the system -* raylib is configured to work with the following gamepads: +* raylib is configured to work with the following gamepads: * - Xbox 360 Controller (Xbox 360, Xbox One) -* - PLAYSTATION(R)3 Controller +* - PLAYSTATION(R)3 Controller * Check raylib.h for buttons configuration * -* This example has been created using raylib 1.6 (www.raylib.com) +* This example has been created using raylib 2.5 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * -* Copyright (c) 2013-2016 Ramon Santamaria (@raysan5) +* Copyright (c) 2013-2019 Ramon Santamaria (@raysan5) * ********************************************************************************************/ @@ -26,21 +26,21 @@ #define PS3_NAME_ID "PLAYSTATION(R)3 Controller" #endif -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; + + SetConfigFlags(FLAG_MSAA_4X_HINT); // Set MSAA 4X hint before windows creation - SetConfigFlags(FLAG_MSAA_4X_HINT); // Set MSAA 4X hint before windows creation - InitWindow(screenWidth, screenHeight, "raylib [core] example - gamepad input"); - + Texture2D texPs3Pad = LoadTexture("resources/ps3.png"); Texture2D texXboxPad = LoadTexture("resources/xbox.png"); - SetTargetFPS(60); + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop @@ -56,7 +56,7 @@ int main() BeginDrawing(); ClearBackground(RAYWHITE); - + if (IsGamepadAvailable(GAMEPAD_PLAYER1)) { DrawText(FormatText("GP1: %s", GetGamepadName(GAMEPAD_PLAYER1)), 10, 10, 10, BLACK); @@ -64,7 +64,7 @@ int main() if (IsGamepadName(GAMEPAD_PLAYER1, XBOX360_NAME_ID)) { DrawTexture(texXboxPad, 0, 0, DARKGRAY); - + // Draw buttons: xbox home if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_BUTTON_MIDDLE)) DrawCircle(394, 89, 19, RED); @@ -75,7 +75,7 @@ int main() if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_BUTTON_RIGHT_FACE_DOWN)) DrawCircle(536, 187, 15, LIME); if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_BUTTON_RIGHT_FACE_RIGHT)) DrawCircle(572, 151, 15, MAROON); if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_BUTTON_RIGHT_FACE_UP)) DrawCircle(536, 115, 15, GOLD); - + // Draw buttons: d-pad DrawRectangle(317, 202, 19, 71, BLACK); DrawRectangle(293, 228, 69, 19, BLACK); @@ -83,7 +83,7 @@ int main() if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_BUTTON_LEFT_FACE_DOWN)) DrawRectangle(317, 202 + 45, 19, 26, RED); if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_BUTTON_LEFT_FACE_LEFT)) DrawRectangle(292, 228, 25, 19, RED); if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_BUTTON_LEFT_FACE_RIGHT)) DrawRectangle(292 + 44, 228, 26, 19, RED); - + // Draw buttons: left-right back if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_BUTTON_LEFT_TRIGGER_1)) DrawCircle(259, 61, 20, RED); if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_BUTTON_RIGHT_TRIGGER_1)) DrawCircle(536, 61, 20, RED); @@ -91,21 +91,21 @@ int main() // Draw axis: left joystick DrawCircle(259, 152, 39, BLACK); DrawCircle(259, 152, 34, LIGHTGRAY); - DrawCircle(259 + (GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_AXIS_LEFT_X)*20), + DrawCircle(259 + (GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_AXIS_LEFT_X)*20), 152 - (GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_AXIS_LEFT_Y)*20), 25, BLACK); - + // Draw axis: right joystick DrawCircle(461, 237, 38, BLACK); DrawCircle(461, 237, 33, LIGHTGRAY); - DrawCircle(461 + (GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_AXIS_RIGHT_X)*20), + DrawCircle(461 + (GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_AXIS_RIGHT_X)*20), 237 - (GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_AXIS_RIGHT_Y)*20), 25, BLACK); // Draw axis: left-right triggers DrawRectangle(170, 30, 15, 70, GRAY); - DrawRectangle(604, 30, 15, 70, GRAY); + DrawRectangle(604, 30, 15, 70, GRAY); DrawRectangle(170, 30, 15, (((1.0f + GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_AXIS_LEFT_TRIGGER))/2.0f)*70), RED); DrawRectangle(604, 30, 15, (((1.0f + GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_AXIS_RIGHT_TRIGGER))/2.0f)*70), RED); - + //DrawText(FormatText("Xbox axis LT: %02.02f", GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_AXIS_LEFT_TRIGGER)), 10, 40, 10, BLACK); //DrawText(FormatText("Xbox axis RT: %02.02f", GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_AXIS_RIGHT_TRIGGER)), 10, 60, 10, BLACK); } @@ -115,7 +115,7 @@ int main() // Draw buttons: ps if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_BUTTON_MIDDLE)) DrawCircle(396, 222, 13, RED); - + // Draw buttons: basic if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_BUTTON_MIDDLE_LEFT)) DrawRectangle(328, 170, 32, 13, RED); if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_BUTTON_MIDDLE_RIGHT)) DrawTriangle((Vector2){ 436, 168 }, (Vector2){ 436, 185 }, (Vector2){ 464, 177 }, RED); @@ -131,7 +131,7 @@ int main() if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_BUTTON_LEFT_FACE_DOWN)) DrawRectangle(225, 132 + 54, 24, 30, RED); if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_BUTTON_LEFT_FACE_LEFT)) DrawRectangle(195, 161, 30, 25, RED); if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_BUTTON_LEFT_FACE_RIGHT)) DrawRectangle(195 + 54, 161, 30, 25, RED); - + // Draw buttons: left-right back buttons if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_BUTTON_LEFT_TRIGGER_1)) DrawCircle(239, 82, 20, RED); if (IsGamepadButtonDown(GAMEPAD_PLAYER1, GAMEPAD_BUTTON_RIGHT_TRIGGER_1)) DrawCircle(557, 82, 20, RED); @@ -139,42 +139,42 @@ int main() // Draw axis: left joystick DrawCircle(319, 255, 35, BLACK); DrawCircle(319, 255, 31, LIGHTGRAY); - DrawCircle(319 + (GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_AXIS_LEFT_X)*20), + DrawCircle(319 + (GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_AXIS_LEFT_X)*20), 255 + (GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_AXIS_LEFT_Y)*20), 25, BLACK); - + // Draw axis: right joystick DrawCircle(475, 255, 35, BLACK); DrawCircle(475, 255, 31, LIGHTGRAY); - DrawCircle(475 + (GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_AXIS_RIGHT_X)*20), + DrawCircle(475 + (GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_AXIS_RIGHT_X)*20), 255 + (GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_AXIS_RIGHT_Y)*20), 25, BLACK); // Draw axis: left-right triggers DrawRectangle(169, 48, 15, 70, GRAY); - DrawRectangle(611, 48, 15, 70, GRAY); + DrawRectangle(611, 48, 15, 70, GRAY); DrawRectangle(169, 48, 15, (((1.0f - GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_AXIS_LEFT_TRIGGER))/2.0f)*70), RED); DrawRectangle(611, 48, 15, (((1.0f - GetGamepadAxisMovement(GAMEPAD_PLAYER1, GAMEPAD_AXIS_RIGHT_TRIGGER))/2.0f)*70), RED); } else { DrawText("- GENERIC GAMEPAD -", 280, 180, 20, GRAY); - + // TODO: Draw generic gamepad } - - DrawText(FormatText("DETECTED AXIS [%i]:", GetGamepadAxisCount(GAMEPAD_PLAYER1)), 10, 50, 10, MAROON); - + + DrawText(FormatText("DETECTED AXIS [%i]:", GetGamepadAxisCount(GAMEPAD_PLAYER1)), 10, 50, 10, MAROON); + for (int i = 0; i < GetGamepadAxisCount(GAMEPAD_PLAYER1); i++) { DrawText(FormatText("AXIS %i: %.02f", i, GetGamepadAxisMovement(GAMEPAD_PLAYER1, i)), 20, 70 + 20*i, 10, DARKGRAY); } - + if (GetGamepadButtonPressed() != -1) DrawText(FormatText("DETECTED BUTTON: %i", GetGamepadButtonPressed()), 10, 430, 10, RED); else DrawText("DETECTED BUTTON: NONE", 10, 430, 10, GRAY); } else { DrawText("GP1: NOT DETECTED", 10, 10, 10, GRAY); - + DrawTexture(texXboxPad, 0, 0, LIGHTGRAY); } @@ -186,7 +186,7 @@ int main() //-------------------------------------------------------------------------------------- UnloadTexture(texPs3Pad); UnloadTexture(texXboxPad); - + CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/core/core_gestures_detection.c b/examples/core/core_input_gestures.c similarity index 92% rename from examples/core/core_gestures_detection.c rename to examples/core/core_input_gestures.c index 63a1e6bdf..affab3ebb 100644 --- a/examples/core/core_gestures_detection.c +++ b/examples/core/core_input_gestures.c @@ -1,6 +1,6 @@ /******************************************************************************************* * -* raylib [core] example - Gestures Detection +* raylib [core] example - Input Gestures Detection * * This example has been created using raylib 1.4 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) @@ -14,27 +14,27 @@ #define MAX_GESTURE_STRINGS 20 -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; - - InitWindow(screenWidth, screenHeight, "raylib [core] example - gestures detection"); - + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [core] example - input gestures"); + Vector2 touchPosition = { 0, 0 }; Rectangle touchArea = { 220, 10, screenWidth - 230, screenHeight - 20 }; - + int gesturesCount = 0; char gestureStrings[MAX_GESTURE_STRINGS][32]; int currentGesture = GESTURE_NONE; int lastGesture = GESTURE_NONE; - + //SetGesturesEnabled(0b0000000000001001); // Enable only some gestures to be detected - - SetTargetFPS(60); + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop @@ -65,14 +65,14 @@ int main() case GESTURE_PINCH_OUT: strcpy(gestureStrings[gesturesCount], "GESTURE PINCH OUT"); break; default: break; } - + gesturesCount++; - + // Reset gestures strings if (gesturesCount >= MAX_GESTURE_STRINGS) { for (int i = 0; i < MAX_GESTURE_STRINGS; i++) strcpy(gestureStrings[i], "\0"); - + gesturesCount = 0; } } @@ -84,32 +84,32 @@ int main() BeginDrawing(); ClearBackground(RAYWHITE); - + DrawRectangleRec(touchArea, GRAY); DrawRectangle(225, 15, screenWidth - 240, screenHeight - 30, RAYWHITE); - + DrawText("GESTURES TEST AREA", screenWidth - 270, screenHeight - 40, 20, Fade(GRAY, 0.5f)); - + for (int i = 0; i < gesturesCount; i++) { if (i%2 == 0) DrawRectangle(10, 30 + 20*i, 200, 20, Fade(LIGHTGRAY, 0.5f)); else DrawRectangle(10, 30 + 20*i, 200, 20, Fade(LIGHTGRAY, 0.3f)); - + if (i < gesturesCount - 1) DrawText(gestureStrings[i], 35, 36 + 20*i, 10, DARKGRAY); else DrawText(gestureStrings[i], 35, 36 + 20*i, 10, MAROON); } - + DrawRectangleLines(10, 29, 200, screenHeight - 50, GRAY); DrawText("DETECTED GESTURES", 50, 15, 10, GRAY); - + if (currentGesture != GESTURE_NONE) DrawCircleV(touchPosition, 30, MAROON); - + EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization - //-------------------------------------------------------------------------------------- + //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- } \ No newline at end of file diff --git a/examples/core/core_gestures_detection.png b/examples/core/core_input_gestures.png similarity index 100% rename from examples/core/core_gestures_detection.png rename to examples/core/core_input_gestures.png diff --git a/examples/core/core_input_keys.c b/examples/core/core_input_keys.c index 69384fd9e..bbb71ee38 100644 --- a/examples/core/core_input_keys.c +++ b/examples/core/core_input_keys.c @@ -11,18 +11,18 @@ #include "raylib.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - keyboard input"); Vector2 ballPosition = { (float)screenWidth/2, (float)screenHeight/2 }; - SetTargetFPS(60); // Set target frames-per-second + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop diff --git a/examples/core/core_input_mouse.c b/examples/core/core_input_mouse.c index 24d2dfcd4..ad205aed8 100644 --- a/examples/core/core_input_mouse.c +++ b/examples/core/core_input_mouse.c @@ -11,19 +11,19 @@ #include "raylib.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - mouse input"); Vector2 ballPosition = { -100.0f, -100.0f }; Color ballColor = DARKBLUE; - - SetTargetFPS(60); + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //--------------------------------------------------------------------------------------- // Main game loop @@ -32,7 +32,7 @@ int main() // Update //---------------------------------------------------------------------------------- ballPosition = GetMousePosition(); - + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) ballColor = MAROON; else if (IsMouseButtonPressed(MOUSE_MIDDLE_BUTTON)) ballColor = LIME; else if (IsMouseButtonPressed(MOUSE_RIGHT_BUTTON)) ballColor = DARKBLUE; diff --git a/examples/core/core_mouse_wheel.c b/examples/core/core_input_mouse_wheel.c similarity index 89% rename from examples/core/core_mouse_wheel.c rename to examples/core/core_input_mouse_wheel.c index 6a5252ee5..7c3e2a16a 100644 --- a/examples/core/core_mouse_wheel.c +++ b/examples/core/core_input_mouse_wheel.c @@ -1,6 +1,6 @@ /******************************************************************************************* * -* raylib [core] examples - Mouse wheel +* raylib [core] examples - Mouse wheel input * * This test has been created using raylib 1.1 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) @@ -11,19 +11,19 @@ #include "raylib.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; - InitWindow(screenWidth, screenHeight, "raylib [core] example - mouse wheel"); + InitWindow(screenWidth, screenHeight, "raylib [core] example - input mouse wheel"); int boxPositionY = screenHeight/2 - 40; int scrollSpeed = 4; // Scrolling speed in pixels - SetTargetFPS(60); + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop diff --git a/examples/core/core_mouse_wheel.png b/examples/core/core_input_mouse_wheel.png similarity index 100% rename from examples/core/core_mouse_wheel.png rename to examples/core/core_input_mouse_wheel.png diff --git a/examples/core/core_input_multitouch.c b/examples/core/core_input_multitouch.c index ef8fa7ae2..5fbb086c4 100644 --- a/examples/core/core_input_multitouch.c +++ b/examples/core/core_input_multitouch.c @@ -5,37 +5,39 @@ * This example has been created using raylib 2.1 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * -* Copyright (c) 2014-2019 Berni and Ramon Santamaria (@raysan5) +* Example contributed by Berni (@Berni8k) and reviewed by Ramon Santamaria (@raysan5) +* +* Copyright (c) 2019 Berni (@Berni8k) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ #include "raylib.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - input multitouch"); Vector2 ballPosition = { -100.0f, -100.0f }; Color ballColor = BEIGE; - - int touchCounter = 0; - Vector2 touchPosition; - SetTargetFPS(60); + int touchCounter = 0; + Vector2 touchPosition = { 0.0f }; + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //--------------------------------------------------------------------------------------- - + // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- ballPosition = GetMousePosition(); - + ballColor = BEIGE; if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) ballColor = MAROON; @@ -45,7 +47,7 @@ int main() if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) touchCounter = 10; if (IsMouseButtonPressed(MOUSE_MIDDLE_BUTTON)) touchCounter = 10; if (IsMouseButtonPressed(MOUSE_RIGHT_BUTTON)) touchCounter = 10; - + if (touchCounter > 0) touchCounter--; //---------------------------------------------------------------------------------- @@ -57,15 +59,15 @@ int main() // Multitouch for (int i = 0; i < MAX_TOUCH_POINTS; ++i) - { + { touchPosition = GetTouchPosition(i); // Get the touch point - + if ((touchPosition.x >= 0) && (touchPosition.y >= 0)) // Make sure point is not (-1,-1) as this means there is no touch for it { // Draw circle and touch index number DrawCircleV(touchPosition, 34, ORANGE); DrawText(FormatText("%d", i), touchPosition.x - 10, touchPosition.y - 70, 40, BLACK); - } + } } // Draw the normal mouse location diff --git a/examples/core/core_loading_thread.c b/examples/core/core_loading_thread.c index 4ffc9d0bf..773ad2eae 100644 --- a/examples/core/core_loading_thread.c +++ b/examples/core/core_loading_thread.c @@ -2,7 +2,7 @@ * * raylib example - loading thread * -* NOTE: This example requires linking with pthreads library, +* NOTE: This example requires linking with pthreads library, * on MinGW, it can be accomplished passing -static parameter to compiler * * This example has been created using raylib 2.5 (www.raylib.com) @@ -15,30 +15,33 @@ #include "raylib.h" #include "pthread.h" // POSIX style threads management -#include -#include // Required for clock() function +#include // C11 atomic data types +#include // Required for: clock() + +// Using C11 atomics for synchronization +// NOTE: A plain bool (or any plain data type for that matter) can't be used for inter-thread synchronization static atomic_bool dataLoaded = ATOMIC_VAR_INIT(false); // Data Loaded completion indicator static void *LoadDataThread(void *arg); // Loading data thread function declaration static int dataProgress = 0; // Data progress accumulator -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - loading thread"); - + pthread_t threadId; // Loading data thread id enum { STATE_WAITING, STATE_LOADING, STATE_FINISHED } state = STATE_WAITING; int framesCounter = 0; - SetTargetFPS(60); + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop @@ -48,33 +51,37 @@ int main() //---------------------------------------------------------------------------------- switch (state) { - case STATE_WAITING: - if (IsKeyPressed(KEY_ENTER)) + case STATE_WAITING: { - int error = pthread_create(&threadId, NULL, &LoadDataThread, NULL); - if (error != 0) TraceLog(LOG_ERROR, "Error creating loading thread"); - else TraceLog(LOG_INFO, "Loading thread initialized successfully"); + if (IsKeyPressed(KEY_ENTER)) + { + int error = pthread_create(&threadId, NULL, &LoadDataThread, NULL); + if (error != 0) TraceLog(LOG_ERROR, "Error creating loading thread"); + else TraceLog(LOG_INFO, "Loading thread initialized successfully"); - state = STATE_LOADING; - } - break; - case STATE_LOADING: - framesCounter++; - if (atomic_load(&dataLoaded)) + state = STATE_LOADING; + } + } break; + case STATE_LOADING: { - framesCounter = 0; - state = STATE_FINISHED; - } - break; - case STATE_FINISHED: - if (IsKeyPressed(KEY_ENTER)) + framesCounter++; + if (atomic_load(&dataLoaded)) + { + framesCounter = 0; + state = STATE_FINISHED; + } + } break; + case STATE_FINISHED: { - // Reset everything to launch again - atomic_store(&dataLoaded, false); - dataProgress = 0; - state = STATE_WAITING; - } - break; + if (IsKeyPressed(KEY_ENTER)) + { + // Reset everything to launch again + atomic_store(&dataLoaded, false); + dataProgress = 0; + state = STATE_WAITING; + } + } break; + default: break; } //---------------------------------------------------------------------------------- @@ -83,22 +90,25 @@ int main() BeginDrawing(); ClearBackground(RAYWHITE); - - switch(state) { - case STATE_WAITING: - DrawText("PRESS ENTER to START LOADING DATA", 150, 170, 20, DARKGRAY); - break; - case STATE_LOADING: - DrawRectangle(150, 200, dataProgress, 60, SKYBLUE); - if ((framesCounter/15)%2) - DrawText("LOADING DATA...", 240, 210, 40, DARKBLUE); - break; - case STATE_FINISHED: - DrawRectangle(150, 200, 500, 60, LIME); - DrawText("DATA LOADED!", 250, 210, 40, GREEN); - break; + + switch (state) + { + case STATE_WAITING: DrawText("PRESS ENTER to START LOADING DATA", 150, 170, 20, DARKGRAY); break; + case STATE_LOADING: + { + DrawRectangle(150, 200, dataProgress, 60, SKYBLUE); + if ((framesCounter/15)%2) DrawText("LOADING DATA...", 240, 210, 40, DARKBLUE); + + } break; + case STATE_FINISHED: + { + DrawRectangle(150, 200, 500, 60, LIME); + DrawText("DATA LOADED!", 250, 210, 40, GREEN); + + } break; + default: break; } - + DrawRectangleLines(150, 200, 500, 60, DARKGRAY); EndDrawing(); @@ -120,11 +130,11 @@ static void *LoadDataThread(void *arg) clock_t prevTime = clock(); // Previous time // We simulate data loading with a time counter for 5 seconds - while (timeCounter < 5000) + while (timeCounter < 5000) { clock_t currentTime = clock() - prevTime; timeCounter = currentTime*1000/CLOCKS_PER_SEC; - + // We accumulate time over a global variable to be used in // main thread as a progress bar dataProgress = timeCounter/10; diff --git a/examples/core/core_random_values.c b/examples/core/core_random_values.c index 06e550dd3..52dabe0ac 100644 --- a/examples/core/core_random_values.c +++ b/examples/core/core_random_values.c @@ -11,20 +11,20 @@ #include "raylib.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - generate random values"); - int framesCounter = 0; // Variable used to count frames + int framesCounter = 0; // Variable used to count frames int randValue = GetRandomValue(-8, 5); // Get a random integer number between -8 and 5 (both included) - SetTargetFPS(60); // Set our game to run at 60 frames-per-second + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop diff --git a/examples/core/core_scissor_test.c b/examples/core/core_scissor_test.c new file mode 100644 index 000000000..55221330e --- /dev/null +++ b/examples/core/core_scissor_test.c @@ -0,0 +1,71 @@ +/******************************************************************************************* +* +* raylib [core] example - Scissor test +* +* This example has been created using raylib 2.5 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Example contributed by Chris Dill (@MysteriousSpace) and reviewed by Ramon Santamaria (@raysan5) +* +* Copyright (c) 2019 Chris Dill (@MysteriousSpace) +* +********************************************************************************************/ + +#include "raylib.h" + +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [core] example - scissor test"); + + Rectangle scissorArea = { 0, 0, 300, 300 }; + bool scissorMode = true; + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + if (IsKeyPressed(KEY_S)) scissorMode = !scissorMode; + + // Centre the scissor area around the mouse position + scissorArea.x = GetMouseX() - scissorArea.width/2; + scissorArea.y = GetMouseY() - scissorArea.height/2; + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + if (scissorMode) BeginScissorMode(scissorArea.x, scissorArea.y, scissorArea.width, scissorArea.height); + + // Draw full screen rectangle and some text + // NOTE: Only part defined by scissor area will be rendered + DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), RED); + DrawText("Move the mouse around to reveal this text!", 190, 200, 20, LIGHTGRAY); + + if (scissorMode) EndScissorMode(); + + DrawRectangleLinesEx(scissorArea, 1, BLACK); + DrawText("Press S to toggle scissor test", 10, 10, 20, BLACK); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} diff --git a/examples/core/core_scissor_test.png b/examples/core/core_scissor_test.png new file mode 100644 index 000000000..194872bb7 Binary files /dev/null and b/examples/core/core_scissor_test.png differ diff --git a/examples/core/core_storage_values.c b/examples/core/core_storage_values.c index 43f0882fd..fbbbc5284 100644 --- a/examples/core/core_storage_values.c +++ b/examples/core/core_storage_values.c @@ -14,21 +14,20 @@ // NOTE: Storage positions must start with 0, directly related to file memory layout typedef enum { STORAGE_SCORE = 0, STORAGE_HISCORE } StorageData; -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - storage save/load values"); - + int score = 0; int hiscore = 0; - int framesCounter = 0; - - SetTargetFPS(60); + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop @@ -41,7 +40,7 @@ int main() score = GetRandomValue(1000, 2000); hiscore = GetRandomValue(2000, 4000); } - + if (IsKeyPressed(KEY_ENTER)) { StorageSaveValue(STORAGE_SCORE, score); @@ -53,7 +52,7 @@ int main() score = StorageLoadValue(STORAGE_SCORE); hiscore = StorageLoadValue(STORAGE_HISCORE); } - + framesCounter++; //---------------------------------------------------------------------------------- @@ -65,9 +64,9 @@ int main() DrawText(FormatText("SCORE: %i", score), 280, 130, 40, MAROON); DrawText(FormatText("HI-SCORE: %i", hiscore), 210, 200, 50, BLACK); - + DrawText(FormatText("frames: %i", framesCounter), 10, 10, 20, LIME); - + DrawText("Press R to generate random numbers", 220, 40, 20, LIGHTGRAY); DrawText("Press ENTER to SAVE values", 250, 310, 20, LIGHTGRAY); DrawText("Press SPACE to LOAD values", 252, 350, 20, LIGHTGRAY); @@ -77,7 +76,7 @@ int main() } // De-Initialization - //-------------------------------------------------------------------------------------- + //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/core/core_vr_simulator.c b/examples/core/core_vr_simulator.c index 65054b732..76e22b1ab 100644 --- a/examples/core/core_vr_simulator.c +++ b/examples/core/core_vr_simulator.c @@ -11,22 +11,29 @@ #include "raylib.h" -int main() +#if defined(PLATFORM_DESKTOP) + #define GLSL_VERSION 330 +#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB + #define GLSL_VERSION 100 +#endif + +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 1080; - int screenHeight = 600; - + const int screenWidth = 800; + const int screenHeight = 450; + // NOTE: screenWidth/screenHeight should match VR device aspect ratio - + + SetConfigFlags(FLAG_MSAA_4X_HINT); InitWindow(screenWidth, screenHeight, "raylib [core] example - vr simulator"); // Init VR simulator (Oculus Rift CV1 parameters) InitVrSimulator(); VrDeviceInfo hmd = { 0 }; // VR device parameters (head-mounted-device) - + // Oculus Rift CV1 parameters for simulator hmd.hResolution = 2160; // HMD horizontal resolution in pixels hmd.vResolution = 1200; // HMD vertical resolution in pixels @@ -36,7 +43,7 @@ int main() hmd.eyeToScreenDistance = 0.041f; // HMD distance between eye and display in meters hmd.lensSeparationDistance = 0.07f; // HMD lens separation distance in meters hmd.interpupillaryDistance = 0.07f; // HMD IPD (distance between pupils) in meters - + // NOTE: CV1 uses a Fresnel-hybrid-asymmetric lenses with specific distortion compute shaders. // Following parameters are an approximation to distortion stereo rendering but results differ from actual device. hmd.lensDistortionValues[0] = 1.0f; // HMD lens distortion constant parameter 0 @@ -47,24 +54,24 @@ int main() hmd.chromaAbCorrection[1] = -0.004f; // HMD chromatic aberration correction parameter 1 hmd.chromaAbCorrection[2] = 1.014f; // HMD chromatic aberration correction parameter 2 hmd.chromaAbCorrection[3] = 0.0f; // HMD chromatic aberration correction parameter 3 - + // Distortion shader (uses device lens distortion and chroma) - Shader distortion = LoadShader(0, "resources/distortion.fs"); - + Shader distortion = LoadShader(0, FormatText("resources/distortion%i.fs", GLSL_VERSION)); + SetVrConfiguration(hmd, distortion); // Set Vr device parameters for stereo rendering - + // Define the camera to look into our 3d world - Camera camera; + Camera camera = { 0 }; camera.position = (Vector3){ 5.0f, 2.0f, 5.0f }; // Camera position camera.target = (Vector3){ 0.0f, 2.0f, 0.0f }; // Camera looking at point camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target) camera.fovy = 60.0f; // Camera field-of-view Y camera.type = CAMERA_PERSPECTIVE; // Camera type - + Vector3 cubePosition = { 0.0f, 0.0f, 0.0f }; - + SetCameraMode(camera, CAMERA_FIRST_PERSON); // Set first person camera mode - + SetTargetFPS(90); // Set our game to run at 90 frames-per-second //-------------------------------------------------------------------------------------- @@ -83,7 +90,7 @@ int main() BeginDrawing(); ClearBackground(RAYWHITE); - + BeginVrDrawing(); BeginMode3D(camera); @@ -94,7 +101,7 @@ int main() DrawGrid(40, 1.0f); EndMode3D(); - + EndVrDrawing(); DrawFPS(10, 10); diff --git a/examples/core/core_window_scale_letterbox.c b/examples/core/core_window_letterbox.c similarity index 81% rename from examples/core/core_window_scale_letterbox.c rename to examples/core/core_window_letterbox.c index ea4a375a2..fe67fe0a0 100644 --- a/examples/core/core_window_scale_letterbox.c +++ b/examples/core/core_window_letterbox.c @@ -5,7 +5,9 @@ * This example has been created using raylib 2.5 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * -* Copyright (c) 2019 Anata and Ramon Santamaria (@raysan5) +* Example contributed by Anata (@anatagawa) and reviewed by Ramon Santamaria (@raysan5) +* +* Copyright (c) 2019 Anata (@anatagawa) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ @@ -14,7 +16,7 @@ #define max(a, b) ((a)>(b)? (a) : (b)) #define min(a, b) ((a)<(b)? (a) : (b)) -int main() +int main(void) { const int windowWidth = 800; const int windowHeight = 450; @@ -26,63 +28,63 @@ int main() int gameScreenWidth = 640; int gameScreenHeight = 480; - - // Render texture initialization + + // Render texture initialization, used to hold the rendering result so we can easily resize it RenderTexture2D target = LoadRenderTexture(gameScreenWidth, gameScreenHeight); SetTextureFilter(target.texture, FILTER_BILINEAR); // Texture scale filter to use - + Color colors[10] = { 0 }; for (int i = 0; i < 10; i++) colors[i] = (Color){ GetRandomValue(100, 250), GetRandomValue(50, 150), GetRandomValue(10, 100), 255 }; - - SetTargetFPS(60); + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- - + // Main game loop - while( !WindowShouldClose() ) // Detect window close button or ESC key + while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- // Compute required framebuffer scaling float scale = min((float)GetScreenWidth()/gameScreenWidth, (float)GetScreenHeight()/gameScreenHeight); - - if (IsKeyPressed(KEY_SPACE)) + + if (IsKeyPressed(KEY_SPACE)) { // Recalculate random colors for the bars for (int i = 0; i < 10; i++) colors[i] = (Color){ GetRandomValue(100, 250), GetRandomValue(50, 150), GetRandomValue(10, 100), 255 }; } //---------------------------------------------------------------------------------- - + // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(BLACK); - - // Draw everything in the render texture + + // Draw everything in the render texture, note this will not be rendered on screen, yet BeginTextureMode(target); - + ClearBackground(RAYWHITE); // Clear render texture background color - + for (int i = 0; i < 10; i++) DrawRectangle(0, (gameScreenHeight/10)*i, gameScreenWidth, gameScreenHeight/10, colors[i]); - - DrawText("You can resize the window,\nand see the screen scaling!", 10, 25, 20, WHITE); - + + DrawText("If executed inside a window,\nyou can resize the window,\nand see the screen scaling!", 10, 25, 20, WHITE); + EndTextureMode(); // Draw RenderTexture2D to window, properly scaled DrawTexturePro(target.texture, (Rectangle){ 0.0f, 0.0f, (float)target.texture.width, (float)-target.texture.height }, - (Rectangle){ (GetScreenWidth() - ((float)gameScreenWidth*scale))*0.5, (GetScreenHeight() - ((float)gameScreenHeight*scale))*0.5, + (Rectangle){ (GetScreenWidth() - ((float)gameScreenWidth*scale))*0.5, (GetScreenHeight() - ((float)gameScreenHeight*scale))*0.5, (float)gameScreenWidth*scale, (float)gameScreenHeight*scale }, (Vector2){ 0, 0 }, 0.0f, WHITE); - + EndDrawing(); //-------------------------------------------------------------------------------------- } - + // De-Initialization //-------------------------------------------------------------------------------------- UnloadRenderTexture(target); // Unload render texture - + CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- - + return 0; } diff --git a/examples/core/core_window_scale_letterbox.png b/examples/core/core_window_letterbox.png similarity index 100% rename from examples/core/core_window_scale_letterbox.png rename to examples/core/core_window_letterbox.png diff --git a/examples/core/core_world_screen.c b/examples/core/core_world_screen.c index 460f6b85e..31d3653db 100644 --- a/examples/core/core_world_screen.c +++ b/examples/core/core_world_screen.c @@ -11,12 +11,12 @@ #include "raylib.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d camera free"); @@ -29,9 +29,8 @@ int main() camera.type = CAMERA_PERSPECTIVE; Vector3 cubePosition = { 0.0f, 0.0f, 0.0f }; - - Vector2 cubeScreenPosition; - + Vector2 cubeScreenPosition = { 0.0f, 0.0f }; + SetCameraMode(camera, CAMERA_FREE); // Set a free camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second @@ -43,7 +42,7 @@ int main() // Update //---------------------------------------------------------------------------------- UpdateCamera(&camera); // Update camera - + // Calculate cube screen space position (with a little offset to be in top) cubeScreenPosition = GetWorldToScreen((Vector3){cubePosition.x, cubePosition.y + 2.5f, cubePosition.z}, camera); //---------------------------------------------------------------------------------- @@ -62,7 +61,7 @@ int main() DrawGrid(10, 1.0f); EndMode3D(); - + DrawText("Enemy: 100 / 100", cubeScreenPosition.x - MeasureText("Enemy: 100 / 100", 20) / 2, cubeScreenPosition.y, 20, BLACK); DrawText("Text is always on top of the cube", (screenWidth - MeasureText("Text is always on top of the cube", 20)) / 2, 25, 20, GRAY); diff --git a/examples/core/resources/distortion100.fs b/examples/core/resources/distortion100.fs new file mode 100644 index 000000000..112cbcb5c --- /dev/null +++ b/examples/core/resources/distortion100.fs @@ -0,0 +1,52 @@ +#version 100 + +precision mediump float; + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// NOTE: Add here your custom variables +uniform vec2 leftLensCenter; +uniform vec2 rightLensCenter; +uniform vec2 leftScreenCenter; +uniform vec2 rightScreenCenter; +uniform vec2 scale; +uniform vec2 scaleIn; +uniform vec4 hmdWarpParam; +uniform vec4 chromaAbParam; + +void main() +{ + // Compute lens distortion + vec2 lensCenter = fragTexCoord.x < 0.5? leftLensCenter : rightLensCenter; + vec2 screenCenter = fragTexCoord.x < 0.5? leftScreenCenter : rightScreenCenter; + vec2 theta = (fragTexCoord - lensCenter)*scaleIn; + float rSq = theta.x*theta.x + theta.y*theta.y; + vec2 theta1 = theta*(hmdWarpParam.x + hmdWarpParam.y*rSq + hmdWarpParam.z*rSq*rSq + hmdWarpParam.w*rSq*rSq*rSq); + vec2 thetaBlue = theta1*(chromaAbParam.z + chromaAbParam.w*rSq); + vec2 tcBlue = lensCenter + scale*thetaBlue; + + if (any(bvec2(clamp(tcBlue, screenCenter - vec2(0.25, 0.5), screenCenter + vec2(0.25, 0.5)) - tcBlue))) + { + // Set black fragment for everything outside the lens border + gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); + } + else + { + // Compute color chroma aberration + float blue = texture2D(texture0, tcBlue).b; + vec2 tcGreen = lensCenter + scale*theta1; + float green = texture2D(texture0, tcGreen).g; + + vec2 thetaRed = theta1*(chromaAbParam.x + chromaAbParam.y*rSq); + vec2 tcRed = lensCenter + scale*thetaRed; + + float red = texture2D(texture0, tcRed).r; + gl_FragColor = vec4(red, green, blue, 1.0); + } +} diff --git a/examples/core/resources/distortion.fs b/examples/core/resources/distortion330.fs similarity index 83% rename from examples/core/resources/distortion.fs rename to examples/core/resources/distortion330.fs index 207a0affb..15d03ccf6 100644 --- a/examples/core/resources/distortion.fs +++ b/examples/core/resources/distortion330.fs @@ -1,10 +1,17 @@ #version 330 +// Input vertex attributes (from vertex shader) in vec2 fragTexCoord; in vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// Output fragment color out vec4 finalColor; -uniform sampler2D texture0; +// NOTE: Add here your custom variables uniform vec2 leftLensCenter = vec2(0.288, 0.5); uniform vec2 rightLensCenter = vec2(0.712, 0.5); uniform vec2 leftScreenCenter = vec2(0.25, 0.5); @@ -16,6 +23,7 @@ uniform vec4 chromaAbParam = vec4(0.996, -0.004, 1.014, 0.0); void main() { + // Compute lens distortion vec2 lensCenter = fragTexCoord.x < 0.5? leftLensCenter : rightLensCenter; vec2 screenCenter = fragTexCoord.x < 0.5? leftScreenCenter : rightScreenCenter; vec2 theta = (fragTexCoord - lensCenter)*scaleIn; @@ -26,10 +34,12 @@ void main() if (any(bvec2(clamp(tcBlue, screenCenter - vec2(0.25, 0.5), screenCenter + vec2(0.25, 0.5)) - tcBlue))) { + // Set black fragment for everything outside the lens border finalColor = vec4(0.0, 0.0, 0.0, 1.0); } else { + // Compute color chroma aberration float blue = texture(texture0, tcBlue).b; vec2 tcGreen = lensCenter + scale*theta1; float green = texture(texture0, tcGreen).g; @@ -40,4 +50,4 @@ void main() float red = texture(texture0, tcRed).r; finalColor = vec4(red, green, blue, 1.0); } -}; +} diff --git a/examples/models/models_animation.c b/examples/models/models_animation.c index a75241b37..2aa321cf7 100644 --- a/examples/models/models_animation.c +++ b/examples/models/models_animation.c @@ -5,18 +5,27 @@ * This example has been created using raylib 2.5 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * -* Copyright (c) 2019 Ramon Santamaria (@raysan5) and @culacant +* Example contributed by Culacant (@culacant) and reviewed by Ramon Santamaria (@raysan5) +* +* Copyright (c) 2019 Culacant (@culacant) and Ramon Santamaria (@raysan5) +* +******************************************************************************************** +* +* To export a model from blender, make sure it is not posed, the vertices need to be in the +* same position as they would be in edit mode. +* and that the scale of your models is set to 0. Scaling can be done from the export menu. * ********************************************************************************************/ +#include #include "raylib.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [models] example - model animation"); @@ -32,7 +41,7 @@ int main() Model model = LoadModel("resources/guy/guy.iqm"); // Load the animated model mesh and basic data Texture2D texture = LoadTexture("resources/guy/guytex.png"); // Load model texture and set material SetMaterialTexture(&model.materials[0], MAP_DIFFUSE, texture); // Set model material map texture - + Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position // Load animation data @@ -89,9 +98,12 @@ int main() // De-Initialization //-------------------------------------------------------------------------------------- + UnloadTexture(texture); // Unload texture + // Unload model animations data for (int i = 0; i < animsCount; i++) UnloadModelAnimation(anims[i]); - + RL_FREE(anims); + UnloadModel(model); // Unload model CloseWindow(); // Close window and OpenGL context diff --git a/examples/models/models_animation.png b/examples/models/models_animation.png new file mode 100644 index 000000000..57e39dd3e Binary files /dev/null and b/examples/models/models_animation.png differ diff --git a/examples/models/models_billboard.c b/examples/models/models_billboard.c index 596557146..597e9a609 100644 --- a/examples/models/models_billboard.c +++ b/examples/models/models_billboard.c @@ -11,12 +11,12 @@ #include "raylib.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [models] example - drawing billboards"); @@ -27,10 +27,10 @@ int main() camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; camera.fovy = 45.0f; camera.type = CAMERA_PERSPECTIVE; - + Texture2D bill = LoadTexture("resources/billboard.png"); // Our texture billboard Vector3 billPosition = { 0.0f, 2.0f, 0.0f }; // Position where draw billboard - + SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second @@ -51,11 +51,11 @@ int main() ClearBackground(RAYWHITE); BeginMode3D(camera); - + DrawGrid(10, 1.0f); // Draw a grid - + DrawBillboard(camera, bill, billPosition, 2.0f, WHITE); - + EndMode3D(); DrawFPS(10, 10); diff --git a/examples/models/models_box_collisions.c b/examples/models/models_box_collisions.c index 41f6056c0..7a937ea7e 100644 --- a/examples/models/models_box_collisions.c +++ b/examples/models/models_box_collisions.c @@ -11,31 +11,31 @@ #include "raylib.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [models] example - box collisions"); // Define the camera to look into our 3d world - Camera camera = {{ 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 }; - + Camera camera = { { 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 }; + Vector3 playerPosition = { 0.0f, 1.0f, 2.0f }; Vector3 playerSize = { 1.0f, 2.0f, 1.0f }; Color playerColor = GREEN; - + Vector3 enemyBoxPos = { -4.0f, 1.0f, 0.0f }; Vector3 enemyBoxSize = { 2.0f, 2.0f, 2.0f }; - + Vector3 enemySpherePos = { 4.0f, 0.0f, 0.0f }; float enemySphereSize = 1.5f; - + bool collision = false; - SetTargetFPS(60); // Set our game to run at 60 frames-per-second + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop @@ -43,40 +43,40 @@ int main() { // Update //---------------------------------------------------------------------------------- - + // Move player if (IsKeyDown(KEY_RIGHT)) playerPosition.x += 0.2f; else if (IsKeyDown(KEY_LEFT)) playerPosition.x -= 0.2f; else if (IsKeyDown(KEY_DOWN)) playerPosition.z += 0.2f; else if (IsKeyDown(KEY_UP)) playerPosition.z -= 0.2f; - + collision = false; - + // Check collisions player vs enemy-box if (CheckCollisionBoxes( - (BoundingBox){(Vector3){ playerPosition.x - playerSize.x/2, - playerPosition.y - playerSize.y/2, - playerPosition.z - playerSize.z/2 }, + (BoundingBox){(Vector3){ playerPosition.x - playerSize.x/2, + playerPosition.y - playerSize.y/2, + playerPosition.z - playerSize.z/2 }, (Vector3){ playerPosition.x + playerSize.x/2, - playerPosition.y + playerSize.y/2, + playerPosition.y + playerSize.y/2, playerPosition.z + playerSize.z/2 }}, - (BoundingBox){(Vector3){ enemyBoxPos.x - enemyBoxSize.x/2, - enemyBoxPos.y - enemyBoxSize.y/2, - enemyBoxPos.z - enemyBoxSize.z/2 }, + (BoundingBox){(Vector3){ enemyBoxPos.x - enemyBoxSize.x/2, + enemyBoxPos.y - enemyBoxSize.y/2, + enemyBoxPos.z - enemyBoxSize.z/2 }, (Vector3){ enemyBoxPos.x + enemyBoxSize.x/2, - enemyBoxPos.y + enemyBoxSize.y/2, + enemyBoxPos.y + enemyBoxSize.y/2, enemyBoxPos.z + enemyBoxSize.z/2 }})) collision = true; - + // Check collisions player vs enemy-sphere if (CheckCollisionBoxSphere( - (BoundingBox){(Vector3){ playerPosition.x - playerSize.x/2, - playerPosition.y - playerSize.y/2, - playerPosition.z - playerSize.z/2 }, + (BoundingBox){(Vector3){ playerPosition.x - playerSize.x/2, + playerPosition.y - playerSize.y/2, + playerPosition.z - playerSize.z/2 }, (Vector3){ playerPosition.x + playerSize.x/2, - playerPosition.y + playerSize.y/2, - playerPosition.z + playerSize.z/2 }}, + playerPosition.y + playerSize.y/2, + playerPosition.z + playerSize.z/2 }}, enemySpherePos, enemySphereSize)) collision = true; - + if (collision) playerColor = RED; else playerColor = GREEN; //---------------------------------------------------------------------------------- @@ -92,18 +92,18 @@ int main() // Draw enemy-box DrawCube(enemyBoxPos, enemyBoxSize.x, enemyBoxSize.y, enemyBoxSize.z, GRAY); DrawCubeWires(enemyBoxPos, enemyBoxSize.x, enemyBoxSize.y, enemyBoxSize.z, DARKGRAY); - + // Draw enemy-sphere DrawSphere(enemySpherePos, enemySphereSize, GRAY); DrawSphereWires(enemySpherePos, enemySphereSize, 16, 16, DARKGRAY); - + // Draw player DrawCubeV(playerPosition, playerSize, playerColor); DrawGrid(10, 1.0f); // Draw a grid EndMode3D(); - + DrawText("Move player with cursors to collide", 220, 40, 20, GRAY); DrawFPS(10, 10); diff --git a/examples/models/models_cubicmap.c b/examples/models/models_cubicmap.c index ac24188e9..f50878459 100644 --- a/examples/models/models_cubicmap.c +++ b/examples/models/models_cubicmap.c @@ -11,32 +11,32 @@ #include "raylib.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [models] example - cubesmap loading and drawing"); // Define the camera to look into our 3d world - Camera camera = {{ 16.0f, 14.0f, 16.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 }; + Camera camera = { { 16.0f, 14.0f, 16.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 }; Image image = LoadImage("resources/cubicmap.png"); // Load cubicmap image (RAM) Texture2D cubicmap = LoadTextureFromImage(image); // Convert image to texture to display (VRAM) - + Mesh mesh = GenMeshCubicmap(image, (Vector3){ 1.0f, 1.0f, 1.0f }); Model model = LoadModelFromMesh(mesh); - + // NOTE: By default each cube is mapped to one part of texture atlas Texture2D texture = LoadTexture("resources/cubicmap_atlas.png"); // Load map texture model.materials[0].maps[MAP_DIFFUSE].texture = texture; // Set map diffuse texture - + Vector3 mapPosition = { -16.0f, 0.0f, -8.0f }; // Set model position UnloadImage(image); // Unload cubesmap image from RAM, already uploaded to VRAM - + SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second @@ -61,10 +61,10 @@ int main() DrawModel(model, mapPosition, 1.0f, WHITE); EndMode3D(); - + DrawTextureEx(cubicmap, (Vector2){ screenWidth - cubicmap.width*4 - 20, 20 }, 0.0f, 4.0f, WHITE); DrawRectangleLines(screenWidth - cubicmap.width*4 - 20, 20, cubicmap.width*4, cubicmap.height*4, GREEN); - + DrawText("cubicmap image used to", 658, 90, 10, GRAY); DrawText("generate map 3d model", 658, 104, 10, GRAY); diff --git a/examples/models/models_first_person_maze.c b/examples/models/models_first_person_maze.c index 093334ba8..07c51b9ad 100644 --- a/examples/models/models_first_person_maze.c +++ b/examples/models/models_first_person_maze.c @@ -13,34 +13,34 @@ #include // Required for: free() -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [models] example - first person maze"); // Define the camera to look into our 3d world - Camera camera = {{ 0.2f, 0.4f, 0.2f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 }; + Camera camera = { { 0.2f, 0.4f, 0.2f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 }; Image imMap = LoadImage("resources/cubicmap.png"); // Load cubicmap image (RAM) Texture2D cubicmap = LoadTextureFromImage(imMap); // Convert image to texture to display (VRAM) Mesh mesh = GenMeshCubicmap(imMap, (Vector3){ 1.0f, 1.0f, 1.0f }); Model model = LoadModelFromMesh(mesh); - + // NOTE: By default each cube is mapped to one part of texture atlas Texture2D texture = LoadTexture("resources/cubicmap_atlas.png"); // Load map texture model.materials[0].maps[MAP_DIFFUSE].texture = texture; // Set map diffuse texture - + // Get map image data to be used for collision detection Color *mapPixels = GetImageData(imMap); UnloadImage(imMap); // Unload image from RAM - + Vector3 mapPosition = { -16.0f, 0.0f, -8.0f }; // Set model position Vector3 playerPosition = camera.position; // Set player position - + SetCameraMode(camera, CAMERA_FIRST_PERSON); // Set camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second @@ -52,23 +52,23 @@ int main() // Update //---------------------------------------------------------------------------------- Vector3 oldCamPos = camera.position; // Store old camera position - + UpdateCamera(&camera); // Update camera - + // Check player collision (we simplify to 2D collision detection) Vector2 playerPos = { camera.position.x, camera.position.z }; float playerRadius = 0.1f; // Collision radius (player is modelled as a cilinder for collision) - + int playerCellX = (int)(playerPos.x - mapPosition.x + 0.5f); int playerCellY = (int)(playerPos.y - mapPosition.z + 0.5f); - + // Out-of-limits security check if (playerCellX < 0) playerCellX = 0; else if (playerCellX >= cubicmap.width) playerCellX = cubicmap.width - 1; - + if (playerCellY < 0) playerCellY = 0; else if (playerCellY >= cubicmap.height) playerCellY = cubicmap.height - 1; - + // Check map collisions using image data and player position // TODO: Improvement: Just check player surrounding cells for collision for (int y = 0; y < cubicmap.height; y++) @@ -76,7 +76,7 @@ int main() for (int x = 0; x < cubicmap.width; x++) { if ((mapPixels[y*cubicmap.width + x].r == 255) && // Collision: white pixel, only check R channel - (CheckCollisionCircleRec(playerPos, playerRadius, + (CheckCollisionCircleRec(playerPos, playerRadius, (Rectangle){ mapPosition.x - 0.5f + x*1.0f, mapPosition.z - 0.5f + y*1.0f, 1.0f, 1.0f }))) { // Collision detected, reset camera position @@ -98,10 +98,10 @@ int main() //DrawCubeV(playerPosition, (Vector3){ 0.2f, 0.4f, 0.2f }, RED); // Draw player EndMode3D(); - + DrawTextureEx(cubicmap, (Vector2){ GetScreenWidth() - cubicmap.width*4 - 20, 20 }, 0.0f, 4.0f, WHITE); DrawRectangleLines(GetScreenWidth() - cubicmap.width*4 - 20, 20, cubicmap.width*4, cubicmap.height*4, GREEN); - + // Draw player position radar DrawRectangle(GetScreenWidth() - cubicmap.width*4 - 20 + playerCellX*4, 20 + playerCellY*4, 4, 4, RED); @@ -114,7 +114,7 @@ int main() // De-Initialization //-------------------------------------------------------------------------------------- free(mapPixels); // Unload color array - + UnloadTexture(cubicmap); // Unload cubicmap texture UnloadTexture(texture); // Unload map texture UnloadModel(model); // Unload map model diff --git a/examples/models/models_geometric_shapes.c b/examples/models/models_geometric_shapes.c index 82ca4c605..39477927c 100644 --- a/examples/models/models_geometric_shapes.c +++ b/examples/models/models_geometric_shapes.c @@ -11,12 +11,12 @@ #include "raylib.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [models] example - geometric shapes"); @@ -28,7 +28,7 @@ int main() camera.fovy = 45.0f; camera.type = CAMERA_PERSPECTIVE; - SetTargetFPS(60); // Set our game to run at 60 frames-per-second + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop diff --git a/examples/models/models_heightmap.c b/examples/models/models_heightmap.c index e0475f182..a2c2e3104 100644 --- a/examples/models/models_heightmap.c +++ b/examples/models/models_heightmap.c @@ -11,21 +11,21 @@ #include "raylib.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [models] example - heightmap loading and drawing"); // Define our custom camera to look into our 3d world - Camera camera = {{ 18.0f, 16.0f, 18.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 }; + Camera camera = { { 18.0f, 16.0f, 18.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 }; Image image = LoadImage("resources/heightmap.png"); // Load heightmap image (RAM) Texture2D texture = LoadTextureFromImage(image); // Convert image to texture (VRAM) - + Mesh mesh = GenMeshHeightmap(image, (Vector3){ 16, 8, 16 }); // Generate heightmap mesh (RAM and VRAM) Model model = LoadModelFromMesh(mesh); // Load model from generated mesh @@ -33,7 +33,7 @@ int main() Vector3 mapPosition = { -8.0f, 0.0f, -8.0f }; // Define model position UnloadImage(image); // Unload heightmap image from RAM, already uploaded to VRAM - + SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second @@ -60,7 +60,7 @@ int main() DrawGrid(20, 1.0f); EndMode3D(); - + DrawTexture(texture, screenWidth - texture.width - 20, 20, WHITE); DrawRectangleLines(screenWidth - texture.width - 20, 20, texture.width, texture.height, GREEN); diff --git a/examples/models/models_loading.c b/examples/models/models_loading.c new file mode 100644 index 000000000..af9c5e390 --- /dev/null +++ b/examples/models/models_loading.c @@ -0,0 +1,142 @@ +/******************************************************************************************* +* +* raylib [models] example - Models loading +* +* raylib supports multiple models file formats: +* +* - OBJ > Text file, must include vertex position-texcoords-normals information, +* if files references some .mtl materials file, it will be loaded (or try to) +* - GLTF > Modern text/binary file format, includes lot of information and it could +* also reference external files, raylib will try loading mesh and materials data +* - IQM > Binary file format including mesh vertex data but also animation data, +* raylib can load .iqm animations. +* +* This example has been created using raylib 2.6 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2014-2019 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [models] example - models loading"); + + // Define the camera to look into our 3d world + Camera camera = { 0 }; + camera.position = (Vector3){ 50.0f, 50.0f, 50.0f }; // Camera position + camera.target = (Vector3){ 0.0f, 10.0f, 0.0f }; // Camera looking at point + camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target) + camera.fovy = 45.0f; // Camera field-of-view Y + camera.type = CAMERA_PERSPECTIVE; // Camera mode type + + Model model = LoadModel("resources/models/castle.obj"); // Load model + Texture2D texture = LoadTexture("resources/models/castle_diffuse.png"); // Load model texture + model.materials[0].maps[MAP_DIFFUSE].texture = texture; // Set map diffuse texture + + Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position + + BoundingBox bounds = MeshBoundingBox(model.meshes[0]); // Set model bounds + + // NOTE: bounds are calculated from the original size of the model, + // if model is scaled on drawing, bounds must be also scaled + + SetCameraMode(camera, CAMERA_FREE); // Set a free camera mode + + bool selected = false; // Selected object flag + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + UpdateCamera(&camera); + + // Load new models/textures on drag&drop + if (IsFileDropped()) + { + int count = 0; + char **droppedFiles = GetDroppedFiles(&count); + + if (count == 1) // Only support one file dropped + { + if (IsFileExtension(droppedFiles[0], ".obj") || + IsFileExtension(droppedFiles[0], ".gltf") || + IsFileExtension(droppedFiles[0], ".iqm")) // Model file formats supported + { + UnloadModel(model); // Unload previous model + model = LoadModel(droppedFiles[0]); // Load new model + model.materials[0].maps[MAP_DIFFUSE].texture = texture; // Set current map diffuse texture + + bounds = MeshBoundingBox(model.meshes[0]); + + // TODO: Move camera position from target enough distance to visualize model properly + } + else if (IsFileExtension(droppedFiles[0], ".png")) // Texture file formats supported + { + // Unload current model texture and load new one + UnloadTexture(texture); + texture = LoadTexture(droppedFiles[0]); + model.materials[0].maps[MAP_DIFFUSE].texture = texture; + } + } + + ClearDroppedFiles(); // Clear internal buffers + } + + // Select model on mouse click + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + // Check collision between ray and box + if (CheckCollisionRayBox(GetMouseRay(GetMousePosition(), camera), bounds)) selected = !selected; + else selected = false; + } + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + BeginMode3D(camera); + + DrawModel(model, position, 1.0f, WHITE); // Draw 3d model with texture + + DrawGrid(20, 10.0f); // Draw a grid + + if (selected) DrawBoundingBox(bounds, GREEN); // Draw selection box + + EndMode3D(); + + DrawText("Drag & drop model to load mesh/texture.", 10, GetScreenHeight() - 20, 10, DARKGRAY); + if (selected) DrawText("MODEL SELECTED", GetScreenWidth() - 110, 10, 10, GREEN); + + DrawText("(c) Castle 3D model by Alberto Cano", screenWidth - 200, screenHeight - 20, 10, GRAY); + + DrawFPS(10, 10); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadTexture(texture); // Unload texture + UnloadModel(model); // Unload model + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} \ No newline at end of file diff --git a/examples/models/models_loading.png b/examples/models/models_loading.png new file mode 100644 index 000000000..8ad8cb195 Binary files /dev/null and b/examples/models/models_loading.png differ diff --git a/examples/models/models_material_pbr.c b/examples/models/models_material_pbr.c index 5c308cfcb..0da741408 100644 --- a/examples/models/models_material_pbr.c +++ b/examples/models/models_material_pbr.c @@ -25,12 +25,12 @@ // PBR material loading static Material LoadMaterialPBR(Color albedo, float metalness, float roughness); -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; SetConfigFlags(FLAG_MSAA_4X_HINT); // Enable Multi Sampling Anti Aliasing 4x (if available) InitWindow(screenWidth, screenHeight, "raylib [models] example - pbr material"); @@ -45,22 +45,21 @@ int main() // Load model and PBR material Model model = LoadModel("resources/pbr/trooper.obj"); - + // Mesh tangents are generated... and uploaded to GPU // NOTE: New VBO for tangents is generated at default location and also binded to mesh VAO MeshTangents(&model.meshes[0]); + UnloadMaterial(model.materials[0]); // get rid of default material model.materials[0] = LoadMaterialPBR((Color){ 255, 255, 255, 255 }, 1.0f, 1.0f); - // Define lights attributes - // NOTE: Shader is passed to every light on creation to define shader bindings internally - Light lights[MAX_LIGHTS] = { - CreateLight(LIGHT_POINT, (Vector3){ LIGHT_DISTANCE, LIGHT_HEIGHT, 0.0f }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 255, 0, 0, 255 }, model.materials[0].shader), - CreateLight(LIGHT_POINT, (Vector3){ 0.0f, LIGHT_HEIGHT, LIGHT_DISTANCE }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 0, 255, 0, 255 }, model.materials[0].shader), - CreateLight(LIGHT_POINT, (Vector3){ -LIGHT_DISTANCE, LIGHT_HEIGHT, 0.0f }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 0, 0, 255, 255 }, model.materials[0].shader), - CreateLight(LIGHT_DIRECTIONAL, (Vector3){ 0.0f, LIGHT_HEIGHT*2.0f, -LIGHT_DISTANCE }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 255, 0, 255, 255 }, model.materials[0].shader) - }; - + // Create lights + // NOTE: Lights are added to an internal lights pool automatically + CreateLight(LIGHT_POINT, (Vector3){ LIGHT_DISTANCE, LIGHT_HEIGHT, 0.0f }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 255, 0, 0, 255 }, model.materials[0].shader); + CreateLight(LIGHT_POINT, (Vector3){ 0.0f, LIGHT_HEIGHT, LIGHT_DISTANCE }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 0, 255, 0, 255 }, model.materials[0].shader); + CreateLight(LIGHT_POINT, (Vector3){ -LIGHT_DISTANCE, LIGHT_HEIGHT, 0.0f }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 0, 0, 255, 255 }, model.materials[0].shader); + CreateLight(LIGHT_DIRECTIONAL, (Vector3){ 0.0f, LIGHT_HEIGHT*2.0f, -LIGHT_DISTANCE }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 255, 0, 255, 255 }, model.materials[0].shader); + SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second @@ -72,7 +71,7 @@ int main() // Update //---------------------------------------------------------------------------------- UpdateCamera(&camera); // Update camera - + // Send to material PBR shader camera view position float cameraPos[3] = { camera.position.x, camera.position.y, camera.position.z }; SetShaderValue(model.materials[0].shader, model.materials[0].shader.locs[LOC_VECTOR_VIEW], cameraPos, UNIFORM_VEC3); @@ -87,7 +86,7 @@ int main() BeginMode3D(camera); DrawModel(model, Vector3Zero(), 1.0f, WHITE); - + DrawGrid(10, 1.0f); EndMode3D(); @@ -100,7 +99,20 @@ int main() // De-Initialization //-------------------------------------------------------------------------------------- - UnloadModel(model); // Unload skybox model + + // Shaders and textures must be unloaded by user, + // they could be in use by other models + UnloadTexture(model.materials[0].maps[MAP_ALBEDO].texture); + UnloadTexture(model.materials[0].maps[MAP_NORMAL].texture); + UnloadTexture(model.materials[0].maps[MAP_METALNESS].texture); + UnloadTexture(model.materials[0].maps[MAP_ROUGHNESS].texture); + UnloadTexture(model.materials[0].maps[MAP_OCCLUSION].texture); + UnloadTexture(model.materials[0].maps[MAP_IRRADIANCE].texture); + UnloadTexture(model.materials[0].maps[MAP_PREFILTER].texture); + UnloadTexture(model.materials[0].maps[MAP_BRDF].texture); + UnloadShader(model.materials[0].shader); + + UnloadModel(model); // Unload model CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- @@ -112,13 +124,14 @@ int main() // NOTE: PBR shader is loaded inside this function static Material LoadMaterialPBR(Color albedo, float metalness, float roughness) { - Material mat = { 0 }; // NOTE: All maps textures are set to { 0 } - - #define PATH_PBR_VS "resources/shaders/pbr.vs" // Path to physically based rendering vertex shader - #define PATH_PBR_FS "resources/shaders/pbr.fs" // Path to physically based rendering fragment shader - - mat.shader = LoadShader(PATH_PBR_VS, PATH_PBR_FS); - + Material mat = LoadMaterialDefault(); // Initialize material to default + +#if defined(PLATFORM_DESKTOP) + mat.shader = LoadShader("resources/shaders/glsl330/pbr.vs", "resources/shaders/glsl330/pbr.fs"); +#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB + mat.shader = LoadShader("resources/shaders/glsl100/pbr.vs", "resources/shaders/glsl100/pbr.fs"); +#endif + // Get required locations points for PBR material // NOTE: Those location names must be available and used in the shader code mat.shader.locs[LOC_MAP_ALBEDO] = GetShaderLocation(mat.shader, "albedo.sampler"); @@ -134,9 +147,9 @@ static Material LoadMaterialPBR(Color albedo, float metalness, float roughness) // Set view matrix location mat.shader.locs[LOC_MATRIX_MODEL] = GetShaderLocation(mat.shader, "matModel"); - mat.shader.locs[LOC_MATRIX_VIEW] = GetShaderLocation(mat.shader, "view"); + //mat.shader.locs[LOC_MATRIX_VIEW] = GetShaderLocation(mat.shader, "view"); mat.shader.locs[LOC_VECTOR_VIEW] = GetShaderLocation(mat.shader, "viewPos"); - + // Set PBR standard maps mat.maps[MAP_ALBEDO].texture = LoadTexture("resources/pbr/trooper_albedo.png"); mat.maps[MAP_NORMAL].texture = LoadTexture("resources/pbr/trooper_normals.png"); @@ -144,23 +157,33 @@ static Material LoadMaterialPBR(Color albedo, float metalness, float roughness) mat.maps[MAP_ROUGHNESS].texture = LoadTexture("resources/pbr/trooper_roughness.png"); mat.maps[MAP_OCCLUSION].texture = LoadTexture("resources/pbr/trooper_ao.png"); - // Set environment maps - #define PATH_CUBEMAP_VS "resources/shaders/cubemap.vs" // Path to equirectangular to cubemap vertex shader - #define PATH_CUBEMAP_FS "resources/shaders/cubemap.fs" // Path to equirectangular to cubemap fragment shader - #define PATH_SKYBOX_VS "resources/shaders/skybox.vs" // Path to skybox vertex shader - #define PATH_IRRADIANCE_FS "resources/shaders/irradiance.fs" // Path to irradiance (GI) calculation fragment shader - #define PATH_PREFILTER_FS "resources/shaders/prefilter.fs" // Path to reflection prefilter calculation fragment shader - #define PATH_BRDF_VS "resources/shaders/brdf.vs" // Path to bidirectional reflectance distribution function vertex shader - #define PATH_BRDF_FS "resources/shaders/brdf.fs" // Path to bidirectional reflectance distribution function fragment shader - - Shader shdrCubemap = LoadShader(PATH_CUBEMAP_VS, PATH_CUBEMAP_FS); - printf("Loaded shader: cubemap\n"); - Shader shdrIrradiance = LoadShader(PATH_SKYBOX_VS, PATH_IRRADIANCE_FS); - printf("Loaded shader: irradiance\n"); - Shader shdrPrefilter = LoadShader(PATH_SKYBOX_VS, PATH_PREFILTER_FS); - printf("Loaded shader: prefilter\n"); - Shader shdrBRDF = LoadShader(PATH_BRDF_VS, PATH_BRDF_FS); - printf("Loaded shader: brdf\n"); + // Load equirectangular to cubemap shader +#if defined(PLATFORM_DESKTOP) + Shader shdrCubemap = LoadShader("resources/shaders/glsl330/cubemap.vs", "resources/shaders/glsl330/cubemap.fs"); +#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB + Shader shdrCubemap = LoadShader("resources/shaders/glsl100/cubemap.vs", "resources/shaders/glsl100/cubemap.fs"); +#endif + + // Load irradiance (GI) calculation shader +#if defined(PLATFORM_DESKTOP) + Shader shdrIrradiance = LoadShader("resources/shaders/glsl330/skybox.vs", "resources/shaders/glsl330/irradiance.fs"); +#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB + Shader shdrIrradiance = LoadShader("resources/shaders/glsl100/skybox.vs", "resources/shaders/glsl100/irradiance.fs"); +#endif + + // Load reflection prefilter calculation shader +#if defined(PLATFORM_DESKTOP) + Shader shdrPrefilter = LoadShader("resources/shaders/glsl330/skybox.vs", "resources/shaders/glsl330/prefilter.fs"); +#else + Shader shdrPrefilter = LoadShader("resources/shaders/glsl100/skybox.vs", "resources/shaders/glsl100/prefilter.fs"); +#endif + + // Load bidirectional reflectance distribution function shader +#if defined(PLATFORM_DESKTOP) + Shader shdrBRDF = LoadShader("resources/shaders/glsl330/brdf.vs", "resources/shaders/glsl330/brdf.fs"); +#else + Shader shdrBRDF = LoadShader("resources/shaders/glsl100/brdf.vs", "resources/shaders/glsl100/brdf.fs"); +#endif // Setup required shader locations SetShaderValue(shdrCubemap, GetShaderLocation(shdrCubemap, "equirectangularMap"), (int[1]){ 0 }, UNIFORM_INT); @@ -174,27 +197,27 @@ static Material LoadMaterialPBR(Color albedo, float metalness, float roughness) mat.maps[MAP_BRDF].texture = GenTextureBRDF(shdrBRDF, BRDF_SIZE); UnloadTexture(cubemap); UnloadTexture(texHDR); - + // Unload already used shaders (to create specific textures) UnloadShader(shdrCubemap); UnloadShader(shdrIrradiance); UnloadShader(shdrPrefilter); UnloadShader(shdrBRDF); - + // Set textures filtering for better quality SetTextureFilter(mat.maps[MAP_ALBEDO].texture, FILTER_BILINEAR); SetTextureFilter(mat.maps[MAP_NORMAL].texture, FILTER_BILINEAR); SetTextureFilter(mat.maps[MAP_METALNESS].texture, FILTER_BILINEAR); SetTextureFilter(mat.maps[MAP_ROUGHNESS].texture, FILTER_BILINEAR); SetTextureFilter(mat.maps[MAP_OCCLUSION].texture, FILTER_BILINEAR); - + // Enable sample usage in shader for assigned textures SetShaderValue(mat.shader, GetShaderLocation(mat.shader, "albedo.useSampler"), (int[1]){ 1 }, UNIFORM_INT); SetShaderValue(mat.shader, GetShaderLocation(mat.shader, "normals.useSampler"), (int[1]){ 1 }, UNIFORM_INT); SetShaderValue(mat.shader, GetShaderLocation(mat.shader, "metalness.useSampler"), (int[1]){ 1 }, UNIFORM_INT); SetShaderValue(mat.shader, GetShaderLocation(mat.shader, "roughness.useSampler"), (int[1]){ 1 }, UNIFORM_INT); SetShaderValue(mat.shader, GetShaderLocation(mat.shader, "occlusion.useSampler"), (int[1]){ 1 }, UNIFORM_INT); - + int renderModeLoc = GetShaderLocation(mat.shader, "renderMode"); SetShaderValue(mat.shader, renderModeLoc, (int[1]){ 0 }, UNIFORM_INT); diff --git a/examples/models/models_mesh_generation.c b/examples/models/models_mesh_generation.c index 2b4b75abe..eaecb2712 100644 --- a/examples/models/models_mesh_generation.c +++ b/examples/models/models_mesh_generation.c @@ -11,24 +11,24 @@ #include "raylib.h" -#define NUM_MODELS 8 // We generate 8 parametric 3d shapes +#define NUM_MODELS 8 // Parametric 3d shapes to generate -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [models] example - mesh generation"); - + // We generate a checked image for texturing Image checked = GenImageChecked(2, 2, 1, 1, RED, GREEN); Texture2D texture = LoadTextureFromImage(checked); UnloadImage(checked); - - Model models[NUM_MODELS]; - + + Model models[NUM_MODELS] = { 0 }; + models[0] = LoadModelFromMesh(GenMeshPlane(2, 2, 5, 5)); models[1] = LoadModelFromMesh(GenMeshCube(2.0f, 1.0f, 2.0f)); models[2] = LoadModelFromMesh(GenMeshSphere(2, 32, 32)); @@ -37,21 +37,21 @@ int main() models[5] = LoadModelFromMesh(GenMeshTorus(0.25f, 4.0f, 16, 32)); models[6] = LoadModelFromMesh(GenMeshKnot(1.0f, 2.0f, 16, 128)); models[7] = LoadModelFromMesh(GenMeshPoly(5, 2.0f)); - + // Set checked texture as default diffuse component for all models material for (int i = 0; i < NUM_MODELS; i++) models[i].materials[0].maps[MAP_DIFFUSE].texture = texture; // Define the camera to look into our 3d world - Camera camera = {{ 5.0f, 5.0f, 5.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 }; + Camera camera = { { 5.0f, 5.0f, 5.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 }; // Model drawing position Vector3 position = { 0.0f, 0.0f, 0.0f }; - + int currentModel = 0; - + SetCameraMode(camera, CAMERA_ORBITAL); // Set a orbital camera mode - SetTargetFPS(60); // Set our game to run at 60 frames-per-second + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop @@ -60,14 +60,14 @@ int main() // Update //---------------------------------------------------------------------------------- UpdateCamera(&camera); // Update internal camera and our camera - + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) { currentModel = (currentModel + 1)%NUM_MODELS; // Cycle between the textures } - + if (IsKeyPressed(KEY_RIGHT)) - { + { currentModel++; if (currentModel >= NUM_MODELS) currentModel = 0; } @@ -91,11 +91,11 @@ int main() DrawGrid(10, 1.0); EndMode3D(); - + DrawRectangle(30, 400, 310, 30, Fade(SKYBLUE, 0.5f)); DrawRectangleLines(30, 400, 310, 30, Fade(DARKBLUE, 0.5f)); DrawText("MOUSE LEFT BUTTON to CYCLE PROCEDURAL MODELS", 40, 410, 10, BLUE); - + switch(currentModel) { case 0: DrawText("PLANE", 680, 10, 20, DARKBLUE); break; @@ -115,11 +115,12 @@ int main() // De-Initialization //-------------------------------------------------------------------------------------- - + UnloadTexture(texture); // Unload texture + // Unload models data (GPU VRAM) for (int i = 0; i < NUM_MODELS; i++) UnloadModel(models[i]); - - CloseWindow(); // Close window and OpenGL context + + CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; diff --git a/examples/models/models_mesh_picking.c b/examples/models/models_mesh_picking.c index 420288290..f600aae84 100644 --- a/examples/models/models_mesh_picking.c +++ b/examples/models/models_mesh_picking.c @@ -5,8 +5,9 @@ * This example has been created using raylib 1.7 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * -* Copyright (c) 2015 Ramon Santamaria (@raysan5) -* Example contributed by Joel Davis (@joeld42) +* Example contributed by Joel Davis (@joeld42) and reviewed by Ramon Santamaria (@raysan5) +* +* Copyright (c) 2017 Joel Davis (@joeld42) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ @@ -15,12 +16,12 @@ #define FLT_MAX 340282346638528859811704183484516925440.0f // Maximum value of a float, from bit pattern 01111111011111111111111111111111 -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [models] example - mesh picking"); @@ -33,22 +34,22 @@ int main() camera.type = CAMERA_PERSPECTIVE; // Camera mode type Ray ray = { 0 }; // Picking ray - + Model tower = LoadModel("resources/models/turret.obj"); // Load OBJ model Texture2D texture = LoadTexture("resources/models/turret_diffuse.png"); // Load model texture tower.materials[0].maps[MAP_DIFFUSE].texture = texture; // Set model diffuse texture - + Vector3 towerPos = { 0.0f, 0.0f, 0.0f }; // Set model position BoundingBox towerBBox = MeshBoundingBox(tower.meshes[0]); // Get mesh bounding box bool hitMeshBBox = false; bool hitTriangle = false; // Test triangle - Vector3 ta = (Vector3){ -25.0, 0.5, 0.0 }; + Vector3 ta = (Vector3){ -25.0, 0.5, 0.0 }; Vector3 tb = (Vector3){ -4.0, 2.5, 1.0 }; Vector3 tc = (Vector3){ -8.0, 6.5, 0.0 }; - Vector3 bary = { 0.0f, 0.0f, 0.0f }; + Vector3 bary = { 0.0f, 0.0f, 0.0f }; SetCameraMode(camera, CAMERA_FREE); // Set a free camera mode @@ -60,7 +61,7 @@ int main() // Update //---------------------------------------------------------------------------------- UpdateCamera(&camera); // Update camera - + // Display information about closest hit RayHitInfo nearestHit = { 0 }; char *hitObjectName = "None"; @@ -70,10 +71,10 @@ int main() // Get ray and test against ground, triangle, and mesh ray = GetMouseRay(GetMousePosition(), camera); - + // Check ray collision aginst ground plane RayHitInfo groundHitInfo = GetCollisionRayGround(ray, 0.0f); - + if ((groundHitInfo.hit) && (groundHitInfo.distance < nearestHit.distance)) { nearestHit = groundHitInfo; @@ -83,8 +84,8 @@ int main() // Check ray collision against test triangle RayHitInfo triHitInfo = GetCollisionRayTriangle(ray, ta, tb, tc); - - if ((triHitInfo.hit) && (triHitInfo.distance < nearestHit.distance)) + + if ((triHitInfo.hit) && (triHitInfo.distance < nearestHit.distance)) { nearestHit = triHitInfo; cursorColor = PURPLE; @@ -92,32 +93,31 @@ int main() bary = Vector3Barycenter(nearestHit.position, ta, tb, tc); hitTriangle = true; - } + } else hitTriangle = false; RayHitInfo meshHitInfo = { 0 }; // Check ray collision against bounding box first, before trying the full ray-mesh test - if (CheckCollisionRayBox(ray, towerBBox)) + if (CheckCollisionRayBox(ray, towerBBox)) { hitMeshBBox = true; - + // Check ray collision against model // NOTE: It considers model.transform matrix! - meshHitInfo = GetCollisionRayModel(ray, &tower); - - if ((meshHitInfo.hit) && (meshHitInfo.distance < nearestHit.distance)) + meshHitInfo = GetCollisionRayModel(ray, tower); + + if ((meshHitInfo.hit) && (meshHitInfo.distance < nearestHit.distance)) { nearestHit = meshHitInfo; cursorColor = ORANGE; hitObjectName = "Mesh"; } - - } - - hitMeshBBox = false; + } + + hitMeshBBox = false; //---------------------------------------------------------------------------------- - + // Draw //---------------------------------------------------------------------------------- BeginDrawing(); @@ -127,10 +127,10 @@ int main() BeginMode3D(camera); // Draw the tower - // WARNING: If scale is different than 1.0f, + // WARNING: If scale is different than 1.0f, // not considered by GetCollisionRayModel() DrawModel(tower, towerPos, 1.0f, WHITE); - + // Draw the test triangle DrawLine3D(ta, tb, PURPLE); DrawLine3D(tb, tc, PURPLE); @@ -140,7 +140,7 @@ int main() if (hitMeshBBox) DrawBoundingBox(towerBBox, LIME); // If we hit something, draw the cursor at the hit point - if (nearestHit.hit) + if (nearestHit.hit) { DrawCube(nearestHit.position, 0.3, 0.3, 0.3, cursorColor); DrawCubeWires(nearestHit.position, 0.3, 0.3, 0.3, RED); @@ -149,40 +149,40 @@ int main() normalEnd.x = nearestHit.position.x + nearestHit.normal.x; normalEnd.y = nearestHit.position.y + nearestHit.normal.y; normalEnd.z = nearestHit.position.z + nearestHit.normal.z; - + DrawLine3D(nearestHit.position, normalEnd, RED); } DrawRay(ray, MAROON); - + DrawGrid(10, 10.0f); EndMode3D(); - + // Draw some debug GUI text DrawText(FormatText("Hit Object: %s", hitObjectName), 10, 50, 10, BLACK); - if (nearestHit.hit) + if (nearestHit.hit) { int ypos = 70; DrawText(FormatText("Distance: %3.2f", nearestHit.distance), 10, ypos, 10, BLACK); - - DrawText(FormatText("Hit Pos: %3.2f %3.2f %3.2f", - nearestHit.position.x, - nearestHit.position.y, + + DrawText(FormatText("Hit Pos: %3.2f %3.2f %3.2f", + nearestHit.position.x, + nearestHit.position.y, nearestHit.position.z), 10, ypos + 15, 10, BLACK); - - DrawText(FormatText("Hit Norm: %3.2f %3.2f %3.2f", - nearestHit.normal.x, - nearestHit.normal.y, + + DrawText(FormatText("Hit Norm: %3.2f %3.2f %3.2f", + nearestHit.normal.x, + nearestHit.normal.y, nearestHit.normal.z), 10, ypos + 30, 10, BLACK); if (hitTriangle) DrawText(FormatText("Barycenter: %3.2f %3.2f %3.2f", bary.x, bary.y, bary.z), 10, ypos + 45, 10, BLACK); } DrawText("Use Mouse to Move Camera", 10, 430, 10, GRAY); - + DrawText("(c) Turret 3D model by Alberto Cano", screenWidth - 200, screenHeight - 20, 10, GRAY); DrawFPS(10, 10); @@ -195,7 +195,7 @@ int main() //-------------------------------------------------------------------------------------- UnloadModel(tower); // Unload model UnloadTexture(texture); // Unload texture - + CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/models/models_obj_loading.c b/examples/models/models_obj_loading.c deleted file mode 100644 index 74e7d08a0..000000000 --- a/examples/models/models_obj_loading.c +++ /dev/null @@ -1,80 +0,0 @@ -/******************************************************************************************* -* -* raylib [models] example - Load and draw a 3d model (OBJ) -* -* This example has been created using raylib 1.3 (www.raylib.com) -* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) -* -* Copyright (c) 2014 Ramon Santamaria (@raysan5) -* -********************************************************************************************/ - -#include "raylib.h" - -int main() -{ - // Initialization - //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; - - InitWindow(screenWidth, screenHeight, "raylib [models] example - obj model loading"); - - // Define the camera to look into our 3d world - Camera camera = { 0 }; - camera.position = (Vector3){ 8.0f, 8.0f, 8.0f }; // Camera position - camera.target = (Vector3){ 0.0f, 2.5f, 0.0f }; // Camera looking at point - camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target) - camera.fovy = 45.0f; // Camera field-of-view Y - camera.type = CAMERA_PERSPECTIVE; // Camera mode type - - Model model = LoadModel("resources/models/castle.obj"); // Load OBJ model - Texture2D texture = LoadTexture("resources/models/castle_diffuse.png"); // Load model texture - model.materials[0].maps[MAP_DIFFUSE].texture = texture; // Set map diffuse texture - Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position - - SetTargetFPS(60); // Set our game to run at 60 frames-per-second - //-------------------------------------------------------------------------------------- - - // Main game loop - while (!WindowShouldClose()) // Detect window close button or ESC key - { - // Update - //---------------------------------------------------------------------------------- - //... - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - BeginDrawing(); - - ClearBackground(RAYWHITE); - - BeginMode3D(camera); - - DrawModel(model, position, 0.2f, WHITE); // Draw 3d model with texture - - DrawGrid(10, 1.0f); // Draw a grid - - DrawGizmo(position); // Draw gizmo - - EndMode3D(); - - DrawText("(c) Castle 3D model by Alberto Cano", screenWidth - 200, screenHeight - 20, 10, GRAY); - - DrawFPS(10, 10); - - EndDrawing(); - //---------------------------------------------------------------------------------- - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - UnloadTexture(texture); // Unload texture - UnloadModel(model); // Unload model - - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} \ No newline at end of file diff --git a/examples/models/models_obj_loading.png b/examples/models/models_obj_loading.png deleted file mode 100644 index 098aa601f..000000000 Binary files a/examples/models/models_obj_loading.png and /dev/null differ diff --git a/examples/models/models_obj_viewer.c b/examples/models/models_obj_viewer.c deleted file mode 100644 index 7d3874416..000000000 --- a/examples/models/models_obj_viewer.c +++ /dev/null @@ -1,127 +0,0 @@ -/******************************************************************************************* -* -* raylib [models] example - OBJ models viewer -* -* This example has been created using raylib 2.0 (www.raylib.com) -* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) -* -* Copyright (c) 2014-2019 Ramon Santamaria (@raysan5) -* -********************************************************************************************/ - -#include "raylib.h" - -#include // Required for: strcpy() - -int main() -{ - // Initialization - //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; - - InitWindow(screenWidth, screenHeight, "raylib example - obj viewer"); - - // Define the camera to look into our 3d world - Camera camera = {{ 30.0f, 30.0f, 30.0f }, { 0.0f, 10.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 }; - - Model model = LoadModel("resources/models/turret.obj"); // Load default model obj - Texture2D texture = LoadTexture("resources/models/turret_diffuse.png"); // Load default model texture - model.materials[0].maps[MAP_DIFFUSE].texture = texture; // Bind texture to model - - Vector3 position = { 0.0, 0.0, 0.0 }; // Set model position - BoundingBox bounds = MeshBoundingBox(model.meshes[0]); // Set model bounds - bool selected = false; // Selected object flag - - SetCameraMode(camera, CAMERA_FREE); // Set a free camera mode - - char objFilename[64] = "turret.obj"; - - SetTargetFPS(60); // Set our game to run at 60 frames-per-second - //-------------------------------------------------------------------------------------- - - // Main game loop - while (!WindowShouldClose()) // Detect window close button or ESC key - { - // Update - //---------------------------------------------------------------------------------- - if (IsFileDropped()) - { - int count = 0; - char **droppedFiles = GetDroppedFiles(&count); - - if (count == 1) - { - if (IsFileExtension(droppedFiles[0], ".obj")) - { - for (int i = 0; i < model.meshCount; i++) UnloadMesh(&model.meshes[i]); - model.meshes = LoadMeshes(droppedFiles[0], &model.meshCount); - bounds = MeshBoundingBox(model.meshes[0]); - } - else if (IsFileExtension(droppedFiles[0], ".png")) - { - UnloadTexture(texture); - texture = LoadTexture(droppedFiles[0]); - model.materials[0].maps[MAP_DIFFUSE].texture = texture; - } - - strcpy(objFilename, GetFileName(droppedFiles[0])); - } - - ClearDroppedFiles(); // Clear internal buffers - } - - UpdateCamera(&camera); - - // Select model on mouse click - if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) - { - // Check collision between ray and box - if (CheckCollisionRayBox(GetMouseRay(GetMousePosition(), camera), bounds)) selected = !selected; - else selected = false; - } - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - BeginDrawing(); - - ClearBackground(RAYWHITE); - - BeginMode3D(camera); - - DrawModel(model, position, 1.0f, WHITE); // Draw 3d model with texture - - DrawGrid(20.0, 10.0); // Draw a grid - - if (selected) DrawBoundingBox(bounds, GREEN); - - EndMode3D(); - - DrawText("Free camera default controls:", 10, 20, 10, DARKGRAY); - DrawText("- Mouse Wheel to Zoom in-out", 20, 40, 10, GRAY); - DrawText("- Mouse Wheel Pressed to Pan", 20, 60, 10, GRAY); - DrawText("- Alt + Mouse Wheel Pressed to Rotate", 20, 80, 10, GRAY); - DrawText("- Alt + Ctrl + Mouse Wheel Pressed for Smooth Zoom", 20, 100, 10, GRAY); - - DrawText("Drag & drop .obj/.png to load mesh/texture.", 10, GetScreenHeight() - 20, 10, DARKGRAY); - DrawText(FormatText("Current file: %s", objFilename), 250, GetScreenHeight() - 20, 10, GRAY); - if (selected) DrawText("MODEL SELECTED", GetScreenWidth() - 110, 10, 10, GREEN); - - DrawText("(c) Turret 3D model by Alberto Cano", screenWidth - 200, screenHeight - 20, 10, GRAY); - - EndDrawing(); - //---------------------------------------------------------------------------------- - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - UnloadModel(model); // Unload model - - ClearDroppedFiles(); // Clear internal buffers - - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} \ No newline at end of file diff --git a/examples/models/models_obj_viewer.png b/examples/models/models_obj_viewer.png deleted file mode 100644 index 6ac707675..000000000 Binary files a/examples/models/models_obj_viewer.png and /dev/null differ diff --git a/examples/models/models_orthographic_projection.c b/examples/models/models_orthographic_projection.c index f9b54b6d0..8c9b5b1c5 100644 --- a/examples/models/models_orthographic_projection.c +++ b/examples/models/models_orthographic_projection.c @@ -1,13 +1,15 @@ /******************************************************************************************* * -* raylib [models] example - Show the difference between perspective and orthographic projection +* raylib [models] example - Show the difference between perspective and orthographic projection * * This program is heavily based on the geometric objects example * -* This example has been created using raylib 1.9.7 (www.raylib.com) +* This example has been created using raylib 2.0 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * -* Copyright (c) 2018 Max Danielsson & Ramon Santamaria (@raysan5) +* Example contributed by Max Danielsson (@autious) and reviewed by Ramon Santamaria (@raysan5) +* +* Copyright (c) 2018 Max Danielsson (@autious) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ @@ -16,19 +18,19 @@ #define FOVY_PERSPECTIVE 45.0f #define WIDTH_ORTHOGRAPHIC 10.0f -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [models] example - geometric shapes"); // Define the camera to look into our 3d world - Camera camera = {{ 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, FOVY_PERSPECTIVE, CAMERA_PERSPECTIVE }; + Camera camera = { { 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, FOVY_PERSPECTIVE, CAMERA_PERSPECTIVE }; - SetTargetFPS(60); // Set our game to run at 60 frames-per-second + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop @@ -36,14 +38,14 @@ int main() { // Update //---------------------------------------------------------------------------------- - if (IsKeyPressed(KEY_SPACE)) + if (IsKeyPressed(KEY_SPACE)) { - if (camera.type == CAMERA_PERSPECTIVE) + if (camera.type == CAMERA_PERSPECTIVE) { camera.fovy = WIDTH_ORTHOGRAPHIC; camera.type = CAMERA_ORTHOGRAPHIC; - } - else + } + else { camera.fovy = FOVY_PERSPECTIVE; camera.type = CAMERA_PERSPECTIVE; diff --git a/examples/models/models_rlgl_full_solar_system.c b/examples/models/models_rlgl_full_solar_system.c new file mode 100644 index 000000000..f8ab7f1de --- /dev/null +++ b/examples/models/models_rlgl_full_solar_system.c @@ -0,0 +1,283 @@ +/******************************************************************************************* +* +* raylib [models] example - rlgl module usage with push/pop matrix transformations +* +* This example uses [rlgl] module funtionality (pseudo-OpenGL 1.1 style coding) +* +* This example has been created using raylib 2.5 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2018 Ramon Santamaria (@raysan5) +* Copyright (c) 2019 Aldrin Martoq (@aldrinmartoq) +* +********************************************************************************************/ + +#include "raylib.h" +#include "rlgl.h" + +#define MAX_BODY_CHILDREN 10 +float rotationSpeed = 0.2; + +// A celestial body that has children bodies orbiting around +typedef struct Body { + const char *label; // label of the body, for ex: moon + float radius; // object radius + float orbitRadius; // orbit average radius + float orbitPeriod; // time the body takes to do a full loop + Color color; // color of the body + float orbitPosition; // current orbit position + Vector2 labelPosition; // label position in screen + struct Body *children[MAX_BODY_CHILDREN]; // children array + int childrenCount; // children count +} Body; + +//------------------------------------------------------------------------------------ +// Module Functions Declaration +//------------------------------------------------------------------------------------ +Body CreateBody(float radius, float orbitRadius, float orbitPeriod, Color color, const char *label); // Initializes a new Body with the given parameters +void AddBodyChildren(Body *parent, Body *children); // Add a children body to the parent body +void DrawSphereBasic(Color color); // Draw sphere without any matrix transformation +void DrawBody(Body *body, Camera *camera); // Draw body and its children, updating labelPosition +void DrawLabels(Body *body); // Draw body label and its children labels + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 1024; + const int screenHeight = 768; + const char *text; + bool gridEnabled = true; + bool helpEnabled = false; + bool labelEnabled = true; + bool cameraParametersEnabled = true; + + InitWindow(screenWidth, screenHeight, "raylib [models] example - rlgl module usage with push/pop matrix transformations"); + + // Define the camera to look into our 3d world + Camera camera = { 0 }; + camera.position = (Vector3){ 8.0f, 8.0f, 8.0f }; + camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; + camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; + camera.fovy = 45.0f; + camera.type = CAMERA_PERSPECTIVE; + + SetCameraMode(camera, CAMERA_FREE); + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + //-------------------------------------------------------------------------------------- + + // Create Bodies + Body sun = CreateBody(0.2, 0.0, 0, GOLD, "sun"); + Body moon = CreateBody(0.05, 0.200, 24, GRAY, "moon"); + Body mercury = CreateBody(0.05, 0.396, 90, GRAY, "mercury"); + Body venus = CreateBody(0.05, 0.723, 210, MAGENTA, "venus"); + Body earth = CreateBody(0.05, 1.000, 365, BLUE, "earth"); + Body mars = CreateBody(0.05, 1.523, 690, RED, "mars"); + Body jupiter = CreateBody(0.05, 5.200, 4260, BROWN, "jupiter"); + Body saturn = CreateBody(0.05, 9.532, 10620, GREEN, "saturn"); + Body uranus = CreateBody(0.05, 19.180, 30270, SKYBLUE, "uranus"); + Body neptune = CreateBody(0.05, 30.056, 59370, PURPLE, "neptune"); + Body pluto = CreateBody(0.05, 39.463, 89310, DARKGREEN, "pluto"); + + AddBodyChildren(&sun, &mercury); + AddBodyChildren(&sun, &venus); + AddBodyChildren(&sun, &earth); + AddBodyChildren(&sun, &mars); + AddBodyChildren(&sun, &jupiter); + AddBodyChildren(&sun, &saturn); + AddBodyChildren(&sun, &uranus); + AddBodyChildren(&sun, &neptune); + AddBodyChildren(&sun, &pluto); + + AddBodyChildren(&earth, &moon); + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + UpdateCamera(&camera); + + if (IsKeyPressed(KEY_G)) { + gridEnabled = !gridEnabled; + } + + if (IsKeyPressed(KEY_H)) { + helpEnabled = !helpEnabled; + } + + if (IsKeyPressed(KEY_L)) { + labelEnabled = !labelEnabled; + } + + if (IsKeyPressed(KEY_P)) { + cameraParametersEnabled = !cameraParametersEnabled; + } + + if (IsKeyPressed(KEY_LEFT)) { + rotationSpeed -= 0.1; + } + + if (IsKeyPressed(KEY_RIGHT)) { + rotationSpeed += 0.1; + } + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + BeginMode3D(camera); + + DrawBody(&sun, &camera); + + // Some reference elements (not affected by previous matrix transformations) + if (gridEnabled) { + DrawGrid(80, 1.0f); + } + + EndMode3D(); + + if (labelEnabled) { + DrawLabels(&sun); + } + + DrawText("FULL SOLAR SYSTEM", 400, 10, 20, MAROON); + text = FormatText("SPEED: %2.2f", rotationSpeed); + DrawText(text, 1024 / 2 - MeasureText(text, 20) / 2, 30, 20, MAROON); + + if (cameraParametersEnabled) { + text = FormatText("Camera\nposition: [%3.3f, %3.3f, %3.3f]\ntarget: [%3.3f, %3.3f, %3.3f]\nup: [%3.3f, %3.3f, %3.3f]", + camera.position.x, camera.position.y, camera.position.z, + camera.target.x, camera.target.y, camera.target.z, + camera.up.x, camera.up.y, camera.up.z); + DrawText(text, 10, 50, 20, MAROON); + } + + if (helpEnabled) { + DrawText("Keys:\n- [g] toggle grid\n- [h] toggle help\n- [l] toggle labels\n- [p] toggle camera parameters\n- [left/right arrows] increase/decrease speed by 0.1", 200, 200, 20, MAROON); + } else { + DrawText("press [h] for help", 1016 - MeasureText("press [h] for help", 20), 740, 20, MAROON); + } + DrawFPS(10, 10); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +//-------------------------------------------------------------------------------------------- +// Module Functions Definitions (local) +//-------------------------------------------------------------------------------------------- + +// Creates a new body +Body CreateBody(float radius, float orbitRadius, float orbitPeriod, Color color, const char *label) +{ + Body body; + + body.label = label; + body.radius = radius; + body.orbitRadius = orbitRadius; + body.orbitPeriod = orbitPeriod; + body.color = color; + body.childrenCount = 0; + body.orbitPosition = 0.0; + return body; +} + +void AddBodyChildren(Body *parent, Body *children) { + if (parent->childrenCount >= MAX_BODY_CHILDREN) { + TraceLog(LOG_ERROR, "BODY HAS TOO MANY CHILDREN"); + } else { + parent->children[parent->childrenCount] = children; + parent->childrenCount++; + } +} + +// Draw body and its children +void DrawBody(Body *body, Camera *camera) +{ + rlPushMatrix(); + rlScalef(body->radius, body->radius, body->radius); // Scale Sun + DrawSphereBasic(body->color); // Draw the body + rlPopMatrix(); + + body->labelPosition = GetWorldToScreen((Vector3) { body->orbitRadius, body->radius, 0.0 }, *camera); + + for (int i = 0; i < body->childrenCount; i++) { + Body *child = body->children[i]; + child->orbitPosition += rotationSpeed * 360 / child->orbitPeriod; + rlPushMatrix(); + rlRotatef(child->orbitPosition, 0.0, 1.0, 0.0); + rlTranslatef(child->orbitRadius, 0.0, 0.0); + rlRotatef(-child->orbitPosition, 0.0, 1.0, 0.0); + + DrawBody(child, camera); + rlPopMatrix(); + + DrawCircle3D((Vector3){ 0.0f, 0.0f, 0.0f }, child->orbitRadius, (Vector3){ 1.0f, 0.0f, 0.0f }, 90.0f, child->color); + } +} + +// Draw body label and its children labels +void DrawLabels(Body *body) +{ + DrawText(body->label, body->labelPosition.x - MeasureText(body->label, 20) / 2, body->labelPosition.y, 20, BLACK); + + for (int i = 0; i < body->childrenCount; i++) { + Body *child = body->children[i]; + + DrawLabels(child); + } +} + + +// Draw sphere without any matrix transformation +// NOTE: Sphere is drawn in world position ( 0, 0, 0 ) with radius 1.0f +void DrawSphereBasic(Color color) +{ + int rings = 16; + int slices = 16; + + rlBegin(RL_TRIANGLES); + rlColor4ub(color.r, color.g, color.b, color.a); + + for (int i = 0; i < (rings + 2); i++) + { + for (int j = 0; j < slices; j++) + { + rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*i))*sinf(DEG2RAD*(j*360/slices)), + sinf(DEG2RAD*(270+(180/(rings + 1))*i)), + cosf(DEG2RAD*(270+(180/(rings + 1))*i))*cosf(DEG2RAD*(j*360/slices))); + rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sinf(DEG2RAD*((j+1)*360/slices)), + sinf(DEG2RAD*(270+(180/(rings + 1))*(i+1))), + cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cosf(DEG2RAD*((j+1)*360/slices))); + rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sinf(DEG2RAD*(j*360/slices)), + sinf(DEG2RAD*(270+(180/(rings + 1))*(i+1))), + cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cosf(DEG2RAD*(j*360/slices))); + + rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*i))*sinf(DEG2RAD*(j*360/slices)), + sinf(DEG2RAD*(270+(180/(rings + 1))*i)), + cosf(DEG2RAD*(270+(180/(rings + 1))*i))*cosf(DEG2RAD*(j*360/slices))); + rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i)))*sinf(DEG2RAD*((j+1)*360/slices)), + sinf(DEG2RAD*(270+(180/(rings + 1))*(i))), + cosf(DEG2RAD*(270+(180/(rings + 1))*(i)))*cosf(DEG2RAD*((j+1)*360/slices))); + rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sinf(DEG2RAD*((j+1)*360/slices)), + sinf(DEG2RAD*(270+(180/(rings + 1))*(i+1))), + cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cosf(DEG2RAD*((j+1)*360/slices))); + } + } + rlEnd(); +} diff --git a/examples/models/models_rlgl_solar_system.c b/examples/models/models_rlgl_solar_system.c index 7193d6f8c..cb9289ad3 100644 --- a/examples/models/models_rlgl_solar_system.c +++ b/examples/models/models_rlgl_solar_system.c @@ -22,13 +22,13 @@ void DrawSphereBasic(Color color); // Draw sphere without any matrix transf //------------------------------------------------------------------------------------ // Program main entry point //------------------------------------------------------------------------------------ -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- const int screenWidth = 800; const int screenHeight = 450; - + const float sunRadius = 4.0f; const float earthRadius = 0.6f; const float earthOrbitRadius = 8.0f; @@ -44,26 +44,26 @@ int main() camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; camera.fovy = 45.0f; camera.type = CAMERA_PERSPECTIVE; - + SetCameraMode(camera, CAMERA_FREE); - + float rotationSpeed = 0.2f; // General system rotation speed - + float earthRotation = 0.0f; // Rotation of earth around itself (days) in degrees float earthOrbitRotation = 0.0f; // Rotation of earth around the Sun (years) in degrees float moonRotation = 0.0f; // Rotation of moon around itself float moonOrbitRotation = 0.0f; // Rotation of moon around earth in degrees - SetTargetFPS(60); // Set our game to run at 60 frames-per-second + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop - while (!WindowShouldClose()) // Detect window close button or ESC key + while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- UpdateCamera(&camera); - + earthRotation += (5.0f*rotationSpeed); earthOrbitRotation += (365/360.0f*(5.0f*rotationSpeed)*rotationSpeed); moonRotation += (2.0f*rotationSpeed); @@ -77,12 +77,12 @@ int main() ClearBackground(RAYWHITE); BeginMode3D(camera); - + rlPushMatrix(); rlScalef(sunRadius, sunRadius, sunRadius); // Scale Sun DrawSphereBasic(GOLD); // Draw the Sun rlPopMatrix(); - + rlPushMatrix(); rlRotatef(earthOrbitRotation, 0.0f, 1.0f, 0.0f); // Rotation for Earth orbit around Sun rlTranslatef(earthOrbitRadius, 0.0f, 0.0f); // Translation for Earth orbit @@ -91,19 +91,19 @@ int main() rlPushMatrix(); rlRotatef(earthRotation, 0.25, 1.0, 0.0); // Rotation for Earth itself rlScalef(earthRadius, earthRadius, earthRadius);// Scale Earth - + DrawSphereBasic(BLUE); // Draw the Earth rlPopMatrix(); - + rlRotatef(moonOrbitRotation, 0.0f, 1.0f, 0.0f); // Rotation for Moon orbit around Earth rlTranslatef(moonOrbitRadius, 0.0f, 0.0f); // Translation for Moon orbit rlRotatef(-moonOrbitRotation, 0.0f, 1.0f, 0.0f); // Rotation for Moon orbit around Earth inverted rlRotatef(moonRotation, 0.0f, 1.0f, 0.0f); // Rotation for Moon itself rlScalef(moonRadius, moonRadius, moonRadius); // Scale Moon - + DrawSphereBasic(LIGHTGRAY); // Draw the Moon rlPopMatrix(); - + // Some reference elements (not affected by previous matrix transformations) DrawCircle3D((Vector3){ 0.0f, 0.0f, 0.0f }, earthOrbitRadius, (Vector3){ 1, 0, 0 }, 90.0f, Fade(RED, 0.5f)); DrawGrid(20, 1.0f); @@ -135,7 +135,7 @@ void DrawSphereBasic(Color color) { int rings = 16; int slices = 16; - + rlBegin(RL_TRIANGLES); rlColor4ub(color.r, color.g, color.b, color.a); diff --git a/examples/models/models_skybox.c b/examples/models/models_skybox.c index 759c79c62..c2849032d 100644 --- a/examples/models/models_skybox.c +++ b/examples/models/models_skybox.c @@ -11,41 +11,49 @@ #include "raylib.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [models] example - skybox loading and drawing"); // Define the camera to look into our 3d world - Camera camera = {{ 1.0f, 1.0f, 1.0f }, { 4.0f, 1.0f, 4.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 }; + Camera camera = { { 1.0f, 1.0f, 1.0f }, { 4.0f, 1.0f, 4.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 }; - // Load skybox model + // Load skybox model Mesh cube = GenMeshCube(1.0f, 1.0f, 1.0f); Model skybox = LoadModelFromMesh(cube); - + // Load skybox shader and set required locations // NOTE: Some locations are automatically set at shader loading - skybox.materials[0].shader = LoadShader("resources/shaders/skybox.vs", "resources/shaders/skybox.fs"); +#if defined(PLATFORM_DESKTOP) + skybox.materials[0].shader = LoadShader("resources/shaders/glsl330/skybox.vs", "resources/shaders/glsl330/skybox.fs"); +#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB + skybox.materials[0].shader = LoadShader("resources/shaders/glsl100/skybox.vs", "resources/shaders/glsl100/skybox.fs"); +#endif SetShaderValue(skybox.materials[0].shader, GetShaderLocation(skybox.materials[0].shader, "environmentMap"), (int[1]){ MAP_CUBEMAP }, UNIFORM_INT); // Load cubemap shader and setup required shader locations - Shader shdrCubemap = LoadShader("resources/shaders/cubemap.vs", "resources/shaders/cubemap.fs"); +#if defined(PLATFORM_DESKTOP) + Shader shdrCubemap = LoadShader("resources/shaders/glsl330/cubemap.vs", "resources/shaders/glsl330/cubemap.fs"); +#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB + Shader shdrCubemap = LoadShader("resources/shaders/glsl100/cubemap.vs", "resources/shaders/glsl100/cubemap.fs"); +#endif SetShaderValue(shdrCubemap, GetShaderLocation(shdrCubemap, "equirectangularMap"), (int[1]){ 0 }, UNIFORM_INT); - + // Load HDR panorama (sphere) texture Texture2D texHDR = LoadTexture("resources/dresden_square.hdr"); - + // Generate cubemap (texture with 6 quads-cube-mapping) from panorama HDR texture // NOTE: New texture is generated rendering to texture, shader computes the sphre->cube coordinates mapping skybox.materials[0].maps[MAP_CUBEMAP].texture = GenTextureCubemap(shdrCubemap, texHDR, 512); - + UnloadTexture(texHDR); // Texture not required anymore, cubemap already generated UnloadShader(shdrCubemap); // Unload cubemap generation shader, not required anymore - + SetCameraMode(camera, CAMERA_FIRST_PERSON); // Set a first person camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second @@ -68,7 +76,7 @@ int main() BeginMode3D(camera); DrawModel(skybox, (Vector3){0, 0, 0}, 1.0f, WHITE); - + DrawGrid(10, 1.0f); EndMode3D(); @@ -81,7 +89,10 @@ int main() // De-Initialization //-------------------------------------------------------------------------------------- - UnloadModel(skybox); // Unload skybox model (and textures) + UnloadShader(skybox.materials[0].shader); + UnloadTexture(skybox.materials[0].maps[MAP_CUBEMAP].texture); + + UnloadModel(skybox); // Unload skybox model CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/models/models_solar_system.c b/examples/models/models_solar_system.c new file mode 100644 index 000000000..5e2ba72a4 --- /dev/null +++ b/examples/models/models_solar_system.c @@ -0,0 +1,244 @@ +/******************************************************************************************* +* +* raylib [models] example - full solar system +* +* This example has been created using raylib 2.5 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2019 Aldrin Martoq (@aldrinmartoq) +* +********************************************************************************************/ + +#include "raylib.h" +#include "rlgl.h" + +#define MAX_BODY_CHILDREN 10 +float rotationSpeed = 0.2; + +// A celestial body that has children bodies orbiting around +typedef struct Body { + const char *label; // label of the body, for ex: moon + float radius; // object radius + float orbitRadius; // orbit average radius + float orbitPeriod; // time the body takes to do a full orbit loop + float rotationPeriod; // time the body takes to do a full rotation on itself + Texture2D texture; // texture of the body + Model model; // model of the body + float orbitPosition; // current orbit position + float rotationPosition; // current rotation position + Vector2 labelPosition; // label position in screen + struct Body *children[MAX_BODY_CHILDREN]; // children array + int childrenCount; // children count +} Body; + +//------------------------------------------------------------------------------------ +// Module Functions Declaration +//------------------------------------------------------------------------------------ +Body CreateBody(float radius, float orbitRadius, float orbitPeriod, const char *label, const char *texture); // Initializes a new Body with the given parameters +void AddBodyChildren(Body *parent, Body *children); // Add a children body to the parent body +void DrawBody(Body *body, Camera *camera); // Draw body and its children, updating labelPosition +void DrawLabels(Body *body); // Draw body label and its children labels + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 1024; + const int screenHeight = 768; + const char *text; + bool gridEnabled = true; + bool helpEnabled = false; + bool labelEnabled = true; + bool cameraParametersEnabled = true; + + InitWindow(screenWidth, screenHeight, "raylib [models] example - solar system"); + + // Define the camera to look into our 3d world + Camera camera = { 0 }; + camera.position = (Vector3){ 16.0f, 16.0f, 16.0f }; + camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; + camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; + camera.fovy = 45.0f; + camera.type = CAMERA_PERSPECTIVE; + + SetCameraMode(camera, CAMERA_FREE); + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + //-------------------------------------------------------------------------------------- + + // Create Bodies + Body sun = CreateBody(0.2, 0.0, 0, "sun", "2k_sun"); + Body moon = CreateBody(0.05, 0.200, 24, "moon", "2k_moon"); + Body mercury = CreateBody(0.05, 0.396, 90, "mercury", "2k_mercury"); + Body venus = CreateBody(0.05, 0.723, 210, "venus", "2k_venus_atmosphere"); + Body earth = CreateBody(0.05, 1.000, 365, "earth", "2k_earth_daymap"); + Body mars = CreateBody(0.05, 1.523, 690, "mars", "2k_mars"); + Body jupiter = CreateBody(0.05, 5.200, 4260, "jupiter", "2k_jupiter"); + Body saturn = CreateBody(0.05, 9.532, 10620, "saturn", "2k_saturn"); + Body uranus = CreateBody(0.05, 19.180, 30270, "uranus", "2k_uranus"); + Body neptune = CreateBody(0.05, 30.056, 59370, "neptune", "2k_neptune"); + Body pluto = CreateBody(0.05, 39.463, 89310, "pluto", "2k_eris_fictional"); + + AddBodyChildren(&sun, &mercury); + // AddBodyChildren(&sun, &venus); + AddBodyChildren(&sun, &earth); + // AddBodyChildren(&sun, &mars); + // AddBodyChildren(&sun, &jupiter); + // AddBodyChildren(&sun, &saturn); + // AddBodyChildren(&sun, &uranus); + // AddBodyChildren(&sun, &neptune); + // AddBodyChildren(&sun, &pluto); + + AddBodyChildren(&earth, &moon); + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + UpdateCamera(&camera); + + if (IsKeyPressed(KEY_G)) { + gridEnabled = !gridEnabled; + } + + if (IsKeyPressed(KEY_H)) { + helpEnabled = !helpEnabled; + } + + if (IsKeyPressed(KEY_L)) { + labelEnabled = !labelEnabled; + } + + if (IsKeyPressed(KEY_P)) { + cameraParametersEnabled = !cameraParametersEnabled; + } + + if (IsKeyPressed(KEY_LEFT)) { + rotationSpeed -= 0.1; + } + + if (IsKeyPressed(KEY_RIGHT)) { + rotationSpeed += 0.1; + } + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(BLACK); + + BeginMode3D(camera); + + DrawBody(&sun, &camera); + + // Some reference elements (not affected by previous matrix transformations) + if (gridEnabled) { + DrawGrid(80, 1.0f); + } + + EndMode3D(); + + if (labelEnabled) { + DrawLabels(&sun); + } + + DrawText("FULL SOLAR SYSTEM", 400, 10, 20, YELLOW); + text = FormatText("SPEED: %2.2f", rotationSpeed); + DrawText(text, 1024 / 2 - MeasureText(text, 20) / 2, 30, 20, YELLOW); + + if (cameraParametersEnabled) { + text = FormatText("Camera\nposition: [%3.3f, %3.3f, %3.3f]\ntarget: [%3.3f, %3.3f, %3.3f]\nup: [%3.3f, %3.3f, %3.3f]", + camera.position.x, camera.position.y, camera.position.z, + camera.target.x, camera.target.y, camera.target.z, + camera.up.x, camera.up.y, camera.up.z); + DrawText(text, 10, 50, 20, YELLOW); + } + + if (helpEnabled) { + DrawText("Keys:\n- [g] toggle grid\n- [h] toggle help\n- [l] toggle labels\n- [p] toggle camera parameters\n- [left/right arrows] increase/decrease speed by 0.1", 200, 200, 20, YELLOW); + } else { + DrawText("press [h] for help", 1016 - MeasureText("press [h] for help", 20), 740, 20, YELLOW); + } + DrawFPS(10, 10); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +//-------------------------------------------------------------------------------------------- +// Module Functions Definitions (local) +//-------------------------------------------------------------------------------------------- + +// Creates a new body +Body CreateBody(float radius, float orbitRadius, float orbitPeriod, const char *label, const char *texture_name) +{ + Body body; + Texture2D texture = LoadTexture(FormatText("resources/solar_system/%s.png", texture_name)); + + GenTextureMipmaps(&texture); + + body.label = label; + body.radius = radius * 10; + body.orbitRadius = orbitRadius * 10; + body.orbitPeriod = orbitPeriod; + body.model = LoadModel("resources/solar_system/sphere.obj"); + body.model.materials[0].maps[MAP_DIFFUSE].texture = texture; + body.childrenCount = 0; + body.orbitPosition = 0.0; + return body; +} + +void AddBodyChildren(Body *parent, Body *children) { + if (parent->childrenCount >= MAX_BODY_CHILDREN) { + TraceLog(LOG_ERROR, "BODY HAS TOO MANY CHILDREN"); + } else { + parent->children[parent->childrenCount] = children; + parent->childrenCount++; + } +} + +// Draw body and its children +void DrawBody(Body *body, Camera *camera) +{ + DrawModel(body->model, (Vector3) { 0.0f, 0.0f, 0.0f}, body->radius, WHITE); + + body->labelPosition = GetWorldToScreen((Vector3) { body->orbitRadius, body->radius, 0.0 }, *camera); + + for (int i = 0; i < body->childrenCount; i++) { + Body *child = body->children[i]; + child->orbitPosition += rotationSpeed * 360 / child->orbitPeriod; + rlPushMatrix(); + rlRotatef(child->orbitPosition, 0.0, 1.0, 0.0); + rlTranslatef(child->orbitRadius, 0.0, 0.0); + rlRotatef(-child->orbitPosition, 0.0, 1.0, 0.0); + + DrawBody(child, camera); + rlPopMatrix(); + + DrawCircle3D((Vector3){ 0.0f, 0.0f, 0.0f }, child->orbitRadius, (Vector3){ 1.0f, 0.0f, 0.0f }, 90.0f, GRAY); + } +} + +// Draw body label and its children labels +void DrawLabels(Body *body) +{ + DrawText(body->label, body->labelPosition.x - MeasureText(body->label, 20) / 2, body->labelPosition.y, 20, WHITE); + + for (int i = 0; i < body->childrenCount; i++) { + Body *child = body->children[i]; + + DrawLabels(child); + } +} diff --git a/examples/models/models_waving_cubes.c b/examples/models/models_waving_cubes.c new file mode 100644 index 000000000..f6309bd6d --- /dev/null +++ b/examples/models/models_waving_cubes.c @@ -0,0 +1,112 @@ +/******************************************************************************************* +* +* raylib [models] example - Waving cubes +* +* This example has been created using raylib 2.5 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Example contributed by Codecat (@codecat) and reviewed by Ramon Santamaria (@raysan5) +* +* Copyright (c) 2019 Codecat (@codecat) and Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#include + +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [models] example - waving cubes"); + + // Initialize the camera + Camera3D camera = { 0 }; + camera.position = (Vector3){ 30.0f, 20.0f, 30.0f }; + camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; + camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; + camera.fovy = 70.0f; + camera.type = CAMERA_PERSPECTIVE; + + // Specify the amount of blocks in each direction + const int numBlocks = 15; + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + double time = GetTime(); + + // Calculate time scale for cube position and size + float scale = (2.0f + (float)sin(time))*0.7f; + + // Move camera around the scene + double cameraTime = time*0.3; + camera.position.x = (float)cos(cameraTime)*40.0f; + camera.position.z = (float)sin(cameraTime)*40.0f; + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + BeginMode3D(camera); + + DrawGrid(10, 5.0f); + + for (int x = 0; x < numBlocks; x++) + { + for (int y = 0; y < numBlocks; y++) + { + for (int z = 0; z < numBlocks; z++) + { + // Scale of the blocks depends on x/y/z positions + float blockScale = (x + y + z)/30.0f; + + // Scatter makes the waving effect by adding blockScale over time + float scatter = sinf(blockScale*20.0f + (float)(time*4.0f)); + + // Calculate the cube position + Vector3 cubePos = { + (float)(x - numBlocks/2)*(scale*3.0f) + scatter, + (float)(y - numBlocks/2)*(scale*2.0f) + scatter, + (float)(z - numBlocks/2)*(scale*3.0f) + scatter + }; + + // Pick a color with a hue depending on cube position for the rainbow color effect + Color cubeColor = ColorFromHSV((Vector3){ (float)(((x + y + z)*18)%360), 0.75f, 0.9f }); + + // Calculate cube size + float cubeSize = (2.4f - scale)*blockScale; + + // And finally, draw the cube! + DrawCube(cubePos, cubeSize, cubeSize, cubeSize, cubeColor); + } + } + } + + EndMode3D(); + + DrawFPS(10, 10); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} diff --git a/examples/models/models_waving_cubes.png b/examples/models/models_waving_cubes.png new file mode 100644 index 000000000..37a1761ec Binary files /dev/null and b/examples/models/models_waving_cubes.png differ diff --git a/examples/models/models_yaw_pitch_roll.c b/examples/models/models_yaw_pitch_roll.c index 7eaaf0bea..652738113 100644 --- a/examples/models/models_yaw_pitch_roll.c +++ b/examples/models/models_yaw_pitch_roll.c @@ -5,9 +5,9 @@ * This example has been created using raylib 1.8 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * -* Example based on Berni work on Raspberry Pi. +* Example contributed by Berni (@Berni8k) and reviewed by Ramon Santamaria (@raysan5) * -* Copyright (c) 2017 Ramon Santamaria (@raysan5) +* Copyright (c) 2017 Berni (@Berni8k) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ @@ -17,10 +17,7 @@ // Draw angle gauge controls void DrawAngleGauge(Texture2D angleGauge, int x, int y, float angle, char title[], Color color); -//---------------------------------------------------------------------------------- -// Main entry point -//---------------------------------------------------------------------------------- -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- @@ -53,10 +50,10 @@ int main() float roll = 0.0f; float yaw = 0.0f; - SetTargetFPS(60); + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- - + // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update @@ -95,6 +92,7 @@ int main() while (pitchOffset < -180) pitchOffset += 360; pitchOffset *= 10; + /* matrix transform done with multiplication to combine rotations Matrix transform = MatrixIdentity(); transform = MatrixMultiply(transform, MatrixRotateZ(DEG2RAD*roll)); @@ -102,8 +100,11 @@ int main() transform = MatrixMultiply(transform, MatrixRotateY(DEG2RAD*yaw)); model.transform = transform; - //---------------------------------------------------------------------------------- + */ + // matrix created from multiple axes at once + model.transform = MatrixRotateXYZ((Vector3){DEG2RAD*pitch,DEG2RAD*yaw,DEG2RAD*roll}); + //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); @@ -168,6 +169,7 @@ int main() //-------------------------------------------------------------------------------------- // Unload all loaded data + UnloadTexture(model.materials[0].maps[MAP_DIFFUSE].texture); UnloadModel(model); UnloadRenderTexture(framebuffer); diff --git a/examples/models/resources/models/Duck/Duck.glb b/examples/models/resources/models/Duck/Duck.glb new file mode 100644 index 000000000..217170d2b Binary files /dev/null and b/examples/models/resources/models/Duck/Duck.glb differ diff --git a/examples/models/resources/models/Duck/Duck.gltf b/examples/models/resources/models/Duck/Duck.gltf new file mode 100644 index 000000000..b80c842ce --- /dev/null +++ b/examples/models/resources/models/Duck/Duck.gltf @@ -0,0 +1,219 @@ +{ + "asset": { + "generator": "COLLADA2GLTF", + "version": "2.0" + }, + "scene": 0, + "scenes": [ + { + "nodes": [ + 0 + ] + } + ], + "nodes": [ + { + "children": [ + 2, + 1 + ], + "matrix": [ + 0.009999999776482582, + 0.0, + 0.0, + 0.0, + 0.0, + 0.009999999776482582, + 0.0, + 0.0, + 0.0, + 0.0, + 0.009999999776482582, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0 + ] + }, + { + "matrix": [ + -0.7289686799049377, + 0.0, + -0.6845470666885376, + 0.0, + -0.4252049028873444, + 0.7836934328079224, + 0.4527972936630249, + 0.0, + 0.5364750623703003, + 0.6211478114128113, + -0.571287989616394, + 0.0, + 400.1130065917969, + 463.2640075683594, + -431.0780334472656, + 1.0 + ], + "camera": 0 + }, + { + "mesh": 0 + } + ], + "cameras": [ + { + "perspective": { + "aspectRatio": 1.5, + "yfov": 0.6605925559997559, + "zfar": 10000.0, + "znear": 1.0 + }, + "type": "perspective" + } + ], + "meshes": [ + { + "primitives": [ + { + "attributes": { + "NORMAL": 1, + "POSITION": 2, + "TEXCOORD_0": 3 + }, + "indices": 0, + "mode": 4, + "material": 0 + } + ], + "name": "LOD3spShape" + } + ], + "accessors": [ + { + "bufferView": 0, + "byteOffset": 0, + "componentType": 5123, + "count": 12636, + "max": [ + 2398 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 1, + "byteOffset": 0, + "componentType": 5126, + "count": 2399, + "max": [ + 0.9995989799499512, + 0.999580979347229, + 0.9984359741210938 + ], + "min": [ + -0.9990839958190918, + -1.0, + -0.9998319745063782 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 28788, + "componentType": 5126, + "count": 2399, + "max": [ + 96.17990112304688, + 163.97000122070313, + 53.92519760131836 + ], + "min": [ + -69.29850006103516, + 9.929369926452637, + -61.32819747924805 + ], + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 0, + "componentType": 5126, + "count": 2399, + "max": [ + 0.9833459854125976, + 0.9800369739532472 + ], + "min": [ + 0.026409000158309938, + 0.01996302604675293 + ], + "type": "VEC2" + } + ], + "materials": [ + { + "pbrMetallicRoughness": { + "baseColorTexture": { + "index": 0 + }, + "metallicFactor": 0.0 + }, + "emissiveFactor": [ + 0.0, + 0.0, + 0.0 + ], + "name": "blinn3-fx" + } + ], + "textures": [ + { + "sampler": 0, + "source": 0 + } + ], + "images": [ + { + "uri": "DuckCM.png" + } + ], + "samplers": [ + { + "magFilter": 9729, + "minFilter": 9986, + "wrapS": 10497, + "wrapT": 10497 + } + ], + "bufferViews": [ + { + "buffer": 0, + "byteOffset": 76768, + "byteLength": 25272, + "target": 34963 + }, + { + "buffer": 0, + "byteOffset": 0, + "byteLength": 57576, + "byteStride": 12, + "target": 34962 + }, + { + "buffer": 0, + "byteOffset": 57576, + "byteLength": 19192, + "byteStride": 8, + "target": 34962 + } + ], + "buffers": [ + { + "byteLength": 102040, + "uri": "Duck0.bin" + } + ] +} diff --git a/examples/models/resources/models/Duck/Duck0.bin b/examples/models/resources/models/Duck/Duck0.bin new file mode 100644 index 000000000..5f01f88ac Binary files /dev/null and b/examples/models/resources/models/Duck/Duck0.bin differ diff --git a/examples/models/resources/models/Duck/DuckCM.png b/examples/models/resources/models/Duck/DuckCM.png new file mode 100644 index 000000000..9fa2dd4cc Binary files /dev/null and b/examples/models/resources/models/Duck/DuckCM.png differ diff --git a/examples/models/resources/models/Duck/Duck_license.txt b/examples/models/resources/models/Duck/Duck_license.txt new file mode 100644 index 000000000..d1b4f3c34 --- /dev/null +++ b/examples/models/resources/models/Duck/Duck_license.txt @@ -0,0 +1,14 @@ +# Duck +## Screenshot + +![screenshot](screenshot/screenshot.png) + +## License Information + +Copyright 2006 Sony Computer Entertainment Inc. + +Licensed under the SCEA Shared Source License, Version 1.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: + +http://research.scea.com/scea_shared_source_license.html + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. \ No newline at end of file diff --git a/examples/models/resources/models/castle_diffuse.png b/examples/models/resources/models/castle_diffuse.png index b616e1dde..361144e91 100644 Binary files a/examples/models/resources/models/castle_diffuse.png and b/examples/models/resources/models/castle_diffuse.png differ diff --git a/examples/models/resources/pbr/trooper_albedo.png b/examples/models/resources/pbr/trooper_albedo.png index ac1422e49..9ba0f5a61 100644 Binary files a/examples/models/resources/pbr/trooper_albedo.png and b/examples/models/resources/pbr/trooper_albedo.png differ diff --git a/examples/models/resources/pbr/trooper_ao.png b/examples/models/resources/pbr/trooper_ao.png index 8567f7b4d..442dd7fb7 100644 Binary files a/examples/models/resources/pbr/trooper_ao.png and b/examples/models/resources/pbr/trooper_ao.png differ diff --git a/examples/models/resources/pbr/trooper_normals.png b/examples/models/resources/pbr/trooper_normals.png index 59c7bdc4e..e04be8830 100644 Binary files a/examples/models/resources/pbr/trooper_normals.png and b/examples/models/resources/pbr/trooper_normals.png differ diff --git a/examples/models/resources/pbr/trooper_roughness.png b/examples/models/resources/pbr/trooper_roughness.png index 53186d51d..29f418f7d 100644 Binary files a/examples/models/resources/pbr/trooper_roughness.png and b/examples/models/resources/pbr/trooper_roughness.png differ diff --git a/examples/models/resources/plane_diffuse.png b/examples/models/resources/plane_diffuse.png index fb16f24c1..8cf75c7d2 100644 Binary files a/examples/models/resources/plane_diffuse.png and b/examples/models/resources/plane_diffuse.png differ diff --git a/examples/models/resources/shaders/brdf.fs b/examples/models/resources/shaders/glsl100/brdf.fs similarity index 100% rename from examples/models/resources/shaders/brdf.fs rename to examples/models/resources/shaders/glsl100/brdf.fs diff --git a/examples/models/resources/shaders/brdf.vs b/examples/models/resources/shaders/glsl100/brdf.vs similarity index 100% rename from examples/models/resources/shaders/brdf.vs rename to examples/models/resources/shaders/glsl100/brdf.vs diff --git a/examples/models/resources/shaders/cubemap.fs b/examples/models/resources/shaders/glsl100/cubemap.fs similarity index 100% rename from examples/models/resources/shaders/cubemap.fs rename to examples/models/resources/shaders/glsl100/cubemap.fs diff --git a/examples/models/resources/shaders/cubemap.vs b/examples/models/resources/shaders/glsl100/cubemap.vs similarity index 100% rename from examples/models/resources/shaders/cubemap.vs rename to examples/models/resources/shaders/glsl100/cubemap.vs diff --git a/examples/models/resources/shaders/irradiance.fs b/examples/models/resources/shaders/glsl100/irradiance.fs similarity index 100% rename from examples/models/resources/shaders/irradiance.fs rename to examples/models/resources/shaders/glsl100/irradiance.fs diff --git a/examples/models/resources/shaders/pbr.fs b/examples/models/resources/shaders/glsl100/pbr.fs similarity index 100% rename from examples/models/resources/shaders/pbr.fs rename to examples/models/resources/shaders/glsl100/pbr.fs diff --git a/examples/models/resources/shaders/pbr.vs b/examples/models/resources/shaders/glsl100/pbr.vs similarity index 100% rename from examples/models/resources/shaders/pbr.vs rename to examples/models/resources/shaders/glsl100/pbr.vs diff --git a/examples/models/resources/shaders/prefilter.fs b/examples/models/resources/shaders/glsl100/prefilter.fs similarity index 100% rename from examples/models/resources/shaders/prefilter.fs rename to examples/models/resources/shaders/glsl100/prefilter.fs diff --git a/examples/models/resources/shaders/skybox.fs b/examples/models/resources/shaders/glsl100/skybox.fs similarity index 100% rename from examples/models/resources/shaders/skybox.fs rename to examples/models/resources/shaders/glsl100/skybox.fs diff --git a/examples/models/resources/shaders/skybox.vs b/examples/models/resources/shaders/glsl100/skybox.vs similarity index 100% rename from examples/models/resources/shaders/skybox.vs rename to examples/models/resources/shaders/glsl100/skybox.vs diff --git a/examples/models/resources/shaders/glsl330/brdf.fs b/examples/models/resources/shaders/glsl330/brdf.fs new file mode 100644 index 000000000..d04bc6618 --- /dev/null +++ b/examples/models/resources/shaders/glsl330/brdf.fs @@ -0,0 +1,133 @@ +/******************************************************************************************* +* +* BRDF LUT Generation - Bidirectional reflectance distribution function fragment shader +* +* REF: https://github.com/HectorMF/BRDFGenerator +* +* Copyright (c) 2017 Victor Fisac +* +**********************************************************************************************/ + +#version 330 + + +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; + +// Constant values +const float PI = 3.14159265359; +const uint MAX_SAMPLES = 1024u; + +// Output fragment color +out vec4 finalColor; + +vec2 Hammersley(uint i, uint N); +float RadicalInverseVdC(uint bits); +float GeometrySchlickGGX(float NdotV, float roughness); +float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness); +vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness); +vec2 IntegrateBRDF(float NdotV, float roughness); + +float RadicalInverseVdC(uint bits) +{ + bits = (bits << 16u) | (bits >> 16u); + bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); + bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); + bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); + bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); + return float(bits) * 2.3283064365386963e-10; // / 0x100000000 +} + +// Compute Hammersley coordinates +vec2 Hammersley(uint i, uint N) +{ + return vec2(float(i)/float(N), RadicalInverseVdC(i)); +} + +// Integrate number of importance samples for (roughness and NoV) +vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness) +{ + float a = roughness*roughness; + float phi = 2.0 * PI * Xi.x; + float cosTheta = sqrt((1.0 - Xi.y)/(1.0 + (a*a - 1.0)*Xi.y)); + float sinTheta = sqrt(1.0 - cosTheta*cosTheta); + + // Transform from spherical coordinates to cartesian coordinates (halfway vector) + vec3 H = vec3(cos(phi)*sinTheta, sin(phi)*sinTheta, cosTheta); + + // Transform from tangent space H vector to world space sample vector + vec3 up = ((abs(N.z) < 0.999) ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0)); + vec3 tangent = normalize(cross(up, N)); + vec3 bitangent = cross(N, tangent); + vec3 sampleVec = tangent*H.x + bitangent*H.y + N*H.z; + + return normalize(sampleVec); +} + +float GeometrySchlickGGX(float NdotV, float roughness) +{ + // For IBL k is calculated different + float k = (roughness*roughness)/2.0; + + float nom = NdotV; + float denom = NdotV*(1.0 - k) + k; + + return nom/denom; +} + +// Compute the geometry term for the BRDF given roughness squared, NoV, NoL +float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness) +{ + float NdotV = max(dot(N, V), 0.0); + float NdotL = max(dot(N, L), 0.0); + float ggx2 = GeometrySchlickGGX(NdotV, roughness); + float ggx1 = GeometrySchlickGGX(NdotL, roughness); + + return ggx1*ggx2; +} + +vec2 IntegrateBRDF(float NdotV, float roughness) +{ + float A = 0.0; + float B = 0.0; + vec3 V = vec3(sqrt(1.0 - NdotV*NdotV), 0.0, NdotV); + vec3 N = vec3(0.0, 0.0, 1.0); + + for (uint i = 0u; i < MAX_SAMPLES; i++) + { + // Generate a sample vector that's biased towards the preferred alignment direction (importance sampling) + + vec2 Xi = Hammersley(i, MAX_SAMPLES); // Compute a Hammersely coordinate + vec3 H = ImportanceSampleGGX(Xi, N, roughness); // Integrate number of importance samples for (roughness and NoV) + vec3 L = normalize(2.0*dot(V, H)*H - V); // Compute reflection vector L + + float NdotL = max(L.z, 0.0); // Compute normal dot light + float NdotH = max(H.z, 0.0); // Compute normal dot half + float VdotH = max(dot(V, H), 0.0); // Compute view dot half + + if (NdotL > 0.0) + { + float G = GeometrySmith(N, V, L, roughness); // Compute the geometry term for the BRDF given roughness squared, NoV, NoL + float GVis = (G*VdotH)/(NdotH*NdotV); // Compute the visibility term given G, VoH, NoH, NoV, NoL + float Fc = pow(1.0 - VdotH, 5.0); // Compute the fresnel term given VoH + + A += (1.0 - Fc)*GVis; // Sum the result given fresnel, geometry, visibility + B += Fc*GVis; + } + } + + // Calculate brdf average sample + A /= float(MAX_SAMPLES); + B /= float(MAX_SAMPLES); + + return vec2(A, B); +} + +void main() +{ + // Calculate brdf based on texture coordinates + vec2 brdf = IntegrateBRDF(fragTexCoord.x, fragTexCoord.y); + + // Calculate final fragment color + finalColor = vec4(brdf.r, brdf.g, 0.0, 1.0); +} diff --git a/examples/models/resources/shaders/glsl330/brdf.vs b/examples/models/resources/shaders/glsl330/brdf.vs new file mode 100644 index 000000000..06384673b --- /dev/null +++ b/examples/models/resources/shaders/glsl330/brdf.vs @@ -0,0 +1,25 @@ +/******************************************************************************************* +* +* rPBR [shader] - Bidirectional reflectance distribution function vertex shader +* +* Copyright (c) 2017 Victor Fisac +* +**********************************************************************************************/ + +#version 330 + +// Input vertex attributes +in vec3 vertexPosition; +in vec2 vertexTexCoord; + +// Output vertex attributes (to fragment shader) +out vec2 fragTexCoord; + +void main() +{ + // Calculate fragment position based on model transformations + fragTexCoord = vertexTexCoord; + + // Calculate final vertex position + gl_Position = vec4(vertexPosition, 1.0); +} \ No newline at end of file diff --git a/examples/models/resources/shaders/glsl330/cubemap.fs b/examples/models/resources/shaders/glsl330/cubemap.fs new file mode 100644 index 000000000..e8e285363 --- /dev/null +++ b/examples/models/resources/shaders/glsl330/cubemap.fs @@ -0,0 +1,38 @@ +/******************************************************************************************* +* +* rPBR [shader] - Equirectangular to cubemap fragment shader +* +* Copyright (c) 2017 Victor Fisac +* +**********************************************************************************************/ + +#version 330 + +// Input vertex attributes (from vertex shader) +in vec3 fragPosition; + +// Input uniform values +uniform sampler2D equirectangularMap; + +// Output fragment color +out vec4 finalColor; + +vec2 SampleSphericalMap(vec3 v) +{ + vec2 uv = vec2(atan(v.z, v.x), asin(v.y)); + uv *= vec2(0.1591, 0.3183); + uv += 0.5; + return uv; +} + +void main() +{ + // Normalize local position + vec2 uv = SampleSphericalMap(normalize(fragPosition)); + + // Fetch color from texture map + vec3 color = texture(equirectangularMap, uv).rgb; + + // Calculate final fragment color + finalColor = vec4(color, 1.0); +} diff --git a/examples/models/resources/shaders/glsl330/cubemap.vs b/examples/models/resources/shaders/glsl330/cubemap.vs new file mode 100644 index 000000000..5721eaa2c --- /dev/null +++ b/examples/models/resources/shaders/glsl330/cubemap.vs @@ -0,0 +1,28 @@ +/******************************************************************************************* +* +* rPBR [shader] - Equirectangular to cubemap vertex shader +* +* Copyright (c) 2017 Victor Fisac +* +**********************************************************************************************/ + +#version 330 + +// Input vertex attributes +in vec3 vertexPosition; + +// Input uniform values +uniform mat4 projection; +uniform mat4 view; + +// Output vertex attributes (to fragment shader) +out vec3 fragPosition; + +void main() +{ + // Calculate fragment position based on model transformations + fragPosition = vertexPosition; + + // Calculate final vertex position + gl_Position = projection*view*vec4(vertexPosition, 1.0); +} diff --git a/examples/models/resources/shaders/glsl330/irradiance.fs b/examples/models/resources/shaders/glsl330/irradiance.fs new file mode 100644 index 000000000..b42d2143e --- /dev/null +++ b/examples/models/resources/shaders/glsl330/irradiance.fs @@ -0,0 +1,58 @@ +/******************************************************************************************* +* +* rPBR [shader] - Irradiance cubemap fragment shader +* +* Copyright (c) 2017 Victor Fisac +* +**********************************************************************************************/ + +#version 330 + +// Input vertex attributes (from vertex shader) +in vec3 fragPosition; + +// Input uniform values +uniform samplerCube environmentMap; + +// Constant values +const float PI = 3.14159265359f; + +// Output fragment color +out vec4 finalColor; + +void main() +{ + // The sample direction equals the hemisphere's orientation + vec3 normal = normalize(fragPosition); + + vec3 irradiance = vec3(0.0); + + vec3 up = vec3(0.0, 1.0, 0.0); + vec3 right = cross(up, normal); + up = cross(normal, right); + + float sampleDelta = 0.025f; + float nrSamples = 0.0f; + + for (float phi = 0.0; phi < 2.0*PI; phi += sampleDelta) + { + for (float theta = 0.0; theta < 0.5*PI; theta += sampleDelta) + { + // Spherical to cartesian (in tangent space) + vec3 tangentSample = vec3(sin(theta)*cos(phi), sin(theta)*sin(phi), cos(theta)); + + // tangent space to world + vec3 sampleVec = tangentSample.x*right + tangentSample.y*up + tangentSample.z*normal; + + // Fetch color from environment cubemap + irradiance += texture(environmentMap, sampleVec).rgb*cos(theta)*sin(theta); + nrSamples++; + } + } + + // Calculate irradiance average value from samples + irradiance = PI*irradiance*(1.0/float(nrSamples)); + + // Calculate final fragment color + finalColor = vec4(irradiance, 1.0); +} diff --git a/examples/models/resources/shaders/glsl330/pbr.fs b/examples/models/resources/shaders/glsl330/pbr.fs new file mode 100644 index 000000000..68bf203a2 --- /dev/null +++ b/examples/models/resources/shaders/glsl330/pbr.fs @@ -0,0 +1,300 @@ +/******************************************************************************************* +* +* rPBR [shader] - Physically based rendering fragment shader +* +* Copyright (c) 2017 Victor Fisac +* +**********************************************************************************************/ + +#version 330 + +#define MAX_REFLECTION_LOD 4.0 +#define MAX_DEPTH_LAYER 20 +#define MIN_DEPTH_LAYER 10 + +#define MAX_LIGHTS 4 +#define LIGHT_DIRECTIONAL 0 +#define LIGHT_POINT 1 + +struct MaterialProperty { + vec3 color; + int useSampler; + sampler2D sampler; +}; + +struct Light { + int enabled; + int type; + vec3 position; + vec3 target; + vec4 color; +}; + +// Input vertex attributes (from vertex shader) +in vec3 fragPosition; +in vec2 fragTexCoord; +in vec3 fragNormal; +in vec3 fragTangent; +in vec3 fragBinormal; + +// Input material values +uniform MaterialProperty albedo; +uniform MaterialProperty normals; +uniform MaterialProperty metalness; +uniform MaterialProperty roughness; +uniform MaterialProperty occlusion; +uniform MaterialProperty emission; +uniform MaterialProperty height; + +// Input uniform values +uniform samplerCube irradianceMap; +uniform samplerCube prefilterMap; +uniform sampler2D brdfLUT; + +// Input lighting values +uniform Light lights[MAX_LIGHTS]; + +// Other uniform values +uniform int renderMode; +uniform vec3 viewPos; +vec2 texCoord; + +// Constant values +const float PI = 3.14159265359; + +// Output fragment color +out vec4 finalColor; + +vec3 ComputeMaterialProperty(MaterialProperty property); +float DistributionGGX(vec3 N, vec3 H, float roughness); +float GeometrySchlickGGX(float NdotV, float roughness); +float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness); +vec3 fresnelSchlick(float cosTheta, vec3 F0); +vec3 fresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness); +vec2 ParallaxMapping(vec2 texCoords, vec3 viewDir); + +// WARNING: There is some weird behaviour with this function, always returns black! +// Yes, I even tried: return texture(property.sampler, texCoord).rgb; +vec3 ComputeMaterialProperty(MaterialProperty property) +{ + vec3 result = vec3(0.0, 0.0, 0.0); + + if (property.useSampler == 1) result = texture(property.sampler, texCoord).rgb; + else result = property.color; + + return result; +} + +float DistributionGGX(vec3 N, vec3 H, float roughness) +{ + float a = roughness*roughness; + float a2 = a*a; + float NdotH = max(dot(N, H), 0.0); + float NdotH2 = NdotH*NdotH; + + float nom = a2; + float denom = (NdotH2*(a2 - 1.0) + 1.0); + denom = PI*denom*denom; + + return nom/denom; +} + +float GeometrySchlickGGX(float NdotV, float roughness) +{ + float r = (roughness + 1.0); + float k = r*r/8.0; + + float nom = NdotV; + float denom = NdotV*(1.0 - k) + k; + + return nom/denom; +} +float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness) +{ + float NdotV = max(dot(N, V), 0.0); + float NdotL = max(dot(N, L), 0.0); + float ggx2 = GeometrySchlickGGX(NdotV, roughness); + float ggx1 = GeometrySchlickGGX(NdotL, roughness); + + return ggx1*ggx2; +} + +vec3 fresnelSchlick(float cosTheta, vec3 F0) +{ + return F0 + (1.0 - F0)*pow(1.0 - cosTheta, 5.0); +} + +vec3 fresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness) +{ + return F0 + (max(vec3(1.0 - roughness), F0) - F0)*pow(1.0 - cosTheta, 5.0); +} + +vec2 ParallaxMapping(vec2 texCoords, vec3 viewDir) +{ + // Calculate the number of depth layers and calculate the size of each layer + float numLayers = mix(MAX_DEPTH_LAYER, MIN_DEPTH_LAYER, abs(dot(vec3(0.0, 0.0, 1.0), viewDir))); + float layerDepth = 1.0/numLayers; + + // Calculate depth of current layer + float currentLayerDepth = 0.0; + + // Calculate the amount to shift the texture coordinates per layer (from vector P) + // Note: height amount is stored in height material attribute color R channel (sampler use is independent) + vec2 P = viewDir.xy*height.color.r; + vec2 deltaTexCoords = P/numLayers; + + // Store initial texture coordinates and depth values + vec2 currentTexCoords = texCoords; + float currentDepthMapValue = texture(height.sampler, currentTexCoords).r; + + while (currentLayerDepth < currentDepthMapValue) + { + // Shift texture coordinates along direction of P + currentTexCoords -= deltaTexCoords; + + // Get depth map value at current texture coordinates + currentDepthMapValue = texture(height.sampler, currentTexCoords).r; + + // Get depth of next layer + currentLayerDepth += layerDepth; + } + + // Get texture coordinates before collision (reverse operations) + vec2 prevTexCoords = currentTexCoords + deltaTexCoords; + + // Get depth after and before collision for linear interpolation + float afterDepth = currentDepthMapValue - currentLayerDepth; + float beforeDepth = texture(height.sampler, prevTexCoords).r - currentLayerDepth + layerDepth; + + // Interpolation of texture coordinates + float weight = afterDepth/(afterDepth - beforeDepth); + vec2 finalTexCoords = prevTexCoords*weight + currentTexCoords*(1.0 - weight); + + return finalTexCoords; +} + +void main() +{ + // Calculate TBN and RM matrices + mat3 TBN = transpose(mat3(fragTangent, fragBinormal, fragNormal)); + + // Calculate lighting required attributes + vec3 normal = normalize(fragNormal); + vec3 view = normalize(viewPos - fragPosition); + vec3 refl = reflect(-view, normal); + + // Check if parallax mapping is enabled and calculate texture coordinates to use based on height map + // NOTE: remember that 'texCoord' variable must be assigned before calling any ComputeMaterialProperty() function + if (height.useSampler == 1) texCoord = ParallaxMapping(fragTexCoord, view); + else texCoord = fragTexCoord; // Use default texture coordinates + + // Fetch material values from texture sampler or color attributes + vec3 color = texture(albedo.sampler, texCoord).rgb; //ComputeMaterialProperty(albedo); + vec3 metal = texture(metalness.sampler, texCoord).rgb; //ComputeMaterialProperty(metalness); + vec3 rough = texture(roughness.sampler, texCoord).rgb; //ComputeMaterialProperty(roughness); + vec3 emiss = texture(emission.sampler, texCoord).rgb; //ComputeMaterialProperty(emission); + vec3 ao = texture(occlusion.sampler, texCoord).rgb; //ComputeMaterialProperty(occlusion); + + // Check if normal mapping is enabled + if (normals.useSampler == 1) + { + // Fetch normal map color and transform lighting values to tangent space + normal = texture(normals.sampler, texCoord).rgb; //ComputeMaterialProperty(normals); + normal = normalize(normal*2.0 - 1.0); + normal = normalize(normal*TBN); + + // Convert tangent space normal to world space due to cubemap reflection calculations + refl = normalize(reflect(-view, normal)); + } + + // Calculate reflectance at normal incidence + vec3 F0 = vec3(0.04); + F0 = mix(F0, color, metal.r); + + // Calculate lighting for all lights + vec3 Lo = vec3(0.0); + vec3 lightDot = vec3(0.0); + + for (int i = 0; i < MAX_LIGHTS; i++) + { + if (lights[i].enabled == 1) + { + // Calculate per-light radiance + vec3 light = vec3(0.0); + vec3 radiance = lights[i].color.rgb; + if (lights[i].type == LIGHT_DIRECTIONAL) light = -normalize(lights[i].target - lights[i].position); + else if (lights[i].type == LIGHT_POINT) + { + light = normalize(lights[i].position - fragPosition); + float distance = length(lights[i].position - fragPosition); + float attenuation = 1.0/(distance*distance); + radiance *= attenuation; + } + + // Cook-torrance BRDF + vec3 high = normalize(view + light); + float NDF = DistributionGGX(normal, high, rough.r); + float G = GeometrySmith(normal, view, light, rough.r); + vec3 F = fresnelSchlick(max(dot(high, view), 0.0), F0); + vec3 nominator = NDF*G*F; + float denominator = 4*max(dot(normal, view), 0.0)*max(dot(normal, light), 0.0) + 0.001; + vec3 brdf = nominator/denominator; + + // Store to kS the fresnel value and calculate energy conservation + vec3 kS = F; + vec3 kD = vec3(1.0) - kS; + + // Multiply kD by the inverse metalness such that only non-metals have diffuse lighting + kD *= 1.0 - metal.r; + + // Scale light by dot product between normal and light direction + float NdotL = max(dot(normal, light), 0.0); + + // Add to outgoing radiance Lo + // Note: BRDF is already multiplied by the Fresnel so it doesn't need to be multiplied again + Lo += (kD*color/PI + brdf)*radiance*NdotL*lights[i].color.a; + lightDot += radiance*NdotL + brdf*lights[i].color.a; + } + } + + // Calculate ambient lighting using IBL + vec3 F = fresnelSchlickRoughness(max(dot(normal, view), 0.0), F0, rough.r); + vec3 kS = F; + vec3 kD = 1.0 - kS; + kD *= 1.0 - metal.r; + + // Calculate indirect diffuse + vec3 irradiance = texture(irradianceMap, fragNormal).rgb; + vec3 diffuse = color*irradiance; + + // Sample both the prefilter map and the BRDF lut and combine them together as per the Split-Sum approximation + vec3 prefilterColor = textureLod(prefilterMap, refl, rough.r*MAX_REFLECTION_LOD).rgb; + vec2 brdf = texture(brdfLUT, vec2(max(dot(normal, view), 0.0), rough.r)).rg; + vec3 reflection = prefilterColor*(F*brdf.x + brdf.y); + + // Calculate final lighting + vec3 ambient = (kD*diffuse + reflection)*ao; + + // Calculate fragment color based on render mode + vec3 fragmentColor = ambient + Lo + emiss; // Physically Based Rendering + + if (renderMode == 1) fragmentColor = color; // Albedo + else if (renderMode == 2) fragmentColor = normal; // Normals + else if (renderMode == 3) fragmentColor = metal; // Metalness + else if (renderMode == 4) fragmentColor = rough; // Roughness + else if (renderMode == 5) fragmentColor = ao; // Ambient Occlusion + else if (renderMode == 6) fragmentColor = emiss; // Emission + else if (renderMode == 7) fragmentColor = lightDot; // Lighting + else if (renderMode == 8) fragmentColor = kS; // Fresnel + else if (renderMode == 9) fragmentColor = irradiance; // Irradiance + else if (renderMode == 10) fragmentColor = reflection; // Reflection + + // Apply HDR tonemapping + fragmentColor = fragmentColor/(fragmentColor + vec3(1.0)); + + // Apply gamma correction + fragmentColor = pow(fragmentColor, vec3(1.0/2.2)); + + // Calculate final fragment color + finalColor = vec4(fragmentColor, 1.0); +} diff --git a/examples/models/resources/shaders/glsl330/pbr.vs b/examples/models/resources/shaders/glsl330/pbr.vs new file mode 100644 index 000000000..8bd3faa14 --- /dev/null +++ b/examples/models/resources/shaders/glsl330/pbr.vs @@ -0,0 +1,49 @@ +/******************************************************************************************* +* +* rPBR [shader] - Physically based rendering vertex shader +* +* Copyright (c) 2017 Victor Fisac +* +**********************************************************************************************/ + +#version 330 + +// Input vertex attributes +in vec3 vertexPosition; +in vec2 vertexTexCoord; +in vec3 vertexNormal; +in vec4 vertexTangent; + +// Input uniform values +uniform mat4 mvp; +uniform mat4 matModel; + +// Output vertex attributes (to fragment shader) +out vec3 fragPosition; +out vec2 fragTexCoord; +out vec3 fragNormal; +out vec3 fragTangent; +out vec3 fragBinormal; + +void main() +{ + // Calculate binormal from vertex normal and tangent + vec3 vertexBinormal = cross(vertexNormal, vec3(vertexTangent)); + + // Calculate fragment normal based on normal transformations + mat3 normalMatrix = transpose(inverse(mat3(matModel))); + + // Calculate fragment position based on model transformations + fragPosition = vec3(matModel*vec4(vertexPosition, 1.0f)); + + // Send vertex attributes to fragment shader + fragTexCoord = vertexTexCoord; + fragNormal = normalize(normalMatrix*vertexNormal); + fragTangent = normalize(normalMatrix*vec3(vertexTangent)); + fragTangent = normalize(fragTangent - dot(fragTangent, fragNormal)*fragNormal); + fragBinormal = normalize(normalMatrix*vertexBinormal); + fragBinormal = cross(fragNormal, fragTangent); + + // Calculate final vertex position + gl_Position = mvp*vec4(vertexPosition, 1.0); +} \ No newline at end of file diff --git a/examples/models/resources/shaders/glsl330/prefilter.fs b/examples/models/resources/shaders/glsl330/prefilter.fs new file mode 100644 index 000000000..9439810d7 --- /dev/null +++ b/examples/models/resources/shaders/glsl330/prefilter.fs @@ -0,0 +1,120 @@ +/******************************************************************************************* +* +* rPBR [shader] - Prefiltered environment for reflections fragment shader +* +* Copyright (c) 2017 Victor Fisac +* +**********************************************************************************************/ + +#version 330 +#define MAX_SAMPLES 1024u +#define CUBEMAP_RESOLUTION 1024.0 + +// Input vertex attributes (from vertex shader) +in vec3 fragPosition; + +// Input uniform values +uniform samplerCube environmentMap; +uniform float roughness; + +// Constant values +const float PI = 3.14159265359f; + +// Output fragment color +out vec4 finalColor; + +float DistributionGGX(vec3 N, vec3 H, float roughness); +float RadicalInverse_VdC(uint bits); +vec2 Hammersley(uint i, uint N); +vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness); + +float DistributionGGX(vec3 N, vec3 H, float roughness) +{ + float a = roughness*roughness; + float a2 = a*a; + float NdotH = max(dot(N, H), 0.0); + float NdotH2 = NdotH*NdotH; + + float nom = a2; + float denom = (NdotH2*(a2 - 1.0) + 1.0); + denom = PI*denom*denom; + + return nom/denom; +} + +float RadicalInverse_VdC(uint bits) +{ + bits = (bits << 16u) | (bits >> 16u); + bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); + bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); + bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); + bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); + return float(bits) * 2.3283064365386963e-10; // / 0x100000000 +} + +vec2 Hammersley(uint i, uint N) +{ + return vec2(float(i)/float(N), RadicalInverse_VdC(i)); +} + +vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness) +{ + float a = roughness*roughness; + float phi = 2.0 * PI * Xi.x; + float cosTheta = sqrt((1.0 - Xi.y)/(1.0 + (a*a - 1.0)*Xi.y)); + float sinTheta = sqrt(1.0 - cosTheta*cosTheta); + + // Transform from spherical coordinates to cartesian coordinates (halfway vector) + vec3 H = vec3(cos(phi)*sinTheta, sin(phi)*sinTheta, cosTheta); + + // Transform from tangent space H vector to world space sample vector + vec3 up = ((abs(N.z) < 0.999) ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0)); + vec3 tangent = normalize(cross(up, N)); + vec3 bitangent = cross(N, tangent); + vec3 sampleVec = tangent*H.x + bitangent*H.y + N*H.z; + + return normalize(sampleVec); +} + +void main() +{ + // Make the simplyfying assumption that V equals R equals the normal + vec3 N = normalize(fragPosition); + vec3 R = N; + vec3 V = R; + + vec3 prefilteredColor = vec3(0.0); + float totalWeight = 0.0; + + for (uint i = 0u; i < MAX_SAMPLES; i++) + { + // Generate a sample vector that's biased towards the preferred alignment direction (importance sampling) + vec2 Xi = Hammersley(i, MAX_SAMPLES); + vec3 H = ImportanceSampleGGX(Xi, N, roughness); + vec3 L = normalize(2.0*dot(V, H)*H - V); + + float NdotL = max(dot(N, L), 0.0); + if(NdotL > 0.0) + { + // Sample from the environment's mip level based on roughness/pdf + float D = DistributionGGX(N, H, roughness); + float NdotH = max(dot(N, H), 0.0); + float HdotV = max(dot(H, V), 0.0); + float pdf = D*NdotH/(4.0*HdotV) + 0.0001; + + float resolution = CUBEMAP_RESOLUTION; + float saTexel = 4.0*PI/(6.0*resolution*resolution); + float saSample = 1.0/(float(MAX_SAMPLES)*pdf + 0.0001); + float mipLevel = ((roughness == 0.0) ? 0.0 : 0.5*log2(saSample/saTexel)); + + prefilteredColor += textureLod(environmentMap, L, mipLevel).rgb*NdotL; + totalWeight += NdotL; + } + } + + // Calculate prefilter average color + prefilteredColor = prefilteredColor/totalWeight; + + // Calculate final fragment color + finalColor = vec4(prefilteredColor, 1.0); +} diff --git a/examples/models/resources/shaders/glsl330/skybox.fs b/examples/models/resources/shaders/glsl330/skybox.fs new file mode 100644 index 000000000..053a2517e --- /dev/null +++ b/examples/models/resources/shaders/glsl330/skybox.fs @@ -0,0 +1,31 @@ +/******************************************************************************************* +* +* rPBR [shader] - Background skybox fragment shader +* +* Copyright (c) 2017 Victor Fisac +* +**********************************************************************************************/ + +#version 330 + +// Input vertex attributes (from vertex shader) +in vec3 fragPosition; + +// Input uniform values +uniform samplerCube environmentMap; + +// Output fragment color +out vec4 finalColor; + +void main() +{ + // Fetch color from texture map + vec3 color = texture(environmentMap, fragPosition).rgb; + + // Apply gamma correction + color = color/(color + vec3(1.0)); + color = pow(color, vec3(1.0/2.2)); + + // Calculate final fragment color + finalColor = vec4(color, 1.0); +} diff --git a/examples/models/resources/shaders/glsl330/skybox.vs b/examples/models/resources/shaders/glsl330/skybox.vs new file mode 100644 index 000000000..4fe9a2c30 --- /dev/null +++ b/examples/models/resources/shaders/glsl330/skybox.vs @@ -0,0 +1,32 @@ +/******************************************************************************************* +* +* rPBR [shader] - Background skybox vertex shader +* +* Copyright (c) 2017 Victor Fisac +* +**********************************************************************************************/ + +#version 330 + +// Input vertex attributes +in vec3 vertexPosition; + +// Input uniform values +uniform mat4 projection; +uniform mat4 view; + +// Output vertex attributes (to fragment shader) +out vec3 fragPosition; + +void main() +{ + // Calculate fragment position based on model transformations + fragPosition = vertexPosition; + + // Remove translation from the view matrix + mat4 rotView = mat4(mat3(view)); + vec4 clipPos = projection*rotView*vec4(vertexPosition, 1.0); + + // Calculate final vertex position + gl_Position = clipPos.xyzw; +} diff --git a/examples/models/resources/solar_system/2k_ceres_fictional.png b/examples/models/resources/solar_system/2k_ceres_fictional.png new file mode 100644 index 000000000..04f97dd13 Binary files /dev/null and b/examples/models/resources/solar_system/2k_ceres_fictional.png differ diff --git a/examples/models/resources/solar_system/2k_earth_clouds.png b/examples/models/resources/solar_system/2k_earth_clouds.png new file mode 100644 index 000000000..538a02e8f Binary files /dev/null and b/examples/models/resources/solar_system/2k_earth_clouds.png differ diff --git a/examples/models/resources/solar_system/2k_earth_daymap.png b/examples/models/resources/solar_system/2k_earth_daymap.png new file mode 100644 index 000000000..56dcd2cd0 Binary files /dev/null and b/examples/models/resources/solar_system/2k_earth_daymap.png differ diff --git a/examples/models/resources/solar_system/2k_earth_nightmap.png b/examples/models/resources/solar_system/2k_earth_nightmap.png new file mode 100644 index 000000000..c568b5437 Binary files /dev/null and b/examples/models/resources/solar_system/2k_earth_nightmap.png differ diff --git a/examples/models/resources/solar_system/2k_earth_normal_map.tif b/examples/models/resources/solar_system/2k_earth_normal_map.tif new file mode 100644 index 000000000..0b843470b Binary files /dev/null and b/examples/models/resources/solar_system/2k_earth_normal_map.tif differ diff --git a/examples/models/resources/solar_system/2k_earth_specular_map.tif b/examples/models/resources/solar_system/2k_earth_specular_map.tif new file mode 100644 index 000000000..f5b57f808 Binary files /dev/null and b/examples/models/resources/solar_system/2k_earth_specular_map.tif differ diff --git a/examples/models/resources/solar_system/2k_eris_fictional.png b/examples/models/resources/solar_system/2k_eris_fictional.png new file mode 100644 index 000000000..03a817901 Binary files /dev/null and b/examples/models/resources/solar_system/2k_eris_fictional.png differ diff --git a/examples/models/resources/solar_system/2k_haumea_fictional.png b/examples/models/resources/solar_system/2k_haumea_fictional.png new file mode 100644 index 000000000..f300c3828 Binary files /dev/null and b/examples/models/resources/solar_system/2k_haumea_fictional.png differ diff --git a/examples/models/resources/solar_system/2k_jupiter.png b/examples/models/resources/solar_system/2k_jupiter.png new file mode 100644 index 000000000..7beeaade9 Binary files /dev/null and b/examples/models/resources/solar_system/2k_jupiter.png differ diff --git a/examples/models/resources/solar_system/2k_makemake_fictional.png b/examples/models/resources/solar_system/2k_makemake_fictional.png new file mode 100644 index 000000000..e4c5c6223 Binary files /dev/null and b/examples/models/resources/solar_system/2k_makemake_fictional.png differ diff --git a/examples/models/resources/solar_system/2k_mars.png b/examples/models/resources/solar_system/2k_mars.png new file mode 100644 index 000000000..c2fe6658a Binary files /dev/null and b/examples/models/resources/solar_system/2k_mars.png differ diff --git a/examples/models/resources/solar_system/2k_mercury.png b/examples/models/resources/solar_system/2k_mercury.png new file mode 100644 index 000000000..e7f0cc7b2 Binary files /dev/null and b/examples/models/resources/solar_system/2k_mercury.png differ diff --git a/examples/models/resources/solar_system/2k_moon.png b/examples/models/resources/solar_system/2k_moon.png new file mode 100644 index 000000000..3ab63f24c Binary files /dev/null and b/examples/models/resources/solar_system/2k_moon.png differ diff --git a/examples/models/resources/solar_system/2k_neptune.png b/examples/models/resources/solar_system/2k_neptune.png new file mode 100644 index 000000000..94382adf4 Binary files /dev/null and b/examples/models/resources/solar_system/2k_neptune.png differ diff --git a/examples/models/resources/solar_system/2k_saturn.png b/examples/models/resources/solar_system/2k_saturn.png new file mode 100644 index 000000000..d3f06f1c3 Binary files /dev/null and b/examples/models/resources/solar_system/2k_saturn.png differ diff --git a/examples/models/resources/solar_system/2k_saturn_ring_alpha.png b/examples/models/resources/solar_system/2k_saturn_ring_alpha.png new file mode 100644 index 000000000..cd69aa9de Binary files /dev/null and b/examples/models/resources/solar_system/2k_saturn_ring_alpha.png differ diff --git a/examples/models/resources/solar_system/2k_stars.png b/examples/models/resources/solar_system/2k_stars.png new file mode 100644 index 000000000..4588deeb7 Binary files /dev/null and b/examples/models/resources/solar_system/2k_stars.png differ diff --git a/examples/models/resources/solar_system/2k_stars_milky_way.png b/examples/models/resources/solar_system/2k_stars_milky_way.png new file mode 100644 index 000000000..36d7cd1cf Binary files /dev/null and b/examples/models/resources/solar_system/2k_stars_milky_way.png differ diff --git a/examples/models/resources/solar_system/2k_sun.png b/examples/models/resources/solar_system/2k_sun.png new file mode 100644 index 000000000..7bf7f0fd8 Binary files /dev/null and b/examples/models/resources/solar_system/2k_sun.png differ diff --git a/examples/models/resources/solar_system/2k_uranus.png b/examples/models/resources/solar_system/2k_uranus.png new file mode 100644 index 000000000..522f46fa5 Binary files /dev/null and b/examples/models/resources/solar_system/2k_uranus.png differ diff --git a/examples/models/resources/solar_system/2k_venus_atmosphere.png b/examples/models/resources/solar_system/2k_venus_atmosphere.png new file mode 100644 index 000000000..23795c3e9 Binary files /dev/null and b/examples/models/resources/solar_system/2k_venus_atmosphere.png differ diff --git a/examples/models/resources/solar_system/2k_venus_surface.png b/examples/models/resources/solar_system/2k_venus_surface.png new file mode 100644 index 000000000..d70257ac6 Binary files /dev/null and b/examples/models/resources/solar_system/2k_venus_surface.png differ diff --git a/examples/models/resources/solar_system/README b/examples/models/resources/solar_system/README new file mode 100644 index 000000000..473041d68 --- /dev/null +++ b/examples/models/resources/solar_system/README @@ -0,0 +1,4 @@ +All textures from Solar System Scope [https://www.solarsystemscope.com/textures/] + +Distributed under Attribution 4.0 International license: +You may use, adapt, and share these textures for any purpose, even commercially. diff --git a/examples/models/resources/solar_system/sphere.obj b/examples/models/resources/solar_system/sphere.obj new file mode 100644 index 000000000..82d839880 --- /dev/null +++ b/examples/models/resources/solar_system/sphere.obj @@ -0,0 +1,10231 @@ +# Blender v2.79 (sub 0) OBJ File: 'sphere.blend' +# www.blender.org +o Sphere +v 0.000000 0.995185 -0.098017 +v 0.000000 0.980785 -0.195090 +v 0.000000 0.956940 -0.290285 +v 0.000000 0.923880 -0.382683 +v 0.000000 0.881921 -0.471397 +v 0.000000 0.831470 -0.555570 +v 0.000000 0.773010 -0.634393 +v 0.000000 0.707107 -0.707107 +v 0.000000 0.634393 -0.773010 +v 0.000000 0.555570 -0.831470 +v 0.000000 0.382683 -0.923880 +v 0.000000 0.290285 -0.956940 +v 0.000000 0.195090 -0.980785 +v 0.000000 0.098017 -0.995185 +v 0.000000 -0.000000 -1.000000 +v 0.000000 -0.098017 -0.995185 +v 0.000000 -0.290285 -0.956940 +v 0.000000 -0.471397 -0.881921 +v 0.000000 -0.555571 -0.831469 +v 0.000000 -0.634394 -0.773010 +v 0.000000 -0.707107 -0.707106 +v 0.000000 -0.773011 -0.634393 +v 0.000000 -0.831470 -0.555570 +v 0.000000 -0.881922 -0.471396 +v 0.000000 -0.956941 -0.290284 +v 0.009607 0.995185 -0.097545 +v 0.019122 0.980785 -0.194151 +v 0.028453 0.956940 -0.288887 +v 0.037510 0.923880 -0.380841 +v 0.046205 0.881921 -0.469127 +v 0.054455 0.831470 -0.552895 +v 0.062181 0.773010 -0.631338 +v 0.069309 0.707107 -0.703702 +v 0.075768 0.634393 -0.769288 +v 0.081498 0.555570 -0.827466 +v 0.086443 0.471397 -0.877675 +v 0.090556 0.382683 -0.919431 +v 0.093797 0.290285 -0.952332 +v 0.096134 0.195090 -0.976063 +v 0.097545 0.098017 -0.990393 +v 0.098017 -0.000000 -0.995185 +v 0.097545 -0.098017 -0.990393 +v 0.096134 -0.195091 -0.976062 +v 0.093797 -0.290285 -0.952332 +v 0.090556 -0.382684 -0.919431 +v 0.086443 -0.471397 -0.877674 +v 0.081498 -0.555571 -0.827466 +v 0.075768 -0.634394 -0.769288 +v 0.069309 -0.707107 -0.703701 +v 0.062181 -0.773011 -0.631338 +v 0.054455 -0.831470 -0.552895 +v 0.046205 -0.881922 -0.469126 +v 0.037510 -0.923880 -0.380840 +v 0.028453 -0.956941 -0.288886 +v 0.019122 -0.980785 -0.194150 +v 0.009607 -0.995185 -0.097544 +v 0.019122 0.995185 -0.096134 +v 0.038060 0.980785 -0.191342 +v 0.056632 0.956940 -0.284707 +v 0.074658 0.923880 -0.375330 +v 0.091965 0.881921 -0.462339 +v 0.108387 0.831470 -0.544895 +v 0.123764 0.773010 -0.622204 +v 0.137950 0.707107 -0.693520 +v 0.150807 0.634393 -0.758157 +v 0.162212 0.555570 -0.815493 +v 0.172054 0.471397 -0.864975 +v 0.180240 0.382683 -0.906127 +v 0.186690 0.290285 -0.938553 +v 0.191342 0.195090 -0.961940 +v 0.194151 0.098017 -0.976062 +v 0.195090 -0.000000 -0.980785 +v 0.194151 -0.098017 -0.976062 +v 0.191342 -0.195091 -0.961940 +v 0.186690 -0.290285 -0.938553 +v 0.180240 -0.382684 -0.906127 +v 0.172054 -0.471397 -0.864975 +v 0.162212 -0.555571 -0.815493 +v 0.150807 -0.634394 -0.758157 +v 0.137950 -0.707107 -0.693520 +v 0.123764 -0.773011 -0.622203 +v 0.108386 -0.831470 -0.544895 +v 0.091965 -0.881922 -0.462338 +v 0.074658 -0.923880 -0.375330 +v 0.056632 -0.956941 -0.284706 +v 0.038060 -0.980785 -0.191341 +v 0.019122 -0.995185 -0.096133 +v 0.028453 0.995185 -0.093797 +v 0.056632 0.980785 -0.186690 +v 0.084265 0.956940 -0.277785 +v 0.111087 0.923880 -0.366205 +v 0.136839 0.881921 -0.451099 +v 0.161274 0.831470 -0.531648 +v 0.184155 0.773010 -0.607076 +v 0.205262 0.707107 -0.676659 +v 0.224393 0.634393 -0.739725 +v 0.241363 0.555570 -0.795667 +v 0.256008 0.471397 -0.843946 +v 0.268188 0.382683 -0.884098 +v 0.277785 0.290285 -0.915735 +v 0.284707 0.195090 -0.938553 +v 0.288887 0.098017 -0.952332 +v 0.290285 -0.000000 -0.956940 +v 0.288887 -0.098017 -0.952332 +v 0.284707 -0.195091 -0.938553 +v 0.277785 -0.290285 -0.915735 +v 0.268188 -0.382684 -0.884097 +v 0.256008 -0.471397 -0.843946 +v 0.241363 -0.555571 -0.795667 +v 0.224393 -0.634394 -0.739725 +v 0.205262 -0.707107 -0.676659 +v 0.184155 -0.773011 -0.607076 +v 0.161274 -0.831470 -0.531647 +v 0.136839 -0.881922 -0.451098 +v 0.111087 -0.923880 -0.366205 +v 0.084265 -0.956941 -0.277784 +v 0.056632 -0.980785 -0.186689 +v 0.028453 -0.995185 -0.093796 +v 0.037510 0.995185 -0.090556 +v 0.074658 0.980785 -0.180240 +v 0.111087 0.956940 -0.268188 +v 0.146447 0.923880 -0.353553 +v 0.180396 0.881921 -0.435514 +v 0.212608 0.831470 -0.513280 +v 0.242772 0.773010 -0.586103 +v 0.270598 0.707107 -0.653281 +v 0.295819 0.634393 -0.714168 +v 0.318190 0.555570 -0.768178 +v 0.337497 0.471397 -0.814789 +v 0.353554 0.382683 -0.853553 +v 0.366206 0.290285 -0.884098 +v 0.375331 0.195090 -0.906127 +v 0.380841 0.098017 -0.919431 +v 0.382684 -0.000000 -0.923880 +v 0.380841 -0.098017 -0.919431 +v 0.375331 -0.195091 -0.906127 +v 0.366205 -0.290285 -0.884098 +v 0.353554 -0.382684 -0.853553 +v 0.337497 -0.471397 -0.814789 +v 0.318190 -0.555571 -0.768178 +v 0.295819 -0.634394 -0.714168 +v 0.270598 -0.707107 -0.653281 +v 0.242772 -0.773011 -0.586102 +v 0.212608 -0.831470 -0.513279 +v 0.180396 -0.881922 -0.435513 +v 0.146447 -0.923880 -0.353553 +v 0.111087 -0.956941 -0.268187 +v 0.074658 -0.980785 -0.180239 +v 0.037510 -0.995185 -0.090555 +v 0.046205 0.995185 -0.086443 +v 0.091965 0.980785 -0.172054 +v 0.136840 0.956940 -0.256008 +v 0.180396 0.923880 -0.337497 +v 0.222215 0.881921 -0.415735 +v 0.261894 0.831470 -0.489969 +v 0.299051 0.773010 -0.559485 +v 0.333328 0.707107 -0.623612 +v 0.364395 0.634393 -0.681734 +v 0.391952 0.555570 -0.733291 +v 0.415735 0.471397 -0.777785 +v 0.435514 0.382683 -0.814789 +v 0.451099 0.290285 -0.843946 +v 0.462339 0.195090 -0.864975 +v 0.469127 0.098017 -0.877674 +v 0.471397 -0.000000 -0.881921 +v 0.469127 -0.098017 -0.877674 +v 0.462339 -0.195091 -0.864975 +v 0.451099 -0.290285 -0.843946 +v 0.435514 -0.382684 -0.814789 +v 0.415735 -0.471397 -0.777785 +v 0.391952 -0.555571 -0.733290 +v 0.364395 -0.634394 -0.681734 +v 0.333328 -0.707107 -0.623612 +v 0.299051 -0.773011 -0.559484 +v 0.261894 -0.831470 -0.489969 +v 0.222215 -0.881922 -0.415734 +v 0.180396 -0.923880 -0.337496 +v 0.136839 -0.956941 -0.256008 +v 0.091965 -0.980785 -0.172054 +v 0.046205 -0.995185 -0.086443 +v 0.054456 0.995185 -0.081498 +v 0.108387 0.980785 -0.162212 +v 0.161274 0.956940 -0.241363 +v 0.212608 0.923880 -0.318190 +v 0.261894 0.881921 -0.391952 +v 0.308659 0.831470 -0.461940 +v 0.352450 0.773010 -0.527479 +v 0.392848 0.707107 -0.587938 +v 0.429462 0.634393 -0.642735 +v 0.461940 0.555570 -0.691342 +v 0.489970 0.471397 -0.733290 +v 0.513280 0.382683 -0.768178 +v 0.531648 0.290285 -0.795667 +v 0.544896 0.195090 -0.815493 +v 0.552895 0.098017 -0.827466 +v 0.555571 -0.000000 -0.831470 +v 0.552895 -0.098017 -0.827466 +v 0.544896 -0.195091 -0.815493 +v 0.531648 -0.290285 -0.795667 +v 0.513280 -0.382684 -0.768178 +v 0.489970 -0.471397 -0.733290 +v 0.461940 -0.555571 -0.691341 +v 0.429462 -0.634394 -0.642734 +v 0.392848 -0.707107 -0.587937 +v 0.352450 -0.773011 -0.527478 +v 0.308658 -0.831470 -0.461939 +v 0.261894 -0.881922 -0.391951 +v 0.212608 -0.923880 -0.318189 +v 0.161274 -0.956941 -0.241362 +v 0.108386 -0.980785 -0.162211 +v 0.054455 -0.995185 -0.081497 +v 0.062182 0.995185 -0.075768 +v 0.123765 0.980785 -0.150807 +v 0.184155 0.956940 -0.224393 +v 0.242772 0.923880 -0.295818 +v 0.299051 0.881921 -0.364394 +v 0.352451 0.831470 -0.429461 +v 0.402455 0.773010 -0.490392 +v 0.448584 0.707107 -0.546601 +v 0.490393 0.634393 -0.597545 +v 0.527479 0.555570 -0.642735 +v 0.559485 0.471397 -0.681734 +v 0.586103 0.382683 -0.714168 +v 0.607077 0.290285 -0.739725 +v 0.622204 0.195090 -0.758157 +v 0.631339 0.098017 -0.769288 +v 0.634394 -0.000000 -0.773010 +v 0.631339 -0.098017 -0.769288 +v 0.622204 -0.195091 -0.758157 +v 0.607077 -0.290285 -0.739725 +v 0.586103 -0.382684 -0.714168 +v 0.559485 -0.471397 -0.681734 +v 0.527479 -0.555571 -0.642734 +v 0.490393 -0.634394 -0.597545 +v 0.448584 -0.707107 -0.546600 +v 0.402455 -0.773011 -0.490392 +v 0.352450 -0.831470 -0.429461 +v 0.299051 -0.881922 -0.364394 +v 0.242772 -0.923880 -0.295818 +v 0.184155 -0.956941 -0.224392 +v 0.123764 -0.980785 -0.150806 +v 0.062181 -0.995185 -0.075767 +v 0.069309 0.995185 -0.069308 +v 0.137950 0.980785 -0.137949 +v 0.205263 0.956940 -0.205262 +v 0.270599 0.923880 -0.270598 +v 0.333328 0.881921 -0.333328 +v 0.392848 0.831470 -0.392847 +v 0.448584 0.773010 -0.448584 +v 0.500001 0.707107 -0.500000 +v 0.546601 0.634393 -0.546601 +v 0.587938 0.555570 -0.587938 +v 0.623613 0.471397 -0.623612 +v 0.653282 0.382683 -0.653281 +v 0.676660 0.290285 -0.676659 +v 0.693520 0.195090 -0.693520 +v 0.703702 0.098017 -0.703702 +v 0.707107 -0.000000 -0.707107 +v 0.703702 -0.098017 -0.703702 +v 0.693520 -0.195091 -0.693520 +v 0.676660 -0.290285 -0.676659 +v 0.653282 -0.382684 -0.653281 +v 0.623613 -0.471397 -0.623612 +v 0.587938 -0.555571 -0.587937 +v 0.546601 -0.634394 -0.546600 +v 0.500000 -0.707107 -0.499999 +v 0.448584 -0.773011 -0.448583 +v 0.392848 -0.831470 -0.392847 +v 0.333328 -0.881922 -0.333327 +v 0.270598 -0.923880 -0.270597 +v 0.205262 -0.956941 -0.205262 +v 0.137950 -0.980785 -0.137949 +v 0.069309 -0.995185 -0.069308 +v 0.075769 0.995185 -0.062181 +v 0.150807 0.980785 -0.123764 +v 0.224394 0.956940 -0.184154 +v 0.295819 0.923880 -0.242771 +v 0.364395 0.881921 -0.299051 +v 0.429462 0.831470 -0.352450 +v 0.490393 0.773010 -0.402455 +v 0.546602 0.707107 -0.448583 +v 0.597546 0.634393 -0.490392 +v 0.642735 0.555570 -0.527478 +v 0.681735 0.471397 -0.559485 +v 0.714169 0.382683 -0.586103 +v 0.739726 0.290285 -0.607076 +v 0.758158 0.195090 -0.622203 +v 0.769289 0.098017 -0.631338 +v 0.773011 -0.000000 -0.634393 +v 0.769289 -0.098017 -0.631338 +v 0.758158 -0.195091 -0.622203 +v 0.739725 -0.290285 -0.607076 +v 0.714169 -0.382684 -0.586103 +v 0.681735 -0.471397 -0.559485 +v 0.642735 -0.555571 -0.527478 +v 0.597546 -0.634394 -0.490392 +v 0.546601 -0.707107 -0.448583 +v 0.490393 -0.773011 -0.402454 +v 0.429462 -0.831470 -0.352449 +v 0.364395 -0.881922 -0.299050 +v 0.295818 -0.923880 -0.242771 +v 0.224393 -0.956941 -0.184154 +v 0.150807 -0.980785 -0.123763 +v 0.075768 -0.995185 -0.062181 +v 0.081499 0.995185 -0.054455 +v 0.162212 0.980785 -0.108386 +v 0.241364 0.956940 -0.161273 +v 0.318190 0.923880 -0.212607 +v 0.391953 0.881921 -0.261894 +v 0.461940 0.831470 -0.308658 +v 0.527479 0.773010 -0.352450 +v 0.587938 0.707107 -0.392847 +v 0.642735 0.634393 -0.429461 +v 0.691342 0.555570 -0.461939 +v 0.733291 0.471397 -0.489969 +v 0.768178 0.382683 -0.513279 +v 0.795668 0.290285 -0.531647 +v 0.815494 0.195090 -0.544895 +v 0.827466 0.098017 -0.552895 +v 0.831470 -0.000000 -0.555570 +v 0.827466 -0.098017 -0.552895 +v 0.815494 -0.195091 -0.544895 +v 0.795667 -0.290285 -0.531647 +v 0.768178 -0.382684 -0.513280 +v 0.733291 -0.471397 -0.489969 +v 0.691342 -0.555571 -0.461939 +v 0.642735 -0.634394 -0.429461 +v 0.587938 -0.707107 -0.392847 +v 0.527479 -0.773011 -0.352449 +v 0.461940 -0.831470 -0.308658 +v 0.391952 -0.881922 -0.261893 +v 0.318190 -0.923880 -0.212607 +v 0.241363 -0.956941 -0.161273 +v 0.162212 -0.980785 -0.108386 +v 0.081498 -0.995185 -0.054455 +v 0.086444 0.995185 -0.046204 +v 0.172055 0.980785 -0.091965 +v 0.256009 0.956940 -0.136839 +v 0.337497 0.923880 -0.180395 +v 0.415736 0.881921 -0.222214 +v 0.489970 0.831470 -0.261894 +v 0.559486 0.773010 -0.299051 +v 0.623613 0.707107 -0.333327 +v 0.681735 0.634393 -0.364394 +v 0.733291 0.555570 -0.391952 +v 0.777786 0.471397 -0.415734 +v 0.814789 0.382683 -0.435513 +v 0.843947 0.290285 -0.451098 +v 0.864976 0.195090 -0.462339 +v 0.877675 0.098017 -0.469126 +v 0.881922 -0.000000 -0.471396 +v 0.877675 -0.098017 -0.469126 +v 0.864976 -0.195091 -0.462339 +v 0.843947 -0.290285 -0.451098 +v 0.814789 -0.382684 -0.435513 +v 0.777786 -0.471397 -0.415734 +v 0.733291 -0.555571 -0.391951 +v 0.681735 -0.634394 -0.364394 +v 0.623613 -0.707107 -0.333327 +v 0.559485 -0.773011 -0.299050 +v 0.489970 -0.831470 -0.261893 +v 0.415735 -0.881922 -0.222214 +v 0.337497 -0.923880 -0.180395 +v 0.256008 -0.956941 -0.136839 +v 0.172054 -0.980785 -0.091964 +v 0.086443 -0.995185 -0.046204 +v 0.090557 0.995185 -0.037509 +v 0.180241 0.980785 -0.074657 +v 0.268189 0.956940 -0.111087 +v 0.353554 0.923880 -0.146446 +v 0.435515 0.881921 -0.180395 +v 0.513281 0.831470 -0.212607 +v 0.586104 0.773010 -0.242771 +v 0.653282 0.707107 -0.270598 +v 0.714169 0.634393 -0.295818 +v 0.768178 0.555570 -0.318189 +v 0.814790 0.471397 -0.337496 +v 0.853554 0.382683 -0.353553 +v 0.884098 0.290285 -0.366205 +v 0.906128 0.195090 -0.375330 +v 0.919431 0.098017 -0.380840 +v 0.923880 -0.000000 -0.382683 +v 0.919431 -0.098017 -0.380840 +v 0.906128 -0.195091 -0.375330 +v 0.884098 -0.290285 -0.366205 +v 0.853554 -0.382684 -0.353553 +v 0.814789 -0.471397 -0.337496 +v 0.768178 -0.555571 -0.318189 +v 0.714169 -0.634394 -0.295818 +v 0.653282 -0.707107 -0.270597 +v 0.586103 -0.773011 -0.242771 +v 0.513280 -0.831470 -0.212607 +v 0.435514 -0.881922 -0.180395 +v 0.353554 -0.923880 -0.146446 +v 0.268188 -0.956941 -0.111086 +v 0.180240 -0.980785 -0.074657 +v 0.090556 -0.995185 -0.037509 +v 0.093797 0.995185 -0.028452 +v 0.186691 0.980785 -0.056631 +v 0.277786 0.956940 -0.084265 +v 0.366206 0.923880 -0.111087 +v 0.451099 0.881921 -0.136839 +v 0.531648 0.831470 -0.161273 +v 0.607077 0.773010 -0.184154 +v 0.676660 0.707107 -0.205262 +v 0.739726 0.634393 -0.224393 +v 0.795667 0.555570 -0.241362 +v 0.843947 0.471397 -0.256008 +v 0.884098 0.382683 -0.268187 +v 0.915736 0.290285 -0.277785 +v 0.938554 0.195090 -0.284707 +v 0.952333 0.098017 -0.288886 +v 0.956941 -0.000000 -0.290284 +v 0.952333 -0.098017 -0.288886 +v 0.938554 -0.195091 -0.284706 +v 0.915735 -0.290285 -0.277785 +v 0.884098 -0.382684 -0.268188 +v 0.843947 -0.471397 -0.256008 +v 0.795667 -0.555571 -0.241362 +v 0.739725 -0.634394 -0.224392 +v 0.676659 -0.707107 -0.205262 +v 0.607077 -0.773011 -0.184154 +v 0.531648 -0.831470 -0.161273 +v 0.451099 -0.881922 -0.136838 +v 0.366205 -0.923880 -0.111086 +v 0.277785 -0.956941 -0.084264 +v 0.186690 -0.980785 -0.056631 +v 0.093797 -0.995185 -0.028452 +v 0.096135 0.995185 -0.019122 +v 0.191343 0.980785 -0.038060 +v 0.284708 0.956940 -0.056631 +v 0.375331 0.923880 -0.074657 +v 0.462340 0.881921 -0.091964 +v 0.544896 0.831470 -0.108386 +v 0.622204 0.773010 -0.123763 +v 0.693521 0.707107 -0.137949 +v 0.758158 0.634393 -0.150806 +v 0.815494 0.555570 -0.162211 +v 0.864976 0.471397 -0.172054 +v 0.906128 0.382683 -0.180239 +v 0.938554 0.290285 -0.186689 +v 0.961940 0.195090 -0.191341 +v 0.976063 0.098017 -0.194150 +v 0.980786 -0.000000 -0.195090 +v 0.976063 -0.098017 -0.194150 +v 0.961940 -0.195091 -0.191341 +v 0.938554 -0.290285 -0.186689 +v 0.906128 -0.382684 -0.180239 +v 0.864976 -0.471397 -0.172054 +v 0.815493 -0.555571 -0.162211 +v 0.758158 -0.634394 -0.150806 +v 0.693520 -0.707107 -0.137949 +v 0.622204 -0.773011 -0.123763 +v 0.544895 -0.831470 -0.108386 +v 0.462339 -0.881922 -0.091964 +v 0.375330 -0.923880 -0.074657 +v 0.284707 -0.956941 -0.056631 +v 0.191342 -0.980785 -0.038059 +v 0.096134 -0.995185 -0.019121 +v 0.097546 0.995185 -0.009607 +v 0.194152 0.980785 -0.019121 +v 0.288888 0.956940 -0.028452 +v 0.380842 0.923880 -0.037509 +v 0.469128 0.881921 -0.046204 +v 0.552896 0.831470 -0.054455 +v 0.631339 0.773010 -0.062181 +v 0.703703 0.707107 -0.069308 +v 0.769289 0.634393 -0.075768 +v 0.827466 0.555570 -0.081498 +v 0.877675 0.471397 -0.086443 +v 0.919431 0.382683 -0.090555 +v 0.952333 0.290285 -0.093796 +v 0.976063 0.195090 -0.096133 +v 0.990393 0.098017 -0.097544 +v 0.995185 -0.000000 -0.098017 +v 0.990393 -0.098017 -0.097544 +v 0.976063 -0.195091 -0.096133 +v 0.952333 -0.290285 -0.093796 +v 0.919431 -0.382684 -0.090555 +v 0.877675 -0.471397 -0.086443 +v 0.827466 -0.555571 -0.081498 +v 0.769289 -0.634394 -0.075768 +v 0.703702 -0.707107 -0.069308 +v 0.631339 -0.773011 -0.062181 +v 0.552895 -0.831470 -0.054455 +v 0.469127 -0.881922 -0.046204 +v 0.380841 -0.923880 -0.037509 +v 0.288887 -0.956941 -0.028452 +v 0.194151 -0.980785 -0.019121 +v 0.097545 -0.995185 -0.009607 +v 0.098018 0.995185 0.000001 +v 0.195091 0.980785 0.000001 +v 0.290286 0.956940 0.000001 +v 0.382684 0.923880 0.000001 +v 0.471398 0.881921 0.000001 +v 0.555571 0.831470 0.000001 +v 0.634394 0.773010 0.000001 +v 0.707107 0.707107 0.000001 +v 0.773011 0.634393 0.000001 +v 0.831470 0.555570 0.000001 +v 0.881922 0.471397 0.000001 +v 0.923880 0.382683 0.000001 +v 0.956941 0.290285 0.000001 +v 0.980786 0.195090 0.000001 +v 0.995185 0.098017 0.000001 +v 1.000001 -0.000000 0.000001 +v 0.995185 -0.098017 0.000001 +v 0.980786 -0.195091 0.000001 +v 0.956941 -0.290285 0.000001 +v 0.923880 -0.382684 0.000001 +v 0.881922 -0.471397 0.000001 +v 0.831470 -0.555571 0.000001 +v 0.773011 -0.634394 0.000001 +v 0.707107 -0.707107 0.000001 +v 0.634394 -0.773011 0.000001 +v 0.555570 -0.831470 0.000001 +v 0.471397 -0.881922 0.000001 +v 0.382684 -0.923880 0.000001 +v 0.290285 -0.956941 0.000001 +v 0.195090 -0.980785 0.000001 +v 0.098017 -0.995185 0.000001 +v 0.097546 0.995185 0.009608 +v 0.194152 0.980785 0.019123 +v 0.288888 0.956940 0.028454 +v 0.380842 0.923880 0.037510 +v 0.469128 0.881921 0.046206 +v 0.552896 0.831470 0.054456 +v 0.631339 0.773010 0.062182 +v 0.703703 0.707107 0.069309 +v 0.769289 0.634393 0.075769 +v 0.827466 0.555570 0.081499 +v 0.877675 0.471397 0.086444 +v 0.919431 0.382683 0.090557 +v 0.952333 0.290285 0.093797 +v 0.976063 0.195090 0.096134 +v 0.990393 0.098017 0.097546 +v 0.995185 -0.000000 0.098018 +v 0.990393 -0.098017 0.097546 +v 0.976063 -0.195091 0.096135 +v 0.952333 -0.290285 0.093797 +v 0.919431 -0.382684 0.090557 +v 0.877675 -0.471397 0.086444 +v 0.827466 -0.555571 0.081499 +v 0.769288 -0.634394 0.075769 +v 0.703702 -0.707107 0.069309 +v 0.631339 -0.773011 0.062182 +v 0.552895 -0.831470 0.054456 +v 0.469127 -0.881922 0.046206 +v 0.380841 -0.923880 0.037510 +v 0.288887 -0.956941 0.028454 +v 0.194151 -0.980785 0.019123 +v 0.097545 -0.995185 0.009608 +v 0.096135 0.995185 0.019123 +v 0.191343 0.980785 0.038061 +v 0.284708 0.956940 0.056633 +v 0.375331 0.923880 0.074659 +v 0.462340 0.881921 0.091966 +v 0.544896 0.831470 0.108387 +v 0.622204 0.773010 0.123765 +v 0.693521 0.707107 0.137951 +v 0.758158 0.634393 0.150808 +v 0.815494 0.555570 0.162213 +v 0.864976 0.471397 0.172055 +v 0.906128 0.382683 0.180241 +v 0.938554 0.290285 0.186691 +v 0.961940 0.195090 0.191343 +v 0.976063 0.098017 0.194152 +v 0.980786 -0.000000 0.195091 +v 0.976063 -0.098017 0.194152 +v 0.961940 -0.195091 0.191343 +v 0.938553 -0.290285 0.186691 +v 0.906128 -0.382684 0.180241 +v 0.864976 -0.471397 0.172055 +v 0.815493 -0.555571 0.162213 +v 0.758157 -0.634394 0.150808 +v 0.693520 -0.707107 0.137951 +v 0.622204 -0.773011 0.123765 +v 0.544895 -0.831470 0.108387 +v 0.462339 -0.881922 0.091966 +v 0.375330 -0.923880 0.074659 +v 0.284707 -0.956941 0.056633 +v 0.191342 -0.980785 0.038061 +v 0.096134 -0.995185 0.019123 +v 0.093797 0.995185 0.028454 +v 0.186691 0.980785 0.056633 +v 0.277786 0.956940 0.084266 +v 0.366206 0.923880 0.111088 +v 0.451099 0.881921 0.136840 +v 0.531648 0.831470 0.161275 +v 0.607077 0.773010 0.184156 +v 0.676660 0.707107 0.205263 +v 0.739725 0.634393 0.224394 +v 0.795667 0.555570 0.241364 +v 0.843946 0.471397 0.256009 +v 0.884098 0.382683 0.268189 +v 0.915735 0.290285 0.277786 +v 0.938554 0.195090 0.284708 +v 0.952333 0.098017 0.288888 +v 0.956941 -0.000000 0.290286 +v 0.952333 -0.098017 0.288888 +v 0.938554 -0.195091 0.284708 +v 0.915735 -0.290285 0.277786 +v 0.884098 -0.382684 0.268189 +v 0.843946 -0.471397 0.256009 +v 0.795667 -0.555571 0.241364 +v 0.739725 -0.634394 0.224394 +v 0.676659 -0.707107 0.205263 +v 0.607077 -0.773011 0.184155 +v 0.531648 -0.831470 0.161274 +v 0.451099 -0.881922 0.136840 +v 0.366205 -0.923880 0.111088 +v 0.277785 -0.956941 0.084266 +v 0.186690 -0.980785 0.056633 +v 0.093797 -0.995185 0.028454 +v 0.090557 0.995185 0.037511 +v 0.180241 0.980785 0.074659 +v 0.268189 0.956940 0.111088 +v 0.353554 0.923880 0.146448 +v 0.435515 0.881921 0.180397 +v 0.513281 0.831470 0.212609 +v 0.586103 0.773010 0.242773 +v 0.653282 0.707107 0.270599 +v 0.714169 0.634393 0.295819 +v 0.768178 0.555570 0.318191 +v 0.814789 0.471397 0.337498 +v 0.853554 0.382683 0.353554 +v 0.884098 0.290285 0.366206 +v 0.906128 0.195090 0.375331 +v 0.919431 0.098017 0.380842 +v 0.923880 -0.000000 0.382684 +v 0.919431 -0.098017 0.380842 +v 0.906128 -0.195091 0.375331 +v 0.884098 -0.290285 0.366206 +v 0.853554 -0.382684 0.353554 +v 0.814789 -0.471397 0.337498 +v 0.768178 -0.555571 0.318191 +v 0.714169 -0.634394 0.295819 +v 0.653282 -0.707107 0.270599 +v 0.586103 -0.773011 0.242773 +v 0.513280 -0.831470 0.212608 +v 0.435514 -0.881922 0.180397 +v 0.353554 -0.923880 0.146447 +v 0.268188 -0.956941 0.111088 +v 0.180240 -0.980785 0.074659 +v 0.090556 -0.995185 0.037510 +v 0.086444 0.995185 0.046206 +v 0.172055 0.980785 0.091966 +v 0.256009 0.956940 0.136841 +v 0.337497 0.923880 0.180397 +v 0.415736 0.881921 0.222216 +v 0.489970 0.831470 0.261895 +v 0.559485 0.773010 0.299052 +v 0.623613 0.707107 0.333329 +v 0.681735 0.634393 0.364396 +v 0.733291 0.555570 0.391953 +v 0.777785 0.471397 0.415736 +v 0.814789 0.382683 0.435515 +v 0.843947 0.290285 0.451100 +v 0.864976 0.195090 0.462340 +v 0.877675 0.098017 0.469128 +v 0.881922 -0.000000 0.471398 +v 0.877675 -0.098017 0.469128 +v 0.864976 -0.195091 0.462340 +v 0.843946 -0.290285 0.451100 +v 0.814789 -0.382684 0.435515 +v 0.777785 -0.471397 0.415736 +v 0.733291 -0.555571 0.391953 +v 0.681735 -0.634394 0.364395 +v 0.623613 -0.707107 0.333329 +v 0.559485 -0.773011 0.299052 +v 0.489969 -0.831470 0.261895 +v 0.415735 -0.881922 0.222216 +v 0.337497 -0.923880 0.180397 +v 0.256008 -0.956941 0.136840 +v 0.172054 -0.980785 0.091966 +v 0.086443 -0.995185 0.046206 +v 0.081499 0.995185 0.054457 +v 0.162212 0.980785 0.108388 +v 0.241364 0.956940 0.161275 +v 0.318190 0.923880 0.212609 +v 0.391953 0.881921 0.261895 +v 0.461940 0.831470 0.308659 +v 0.527479 0.773010 0.352451 +v 0.587938 0.707107 0.392849 +v 0.642735 0.634393 0.429463 +v 0.691342 0.555570 0.461941 +v 0.733291 0.471397 0.489970 +v 0.768178 0.382683 0.513281 +v 0.795667 0.290285 0.531649 +v 0.815494 0.195090 0.544896 +v 0.827466 0.098017 0.552896 +v 0.831470 -0.000000 0.555571 +v 0.827466 -0.098017 0.552896 +v 0.815494 -0.195091 0.544896 +v 0.795667 -0.290285 0.531649 +v 0.768178 -0.382684 0.513281 +v 0.733291 -0.471397 0.489970 +v 0.691342 -0.555571 0.461941 +v 0.642735 -0.634394 0.429462 +v 0.587938 -0.707107 0.392848 +v 0.527479 -0.773011 0.352451 +v 0.461940 -0.831470 0.308659 +v 0.391952 -0.881922 0.261895 +v 0.318190 -0.923880 0.212608 +v 0.241363 -0.956941 0.161274 +v 0.162212 -0.980785 0.108387 +v 0.081498 -0.995185 0.054456 +v 0.075769 0.995185 0.062183 +v 0.150807 0.980785 0.123765 +v 0.224394 0.956940 0.184156 +v 0.295819 0.923880 0.242773 +v 0.364395 0.881921 0.299052 +v 0.429462 0.831470 0.352451 +v 0.490393 0.773010 0.402456 +v 0.546601 0.707107 0.448585 +v 0.597546 0.634393 0.490394 +v 0.642735 0.555570 0.527480 +v 0.681735 0.471397 0.559486 +v 0.714169 0.382683 0.586104 +v 0.739725 0.290285 0.607078 +v 0.758158 0.195090 0.622205 +v 0.769288 0.098017 0.631339 +v 0.773011 -0.000000 0.634394 +v 0.769288 -0.098017 0.631339 +v 0.758158 -0.195091 0.622205 +v 0.739725 -0.290285 0.607078 +v 0.714169 -0.382684 0.586104 +v 0.681735 -0.471397 0.559486 +v 0.642735 -0.555571 0.527480 +v 0.597545 -0.634394 0.490394 +v 0.546601 -0.707107 0.448585 +v 0.490393 -0.773011 0.402456 +v 0.429462 -0.831470 0.352451 +v 0.364395 -0.881922 0.299052 +v 0.295818 -0.923880 0.242773 +v 0.224393 -0.956941 0.184156 +v 0.150807 -0.980785 0.123765 +v 0.075768 -0.995185 0.062182 +v 0.069309 0.995185 0.069310 +v 0.137950 0.980785 0.137951 +v 0.205263 0.956940 0.205264 +v 0.270599 0.923880 0.270599 +v 0.333328 0.881921 0.333329 +v 0.392848 0.831470 0.392849 +v 0.448584 0.773010 0.448585 +v 0.500000 0.707107 0.500001 +v 0.546601 0.634393 0.546602 +v 0.587938 0.555570 0.587939 +v 0.623613 0.471397 0.623614 +v 0.653282 0.382683 0.653282 +v 0.676659 0.290285 0.676660 +v 0.693520 0.195090 0.693521 +v 0.703702 0.098017 0.703703 +v 0.707107 -0.000000 0.707108 +v 0.703702 -0.098017 0.703703 +v 0.693520 -0.195091 0.693521 +v 0.676659 -0.290285 0.676660 +v 0.653282 -0.382684 0.653282 +v 0.623613 -0.471397 0.623613 +v 0.587938 -0.555571 0.587939 +v 0.546601 -0.634394 0.546602 +v 0.500000 -0.707107 0.500001 +v 0.448584 -0.773011 0.448585 +v 0.392848 -0.831470 0.392848 +v 0.333328 -0.881922 0.333329 +v 0.270598 -0.923880 0.270599 +v 0.205262 -0.956941 0.205263 +v 0.137950 -0.980785 0.137951 +v 0.069309 -0.995185 0.069309 +v 0.062182 0.995185 0.075770 +v 0.123764 0.980785 0.150808 +v 0.184155 0.956940 0.224395 +v 0.242772 0.923880 0.295820 +v 0.299051 0.881921 0.364396 +v 0.352451 0.831470 0.429463 +v 0.402455 0.773010 0.490394 +v 0.448584 0.707107 0.546602 +v 0.490393 0.634393 0.597546 +v 0.527479 0.555570 0.642736 +v 0.559485 0.471397 0.681735 +v 0.586103 0.382683 0.714170 +v 0.607077 0.290285 0.739726 +v 0.622204 0.195090 0.758158 +v 0.631339 0.098017 0.769289 +v 0.634394 -0.000000 0.773012 +v 0.631339 -0.098017 0.769289 +v 0.622204 -0.195091 0.758159 +v 0.607077 -0.290285 0.739726 +v 0.586103 -0.382684 0.714169 +v 0.559485 -0.471397 0.681735 +v 0.527479 -0.555571 0.642736 +v 0.490393 -0.634394 0.597546 +v 0.448584 -0.707107 0.546602 +v 0.402455 -0.773011 0.490393 +v 0.352450 -0.831470 0.429463 +v 0.299051 -0.881922 0.364396 +v 0.242772 -0.923880 0.295819 +v 0.184155 -0.956941 0.224394 +v 0.123764 -0.980785 0.150808 +v 0.062181 -0.995185 0.075769 +v 0.054456 0.995185 0.081500 +v 0.108387 0.980785 0.162213 +v 0.161274 0.956940 0.241364 +v 0.212608 0.923880 0.318191 +v 0.261894 0.881921 0.391954 +v 0.308659 0.831470 0.461941 +v 0.352450 0.773010 0.527480 +v 0.392848 0.707107 0.587939 +v 0.429462 0.634393 0.642736 +v 0.461940 0.555570 0.691343 +v 0.489969 0.471397 0.733292 +v 0.513280 0.382683 0.768179 +v 0.531648 0.290285 0.795668 +v 0.544896 0.195090 0.815494 +v 0.552895 0.098017 0.827467 +v 0.555570 -0.000000 0.831471 +v 0.552895 -0.098017 0.827467 +v 0.544896 -0.195091 0.815494 +v 0.531648 -0.290285 0.795668 +v 0.513280 -0.382684 0.768179 +v 0.489969 -0.471397 0.733292 +v 0.461940 -0.555571 0.691343 +v 0.429462 -0.634394 0.642736 +v 0.392848 -0.707107 0.587939 +v 0.352450 -0.773011 0.527480 +v 0.308658 -0.831470 0.461941 +v 0.261894 -0.881922 0.391953 +v 0.212608 -0.923880 0.318191 +v 0.161274 -0.956941 0.241364 +v 0.108386 -0.980785 0.162213 +v 0.054455 -0.995185 0.081499 +v 0.046205 0.995185 0.086445 +v 0.091965 0.980785 0.172056 +v 0.136840 0.956940 0.256010 +v 0.180396 0.923880 0.337498 +v 0.222215 0.881921 0.415736 +v 0.261894 0.831470 0.489971 +v 0.299051 0.773010 0.559486 +v 0.333328 0.707107 0.623614 +v 0.364395 0.634393 0.681736 +v 0.391952 0.555570 0.733292 +v 0.415735 0.471397 0.777786 +v 0.435514 0.382683 0.814790 +v 0.451099 0.290285 0.843947 +v 0.462339 0.195090 0.864977 +v 0.469127 0.098017 0.877675 +v 0.471397 -0.000000 0.881922 +v 0.469127 -0.098017 0.877675 +v 0.462339 -0.195091 0.864977 +v 0.451099 -0.290285 0.843947 +v 0.435514 -0.382684 0.814790 +v 0.415735 -0.471397 0.777786 +v 0.391952 -0.555571 0.733292 +v 0.364395 -0.634394 0.681735 +v 0.333328 -0.707107 0.623613 +v 0.299051 -0.773011 0.559486 +v 0.261894 -0.831470 0.489970 +v 0.222215 -0.881922 0.415736 +v 0.180396 -0.923880 0.337498 +v 0.136839 -0.956941 0.256009 +v 0.091965 -0.980785 0.172055 +v 0.046205 -0.995185 0.086444 +v 0.037510 0.995185 0.090558 +v 0.074658 0.980785 0.180241 +v 0.111088 0.956940 0.268190 +v 0.146447 0.923880 0.353555 +v 0.180396 0.881921 0.435515 +v 0.212608 0.831470 0.513281 +v 0.242772 0.773010 0.586104 +v 0.270598 0.707107 0.653283 +v 0.295818 0.634393 0.714170 +v 0.318190 0.555570 0.768179 +v 0.337497 0.471397 0.814790 +v 0.353554 0.382683 0.853554 +v 0.366205 0.290285 0.884099 +v 0.375331 0.195090 0.906129 +v 0.380841 0.098017 0.919432 +v 0.382684 -0.000000 0.923881 +v 0.380841 -0.098017 0.919432 +v 0.375331 -0.195091 0.906129 +v 0.366205 -0.290285 0.884099 +v 0.353554 -0.382684 0.853554 +v 0.337497 -0.471397 0.814790 +v 0.318190 -0.555571 0.768179 +v 0.295818 -0.634394 0.714169 +v 0.270598 -0.707107 0.653282 +v 0.242772 -0.773011 0.586104 +v 0.212608 -0.831470 0.513281 +v 0.180396 -0.881922 0.435515 +v 0.146447 -0.923880 0.353554 +v 0.111087 -0.956941 0.268189 +v 0.074658 -0.980785 0.180241 +v 0.037510 -0.995185 0.090557 +v 0.028453 0.995185 0.093798 +v 0.056632 0.980785 0.186691 +v 0.084266 0.956940 0.277787 +v 0.111087 0.923880 0.366207 +v 0.136840 0.881921 0.451100 +v 0.161274 0.831470 0.531649 +v 0.184155 0.773010 0.607078 +v 0.205262 0.707107 0.676660 +v 0.224393 0.634393 0.739726 +v 0.241363 0.555570 0.795668 +v 0.256008 0.471397 0.843947 +v 0.268188 0.382683 0.884099 +v 0.277785 0.290285 0.915736 +v 0.284707 0.195090 0.938554 +v 0.288887 0.098017 0.952333 +v 0.290285 -0.000000 0.956941 +v 0.288887 -0.098017 0.952333 +v 0.284707 -0.195091 0.938554 +v 0.277785 -0.290285 0.915736 +v 0.268188 -0.382684 0.884098 +v 0.256008 -0.471397 0.843947 +v 0.241363 -0.555571 0.795668 +v 0.224393 -0.634394 0.739726 +v 0.205262 -0.707107 0.676660 +v 0.184155 -0.773011 0.607077 +v 0.161274 -0.831470 0.531649 +v 0.136839 -0.881922 0.451100 +v 0.111087 -0.923880 0.366206 +v 0.084265 -0.956941 0.277786 +v 0.056632 -0.980785 0.186691 +v 0.028453 -0.995185 0.093797 +v 0.019122 0.995185 0.096135 +v 0.038060 0.980785 0.191343 +v 0.056632 0.956940 0.284709 +v 0.074658 0.923880 0.375332 +v 0.091965 0.881921 0.462341 +v 0.108387 0.831470 0.544897 +v 0.123764 0.773010 0.622205 +v 0.137950 0.707107 0.693521 +v 0.150807 0.634393 0.758158 +v 0.162212 0.555570 0.815494 +v 0.172054 0.471397 0.864977 +v 0.180240 0.382683 0.906128 +v 0.186690 0.290285 0.938554 +v 0.191342 0.195090 0.961941 +v 0.194151 0.098017 0.976063 +v 0.195090 -0.000000 0.980786 +v 0.194151 -0.098017 0.976063 +v 0.191342 -0.195091 0.961941 +v 0.186690 -0.290285 0.938554 +v 0.180240 -0.382684 0.906128 +v 0.172054 -0.471397 0.864976 +v 0.162212 -0.555571 0.815494 +v 0.150807 -0.634394 0.758158 +v 0.137950 -0.707107 0.693521 +v 0.123764 -0.773011 0.622204 +v 0.108386 -0.831470 0.544896 +v 0.091965 -0.881922 0.462340 +v 0.074658 -0.923880 0.375331 +v 0.056632 -0.956941 0.284708 +v 0.038060 -0.980785 0.191343 +v 0.019122 -0.995185 0.096135 +v 0.009607 0.995185 0.097547 +v 0.019122 0.980785 0.194152 +v 0.028453 0.956940 0.288889 +v 0.037510 0.923880 0.380842 +v 0.046205 0.881921 0.469128 +v 0.054456 0.831470 0.552896 +v 0.062181 0.773010 0.631340 +v 0.069309 0.707107 0.703703 +v 0.075768 0.634393 0.769289 +v 0.081498 0.555570 0.827467 +v 0.086443 0.471397 0.877676 +v 0.090556 0.382683 0.919432 +v 0.093797 0.290285 0.952334 +v 0.096134 0.195090 0.976064 +v 0.097545 0.098017 0.990394 +v 0.098017 -0.000000 0.995186 +v 0.097545 -0.098017 0.990394 +v 0.096134 -0.195091 0.976064 +v 0.093796 -0.290285 0.952333 +v 0.090556 -0.382684 0.919432 +v 0.086443 -0.471397 0.877676 +v 0.081498 -0.555571 0.827467 +v 0.075768 -0.634394 0.769289 +v 0.069309 -0.707107 0.703703 +v 0.062181 -0.773011 0.631339 +v 0.054455 -0.831470 0.552896 +v 0.046205 -0.881922 0.469128 +v 0.037510 -0.923880 0.380842 +v 0.028453 -0.956941 0.288888 +v 0.019122 -0.980785 0.194152 +v 0.009607 -0.995185 0.097546 +v -0.000000 0.995185 0.098019 +v -0.000000 0.980785 0.195092 +v 0.000000 0.956940 0.290286 +v 0.000000 0.923880 0.382685 +v 0.000000 0.881921 0.471398 +v 0.000000 0.831470 0.555572 +v 0.000000 0.773010 0.634395 +v -0.000000 0.707107 0.707108 +v -0.000000 0.634393 0.773012 +v 0.000000 0.555570 0.831471 +v -0.000000 0.471397 0.881922 +v 0.000000 0.382683 0.923881 +v -0.000000 0.290285 0.956941 +v 0.000000 0.195090 0.980787 +v 0.000000 0.098017 0.995186 +v 0.000000 -0.000000 1.000001 +v 0.000000 -0.098017 0.995186 +v 0.000000 -0.195091 0.980787 +v -0.000000 -0.290285 0.956941 +v 0.000000 -0.382684 0.923880 +v 0.000000 -0.471397 0.881922 +v -0.000000 -0.555571 0.831470 +v -0.000000 -0.634394 0.773011 +v -0.000000 -0.707107 0.707108 +v 0.000000 -0.773011 0.634394 +v 0.000000 -0.831470 0.555571 +v 0.000000 -0.881922 0.471398 +v 0.000000 -0.923880 0.382684 +v 0.000000 -0.956941 0.290286 +v 0.000000 -0.980785 0.195091 +v -0.000000 -0.995185 0.098018 +v -0.009607 0.995185 0.097547 +v -0.019122 0.980785 0.194152 +v -0.028453 0.956940 0.288889 +v -0.037510 0.923880 0.380842 +v -0.046205 0.881921 0.469128 +v -0.054455 0.831470 0.552896 +v -0.062181 0.773010 0.631340 +v -0.069309 0.707107 0.703703 +v -0.075768 0.634393 0.769289 +v -0.081498 0.555570 0.827467 +v -0.086443 0.471397 0.877676 +v -0.090556 0.382683 0.919432 +v -0.093797 0.290285 0.952334 +v -0.096134 0.195090 0.976064 +v -0.097545 0.098017 0.990394 +v -0.098017 -0.000000 0.995186 +v -0.097545 -0.098017 0.990394 +v -0.096134 -0.195091 0.976064 +v -0.093797 -0.290285 0.952333 +v -0.090556 -0.382684 0.919432 +v -0.086443 -0.471397 0.877676 +v -0.081498 -0.555571 0.827467 +v -0.075768 -0.634394 0.769289 +v -0.069309 -0.707107 0.703703 +v -0.062181 -0.773011 0.631339 +v -0.054455 -0.831470 0.552896 +v -0.046205 -0.881922 0.469128 +v -0.037509 -0.923880 0.380842 +v -0.028453 -0.956941 0.288888 +v -0.019122 -0.980785 0.194152 +v -0.009607 -0.995185 0.097546 +v -0.019122 0.995185 0.096135 +v -0.038060 0.980785 0.191343 +v -0.056632 0.956940 0.284709 +v -0.074658 0.923880 0.375332 +v -0.091965 0.881921 0.462341 +v -0.108386 0.831470 0.544897 +v -0.123764 0.773010 0.622205 +v -0.137950 0.707107 0.693521 +v -0.150807 0.634393 0.758158 +v -0.162212 0.555570 0.815494 +v -0.172054 0.471397 0.864976 +v -0.180240 0.382683 0.906128 +v -0.186690 0.290285 0.938554 +v -0.191342 0.195090 0.961941 +v -0.194151 0.098017 0.976063 +v -0.195090 -0.000000 0.980786 +v -0.194151 -0.098017 0.976063 +v -0.191342 -0.195091 0.961941 +v -0.186690 -0.290285 0.938554 +v -0.180240 -0.382684 0.906128 +v -0.172054 -0.471397 0.864976 +v -0.162212 -0.555571 0.815494 +v -0.150807 -0.634394 0.758158 +v -0.137950 -0.707107 0.693521 +v -0.123764 -0.773011 0.622204 +v -0.108386 -0.831470 0.544896 +v -0.091965 -0.881922 0.462340 +v -0.074658 -0.923880 0.375331 +v -0.056632 -0.956941 0.284708 +v -0.038060 -0.980785 0.191343 +v -0.019122 -0.995185 0.096135 +v -0.028453 0.995185 0.093798 +v -0.056632 0.980785 0.186691 +v -0.084265 0.956940 0.277787 +v -0.111087 0.923880 0.366207 +v -0.136839 0.881921 0.451100 +v -0.161274 0.831470 0.531649 +v -0.184155 0.773010 0.607078 +v -0.205262 0.707107 0.676660 +v -0.224393 0.634393 0.739726 +v -0.241363 0.555570 0.795668 +v -0.256008 0.471397 0.843947 +v -0.268188 0.382683 0.884099 +v -0.277785 0.290285 0.915736 +v -0.284707 0.195090 0.938554 +v -0.288887 0.098017 0.952333 +v -0.290285 -0.000000 0.956941 +v -0.288887 -0.098017 0.952333 +v -0.284707 -0.195091 0.938554 +v -0.277785 -0.290285 0.915736 +v -0.268188 -0.382684 0.884098 +v -0.256008 -0.471397 0.843947 +v -0.241363 -0.555571 0.795667 +v -0.224393 -0.634394 0.739726 +v -0.205262 -0.707107 0.676660 +v -0.184155 -0.773011 0.607077 +v -0.161274 -0.831470 0.531649 +v -0.136839 -0.881922 0.451100 +v -0.111087 -0.923880 0.366206 +v -0.084265 -0.956941 0.277786 +v -0.056632 -0.980785 0.186691 +v -0.028453 -0.995185 0.093797 +v -0.037510 0.995185 0.090558 +v -0.074658 0.980785 0.180241 +v -0.111087 0.956940 0.268190 +v -0.146447 0.923880 0.353555 +v -0.180396 0.881921 0.435515 +v -0.212608 0.831470 0.513281 +v -0.242772 0.773010 0.586104 +v -0.270598 0.707107 0.653283 +v -0.295818 0.634393 0.714170 +v -0.318190 0.555570 0.768179 +v -0.337497 0.471397 0.814790 +v -0.353553 0.382683 0.853554 +v -0.366205 0.290285 0.884099 +v -0.375330 0.195090 0.906129 +v -0.380841 0.098017 0.919432 +v -0.382683 -0.000000 0.923881 +v -0.380841 -0.098017 0.919432 +v -0.375330 -0.195091 0.906129 +v -0.366205 -0.290285 0.884098 +v -0.353553 -0.382684 0.853554 +v -0.337497 -0.471397 0.814790 +v -0.318190 -0.555571 0.768178 +v -0.295818 -0.634394 0.714169 +v -0.270598 -0.707107 0.653282 +v -0.242772 -0.773011 0.586104 +v -0.212608 -0.831470 0.513281 +v -0.180396 -0.881922 0.435515 +v -0.146447 -0.923880 0.353554 +v -0.111087 -0.956941 0.268189 +v -0.074658 -0.980785 0.180241 +v -0.037510 -0.995185 0.090557 +v -0.046205 0.995185 0.086445 +v -0.091965 0.980785 0.172056 +v -0.136840 0.956940 0.256010 +v -0.180396 0.923880 0.337498 +v -0.222215 0.881921 0.415736 +v -0.261894 0.831470 0.489971 +v -0.299051 0.773010 0.559486 +v -0.333328 0.707107 0.623614 +v -0.364395 0.634393 0.681735 +v -0.391952 0.555570 0.733292 +v -0.415735 0.471397 0.777786 +v -0.435514 0.382683 0.814790 +v -0.451099 0.290285 0.843947 +v -0.462339 0.195090 0.864977 +v -0.469127 0.098017 0.877675 +v -0.471397 -0.000000 0.881922 +v -0.469127 -0.098017 0.877675 +v -0.462339 -0.195091 0.864977 +v -0.451099 -0.290285 0.843947 +v -0.435514 -0.382684 0.814790 +v -0.415735 -0.471397 0.777786 +v -0.391952 -0.555571 0.733291 +v -0.364395 -0.634394 0.681735 +v -0.333328 -0.707107 0.623613 +v -0.299051 -0.773011 0.559486 +v -0.261894 -0.831470 0.489970 +v -0.222215 -0.881922 0.415736 +v -0.180396 -0.923880 0.337498 +v -0.136839 -0.956941 0.256009 +v -0.091965 -0.980785 0.172055 +v -0.046205 -0.995185 0.086444 +v -0.054456 0.995185 0.081500 +v -0.108387 0.980785 0.162213 +v -0.161274 0.956940 0.241364 +v -0.212608 0.923880 0.318191 +v -0.261894 0.881921 0.391953 +v -0.308659 0.831470 0.461941 +v -0.352450 0.773010 0.527480 +v -0.392848 0.707107 0.587939 +v -0.429462 0.634393 0.642736 +v -0.461940 0.555570 0.691343 +v -0.489969 0.471397 0.733292 +v -0.513280 0.382683 0.768179 +v -0.531648 0.290285 0.795668 +v -0.544895 0.195090 0.815494 +v -0.552895 0.098017 0.827467 +v -0.555570 -0.000000 0.831471 +v -0.552895 -0.098017 0.827467 +v -0.544895 -0.195091 0.815494 +v -0.531648 -0.290285 0.795668 +v -0.513280 -0.382684 0.768179 +v -0.489969 -0.471397 0.733292 +v -0.461940 -0.555571 0.691342 +v -0.429462 -0.634394 0.642735 +v -0.392848 -0.707107 0.587939 +v -0.352450 -0.773011 0.527479 +v -0.308658 -0.831470 0.461941 +v -0.261894 -0.881922 0.391953 +v -0.212608 -0.923880 0.318191 +v -0.161274 -0.956941 0.241364 +v -0.108386 -0.980785 0.162212 +v -0.054455 -0.995185 0.081499 +v -0.062182 0.995185 0.075770 +v -0.123764 0.980785 0.150808 +v -0.184155 0.956940 0.224395 +v -0.242772 0.923880 0.295820 +v -0.299051 0.881921 0.364396 +v -0.352450 0.831470 0.429463 +v -0.402455 0.773010 0.490394 +v -0.448584 0.707107 0.546602 +v -0.490393 0.634393 0.597546 +v -0.527479 0.555570 0.642736 +v -0.559485 0.471397 0.681735 +v -0.586103 0.382683 0.714169 +v -0.607077 0.290285 0.739726 +v -0.622204 0.195090 0.758159 +v -0.631338 0.098017 0.769289 +v -0.634393 -0.000000 0.773011 +v -0.631338 -0.098017 0.769289 +v -0.622204 -0.195091 0.758159 +v -0.607077 -0.290285 0.739726 +v -0.586103 -0.382684 0.714170 +v -0.559485 -0.471397 0.681735 +v -0.527479 -0.555571 0.642735 +v -0.490393 -0.634394 0.597546 +v -0.448584 -0.707107 0.546602 +v -0.402455 -0.773011 0.490393 +v -0.352450 -0.831470 0.429463 +v -0.299051 -0.881922 0.364396 +v -0.242772 -0.923880 0.295819 +v -0.184155 -0.956941 0.224394 +v -0.123764 -0.980785 0.150808 +v -0.062181 -0.995185 0.075769 +v -0.069309 0.995185 0.069310 +v -0.137950 0.980785 0.137951 +v -0.205263 0.956940 0.205264 +v -0.270599 0.923880 0.270599 +v -0.333328 0.881921 0.333329 +v -0.392848 0.831470 0.392849 +v -0.448584 0.773010 0.448585 +v -0.500000 0.707107 0.500001 +v -0.546601 0.634393 0.546602 +v -0.587938 0.555570 0.587939 +v -0.623613 0.471397 0.623614 +v -0.653282 0.382683 0.653282 +v -0.676659 0.290285 0.676660 +v -0.693520 0.195090 0.693521 +v -0.703702 0.098017 0.703703 +v -0.707107 -0.000000 0.707108 +v -0.703702 -0.098017 0.703703 +v -0.693520 -0.195091 0.693521 +v -0.676659 -0.290285 0.676660 +v -0.653281 -0.382684 0.653282 +v -0.623613 -0.471397 0.623613 +v -0.587938 -0.555571 0.587938 +v -0.546601 -0.634394 0.546602 +v -0.500000 -0.707107 0.500001 +v -0.448584 -0.773011 0.448585 +v -0.392848 -0.831470 0.392848 +v -0.333328 -0.881922 0.333329 +v -0.270598 -0.923880 0.270599 +v -0.205262 -0.956941 0.205263 +v -0.137950 -0.980785 0.137950 +v -0.069309 -0.995185 0.069309 +v -0.075769 0.995185 0.062183 +v -0.150807 0.980785 0.123765 +v -0.224394 0.956940 0.184156 +v -0.295819 0.923880 0.242773 +v -0.364395 0.881921 0.299052 +v -0.429462 0.831470 0.352451 +v -0.490393 0.773010 0.402456 +v -0.546601 0.707107 0.448585 +v -0.597545 0.634393 0.490394 +v -0.642735 0.555570 0.527480 +v -0.681735 0.471397 0.559486 +v -0.714169 0.382683 0.586104 +v -0.739725 0.290285 0.607077 +v -0.758158 0.195090 0.622205 +v -0.769288 0.098017 0.631339 +v -0.773011 -0.000000 0.634394 +v -0.769288 -0.098017 0.631339 +v -0.758158 -0.195091 0.622205 +v -0.739725 -0.290285 0.607077 +v -0.714168 -0.382684 0.586104 +v -0.681734 -0.471397 0.559486 +v -0.642735 -0.555571 0.527479 +v -0.597545 -0.634394 0.490393 +v -0.546601 -0.707107 0.448585 +v -0.490392 -0.773011 0.402456 +v -0.429462 -0.831470 0.352451 +v -0.364395 -0.881922 0.299052 +v -0.295818 -0.923880 0.242773 +v -0.224393 -0.956941 0.184156 +v -0.150807 -0.980785 0.123765 +v -0.075768 -0.995185 0.062182 +v -0.081499 0.995185 0.054457 +v -0.162212 0.980785 0.108388 +v -0.241364 0.956940 0.161275 +v -0.318190 0.923880 0.212609 +v -0.391953 0.881921 0.261895 +v -0.461940 0.831470 0.308659 +v -0.527479 0.773010 0.352451 +v -0.587938 0.707107 0.392849 +v -0.642735 0.634393 0.429463 +v -0.691342 0.555570 0.461941 +v -0.733291 0.471397 0.489970 +v -0.768178 0.382683 0.513281 +v -0.795667 0.290285 0.531648 +v -0.815494 0.195090 0.544896 +v -0.827466 0.098017 0.552896 +v -0.831470 -0.000000 0.555571 +v -0.827466 -0.098017 0.552896 +v -0.815494 -0.195091 0.544896 +v -0.795667 -0.290285 0.531648 +v -0.768178 -0.382684 0.513281 +v -0.733291 -0.471397 0.489970 +v -0.691342 -0.555571 0.461940 +v -0.642735 -0.634394 0.429462 +v -0.587938 -0.707107 0.392848 +v -0.527479 -0.773011 0.352451 +v -0.461940 -0.831470 0.308659 +v -0.391952 -0.881922 0.261895 +v -0.318190 -0.923880 0.212608 +v -0.241363 -0.956941 0.161274 +v -0.162212 -0.980785 0.108387 +v -0.081498 -0.995185 0.054456 +v -0.086444 0.995185 0.046206 +v -0.172055 0.980785 0.091966 +v -0.256009 0.956940 0.136840 +v -0.337497 0.923880 0.180397 +v -0.415735 0.881921 0.222216 +v -0.489970 0.831470 0.261895 +v -0.559485 0.773010 0.299052 +v -0.623613 0.707107 0.333329 +v -0.681735 0.634393 0.364396 +v -0.733291 0.555570 0.391953 +v -0.777785 0.471397 0.415736 +v -0.814789 0.382683 0.435515 +v -0.843946 0.290285 0.451099 +v -0.864976 0.195090 0.462340 +v -0.877675 0.098017 0.469128 +v -0.881922 -0.000000 0.471398 +v -0.877675 -0.098017 0.469128 +v -0.864976 -0.195091 0.462340 +v -0.843946 -0.290285 0.451099 +v -0.814789 -0.382684 0.435515 +v -0.777785 -0.471397 0.415736 +v -0.733291 -0.555571 0.391953 +v -0.681734 -0.634394 0.364395 +v -0.623613 -0.707107 0.333329 +v -0.559485 -0.773011 0.299052 +v -0.489969 -0.831470 0.261895 +v -0.415735 -0.881922 0.222216 +v -0.337497 -0.923880 0.180397 +v -0.256008 -0.956941 0.136840 +v -0.172054 -0.980785 0.091966 +v -0.086443 -0.995185 0.046206 +v -0.090557 0.995185 0.037511 +v -0.180241 0.980785 0.074659 +v -0.268189 0.956940 0.111088 +v -0.353554 0.923880 0.146448 +v -0.435514 0.881921 0.180397 +v -0.513281 0.831470 0.212609 +v -0.586103 0.773010 0.242773 +v -0.653282 0.707107 0.270599 +v -0.714169 0.634393 0.295819 +v -0.768178 0.555570 0.318190 +v -0.814789 0.471397 0.337498 +v -0.853553 0.382683 0.353554 +v -0.884098 0.290285 0.366206 +v -0.906128 0.195090 0.375331 +v -0.919431 0.098017 0.380841 +v -0.923880 -0.000000 0.382684 +v -0.919431 -0.098017 0.380841 +v -0.906128 -0.195091 0.375331 +v -0.884098 -0.290285 0.366206 +v -0.853553 -0.382684 0.353554 +v -0.814789 -0.471397 0.337498 +v -0.768178 -0.555571 0.318190 +v -0.714169 -0.634394 0.295819 +v -0.653282 -0.707107 0.270599 +v -0.586103 -0.773011 0.242773 +v -0.513280 -0.831470 0.212608 +v -0.435514 -0.881922 0.180397 +v -0.353553 -0.923880 0.146447 +v -0.268188 -0.956941 0.111088 +v -0.180240 -0.980785 0.074659 +v -0.090556 -0.995185 0.037510 +v -0.093797 0.995185 0.028454 +v -0.186691 0.980785 0.056633 +v -0.277786 0.956940 0.084266 +v -0.366206 0.923880 0.111088 +v -0.451099 0.881921 0.136840 +v -0.531648 0.831470 0.161275 +v -0.607077 0.773010 0.184155 +v -0.676660 0.707107 0.205263 +v -0.739725 0.634393 0.224394 +v -0.795667 0.555570 0.241364 +v -0.843946 0.471397 0.256009 +v -0.884098 0.382683 0.268189 +v -0.915735 0.290285 0.277786 +v -0.938554 0.195090 0.284708 +v -0.952332 0.098017 0.288888 +v -0.956941 -0.000000 0.290285 +v -0.952332 -0.098017 0.288888 +v -0.938554 -0.195091 0.284708 +v -0.915735 -0.290285 0.277786 +v -0.884098 -0.382684 0.268189 +v -0.843946 -0.471397 0.256009 +v -0.795667 -0.555571 0.241364 +v -0.739725 -0.634394 0.224394 +v -0.676659 -0.707107 0.205263 +v -0.607076 -0.773011 0.184155 +v -0.531648 -0.831470 0.161274 +v -0.451099 -0.881922 0.136840 +v -0.366205 -0.923880 0.111088 +v -0.277785 -0.956941 0.084266 +v -0.186690 -0.980785 0.056633 +v -0.093797 -0.995185 0.028454 +v -0.096135 0.995185 0.019123 +v -0.191342 0.980785 0.038061 +v -0.284708 0.956940 0.056633 +v -0.375331 0.923880 0.074659 +v -0.462340 0.881921 0.091966 +v -0.544896 0.831470 0.108387 +v -0.622204 0.773010 0.123765 +v -0.693520 0.707107 0.137951 +v -0.758158 0.634393 0.150808 +v -0.815493 0.555570 0.162212 +v -0.864976 0.471397 0.172055 +v -0.906127 0.382683 0.180241 +v -0.938553 0.290285 0.186690 +v -0.961940 0.195090 0.191343 +v -0.976063 0.098017 0.194152 +v -0.980786 -0.000000 0.195091 +v -0.976063 -0.098017 0.194152 +v -0.961940 -0.195091 0.191343 +v -0.938553 -0.290285 0.186691 +v -0.906127 -0.382684 0.180241 +v -0.864976 -0.471397 0.172055 +v -0.815493 -0.555571 0.162212 +v -0.758157 -0.634394 0.150808 +v -0.693520 -0.707107 0.137950 +v -0.622204 -0.773011 0.123765 +v -0.544895 -0.831470 0.108387 +v -0.462339 -0.881922 0.091966 +v -0.375330 -0.923880 0.074659 +v -0.284707 -0.956941 0.056633 +v -0.191342 -0.980785 0.038061 +v -0.096134 -0.995185 0.019123 +v -0.000001 1.000000 0.000001 +v -0.097546 0.995185 0.009608 +v -0.194152 0.980785 0.019123 +v -0.288888 0.956940 0.028454 +v -0.380841 0.923880 0.037510 +v -0.469127 0.881921 0.046206 +v -0.552896 0.831470 0.054456 +v -0.631339 0.773010 0.062182 +v -0.703702 0.707107 0.069309 +v -0.769289 0.634393 0.075769 +v -0.827466 0.555570 0.081499 +v -0.877675 0.471397 0.086444 +v -0.919431 0.382683 0.090557 +v -0.952333 0.290285 0.093797 +v -0.976063 0.195090 0.096135 +v -0.990393 0.098017 0.097546 +v -0.995185 -0.000000 0.098018 +v -0.990393 -0.098017 0.097546 +v -0.976063 -0.195091 0.096135 +v -0.952333 -0.290285 0.093797 +v -0.919431 -0.382684 0.090557 +v -0.877675 -0.471397 0.086444 +v -0.827466 -0.555571 0.081499 +v -0.769288 -0.634394 0.075769 +v -0.703702 -0.707107 0.069309 +v -0.631338 -0.773011 0.062182 +v -0.552895 -0.831470 0.054456 +v -0.469127 -0.881922 0.046206 +v -0.380841 -0.923880 0.037510 +v -0.288887 -0.956941 0.028454 +v -0.194151 -0.980785 0.019123 +v -0.097545 -0.995185 0.009608 +v -0.098018 0.995185 0.000001 +v -0.195091 0.980785 0.000001 +v -0.290286 0.956940 0.000001 +v -0.382684 0.923880 0.000001 +v -0.471397 0.881921 0.000001 +v -0.555571 0.831470 0.000001 +v -0.634394 0.773010 0.000001 +v -0.707107 0.707107 0.000001 +v -0.773011 0.634393 0.000001 +v -0.831470 0.555570 0.000001 +v -0.881922 0.471397 0.000001 +v -0.923880 0.382683 0.000001 +v -0.956941 0.290285 0.000001 +v -0.980786 0.195090 0.000001 +v -0.995185 0.098017 0.000001 +v -1.000000 -0.000000 0.000001 +v -0.995185 -0.098017 0.000001 +v -0.980786 -0.195091 0.000001 +v -0.956940 -0.290285 0.000001 +v -0.923880 -0.382684 0.000001 +v -0.881922 -0.471397 0.000001 +v -0.831470 -0.555571 0.000001 +v -0.773010 -0.634394 0.000001 +v -0.707107 -0.707107 0.000001 +v -0.634393 -0.773011 0.000001 +v -0.555571 -0.831470 0.000001 +v -0.471397 -0.881922 0.000001 +v -0.382683 -0.923880 0.000001 +v -0.290285 -0.956941 0.000001 +v -0.195090 -0.980785 0.000001 +v -0.098017 -0.995185 0.000001 +v -0.097546 0.995185 -0.009607 +v -0.194152 0.980785 -0.019121 +v -0.288888 0.956940 -0.028452 +v -0.380841 0.923880 -0.037509 +v -0.469127 0.881921 -0.046204 +v -0.552896 0.831470 -0.054455 +v -0.631339 0.773010 -0.062181 +v -0.703702 0.707107 -0.069308 +v -0.769289 0.634393 -0.075768 +v -0.827466 0.555570 -0.081498 +v -0.877675 0.471397 -0.086443 +v -0.919431 0.382683 -0.090555 +v -0.952333 0.290285 -0.093796 +v -0.976063 0.195090 -0.096133 +v -0.990393 0.098017 -0.097545 +v -0.995185 -0.000000 -0.098016 +v -0.990393 -0.098017 -0.097545 +v -0.976063 -0.195091 -0.096133 +v -0.952333 -0.290285 -0.093796 +v -0.919431 -0.382684 -0.090555 +v -0.877675 -0.471397 -0.086443 +v -0.827466 -0.555571 -0.081498 +v -0.769288 -0.634394 -0.075768 +v -0.703702 -0.707107 -0.069308 +v -0.631338 -0.773011 -0.062181 +v -0.552895 -0.831470 -0.054455 +v -0.469127 -0.881922 -0.046204 +v -0.380841 -0.923880 -0.037509 +v -0.288887 -0.956941 -0.028452 +v -0.194151 -0.980785 -0.019121 +v -0.097545 -0.995185 -0.009607 +v -0.096135 0.995185 -0.019122 +v -0.191342 0.980785 -0.038060 +v -0.284708 0.956940 -0.056631 +v -0.375331 0.923880 -0.074657 +v -0.462340 0.881921 -0.091964 +v -0.544896 0.831470 -0.108386 +v -0.622204 0.773010 -0.123763 +v -0.693520 0.707107 -0.137949 +v -0.758158 0.634393 -0.150806 +v -0.815493 0.555570 -0.162211 +v -0.864976 0.471397 -0.172054 +v -0.906128 0.382683 -0.180239 +v -0.938553 0.290285 -0.186689 +v -0.961940 0.195090 -0.191341 +v -0.976062 0.098017 -0.194150 +v -0.980785 -0.000000 -0.195090 +v -0.976062 -0.098017 -0.194150 +v -0.961940 -0.195091 -0.191341 +v -0.938553 -0.290285 -0.186689 +v -0.906128 -0.382684 -0.180239 +v -0.864976 -0.471397 -0.172054 +v -0.815493 -0.555571 -0.162211 +v -0.758157 -0.634394 -0.150806 +v -0.693520 -0.707107 -0.137949 +v -0.622204 -0.773011 -0.123763 +v -0.544895 -0.831470 -0.108386 +v -0.462339 -0.881922 -0.091964 +v -0.375330 -0.923880 -0.074657 +v -0.284707 -0.956941 -0.056631 +v -0.191342 -0.980785 -0.038059 +v -0.096134 -0.995185 -0.019121 +v -0.093797 0.995185 -0.028452 +v -0.186691 0.980785 -0.056631 +v -0.277786 0.956940 -0.084265 +v -0.366206 0.923880 -0.111086 +v -0.451099 0.881921 -0.136839 +v -0.531648 0.831470 -0.161273 +v -0.607077 0.773010 -0.184154 +v -0.676660 0.707107 -0.205262 +v -0.739725 0.634393 -0.224392 +v -0.795667 0.555570 -0.241362 +v -0.843946 0.471397 -0.256008 +v -0.884098 0.382683 -0.268187 +v -0.915735 0.290285 -0.277785 +v -0.938554 0.195090 -0.284706 +v -0.952332 0.098017 -0.288886 +v -0.956941 -0.000000 -0.290284 +v -0.952332 -0.098017 -0.288886 +v -0.938554 -0.195091 -0.284706 +v -0.915735 -0.290285 -0.277784 +v -0.884098 -0.382684 -0.268187 +v -0.843946 -0.471397 -0.256008 +v -0.795667 -0.555571 -0.241362 +v -0.739725 -0.634394 -0.224392 +v -0.676659 -0.707107 -0.205262 +v -0.607077 -0.773011 -0.184154 +v -0.531648 -0.831470 -0.161273 +v -0.451099 -0.881922 -0.136838 +v -0.366205 -0.923880 -0.111086 +v -0.277785 -0.956941 -0.084264 +v -0.186690 -0.980785 -0.056631 +v -0.093797 -0.995185 -0.028452 +v -0.090557 0.995185 -0.037509 +v -0.180241 0.980785 -0.074657 +v -0.268189 0.956940 -0.111087 +v -0.353554 0.923880 -0.146446 +v -0.435514 0.881921 -0.180395 +v -0.513281 0.831470 -0.212607 +v -0.586103 0.773010 -0.242771 +v -0.653282 0.707107 -0.270598 +v -0.714169 0.634393 -0.295818 +v -0.768178 0.555570 -0.318189 +v -0.814789 0.471397 -0.337496 +v -0.853554 0.382683 -0.353553 +v -0.884098 0.290285 -0.366205 +v -0.906128 0.195090 -0.375330 +v -0.919431 0.098017 -0.380840 +v -0.923880 -0.000000 -0.382683 +v -0.919431 -0.098017 -0.380840 +v -0.906128 -0.195091 -0.375330 +v -0.884098 -0.290285 -0.366205 +v -0.853554 -0.382684 -0.353553 +v -0.814789 -0.471397 -0.337496 +v -0.768178 -0.555571 -0.318189 +v -0.714169 -0.634394 -0.295818 +v -0.653282 -0.707107 -0.270597 +v -0.586103 -0.773011 -0.242771 +v -0.513280 -0.831470 -0.212607 +v -0.435514 -0.881922 -0.180395 +v -0.353553 -0.923880 -0.146446 +v -0.268188 -0.956941 -0.111086 +v -0.180240 -0.980785 -0.074657 +v -0.090556 -0.995185 -0.037509 +v -0.086444 0.995185 -0.046205 +v -0.172055 0.980785 -0.091965 +v -0.256009 0.956940 -0.136839 +v -0.337497 0.923880 -0.180395 +v -0.415735 0.881921 -0.222214 +v -0.489970 0.831470 -0.261894 +v -0.559485 0.773010 -0.299050 +v -0.623613 0.707107 -0.333327 +v -0.681735 0.634393 -0.364394 +v -0.733291 0.555570 -0.391951 +v -0.777785 0.471397 -0.415734 +v -0.814789 0.382683 -0.435513 +v -0.843946 0.290285 -0.451098 +v -0.864976 0.195090 -0.462338 +v -0.877675 0.098017 -0.469126 +v -0.881921 -0.000000 -0.471396 +v -0.877675 -0.098017 -0.469126 +v -0.864976 -0.195091 -0.462338 +v -0.843946 -0.290285 -0.451098 +v -0.814789 -0.382684 -0.435513 +v -0.777785 -0.471397 -0.415734 +v -0.733291 -0.555571 -0.391951 +v -0.681734 -0.634394 -0.364394 +v -0.623613 -0.707107 -0.333327 +v -0.559485 -0.773011 -0.299050 +v -0.489970 -0.831470 -0.261893 +v -0.415735 -0.881922 -0.222214 +v -0.337496 -0.923880 -0.180395 +v -0.256008 -0.956941 -0.136839 +v -0.172054 -0.980785 -0.091964 +v -0.086443 -0.995185 -0.046204 +v -0.081499 0.995185 -0.054455 +v -0.162212 0.980785 -0.108386 +v -0.241364 0.956940 -0.161273 +v -0.318190 0.923880 -0.212607 +v -0.391952 0.881921 -0.261893 +v -0.461940 0.831470 -0.308658 +v -0.527479 0.773010 -0.352449 +v -0.587938 0.707107 -0.392847 +v -0.642735 0.634393 -0.429461 +v -0.691342 0.555570 -0.461939 +v -0.733291 0.471397 -0.489969 +v -0.768178 0.382683 -0.513279 +v -0.795667 0.290285 -0.531647 +v -0.815494 0.195090 -0.544895 +v -0.827466 0.098017 -0.552894 +v -0.831470 -0.000000 -0.555570 +v -0.827466 -0.098017 -0.552894 +v -0.815494 -0.195091 -0.544895 +v -0.795667 -0.290285 -0.531647 +v -0.768178 -0.382684 -0.513279 +v -0.733291 -0.471397 -0.489969 +v -0.691342 -0.555571 -0.461939 +v -0.642735 -0.634394 -0.429461 +v -0.587938 -0.707107 -0.392847 +v -0.527479 -0.773011 -0.352449 +v -0.461940 -0.831470 -0.308658 +v -0.391952 -0.881922 -0.261893 +v -0.318189 -0.923880 -0.212607 +v -0.241363 -0.956941 -0.161273 +v -0.162212 -0.980785 -0.108386 +v -0.081498 -0.995185 -0.054455 +v -0.075769 0.995185 -0.062181 +v -0.150807 0.980785 -0.123764 +v -0.224394 0.956940 -0.184154 +v -0.295819 0.923880 -0.242771 +v -0.364395 0.881921 -0.299050 +v -0.429462 0.831470 -0.352450 +v -0.490393 0.773010 -0.402454 +v -0.546601 0.707107 -0.448583 +v -0.597545 0.634393 -0.490392 +v -0.642735 0.555570 -0.527478 +v -0.681735 0.471397 -0.559484 +v -0.714169 0.382683 -0.586102 +v -0.739725 0.290285 -0.607076 +v -0.758158 0.195090 -0.622203 +v -0.769288 0.098017 -0.631338 +v -0.773011 -0.000000 -0.634393 +v -0.769288 -0.098017 -0.631338 +v -0.758158 -0.195091 -0.622203 +v -0.739725 -0.290285 -0.607076 +v -0.714169 -0.382684 -0.586102 +v -0.681735 -0.471397 -0.559484 +v -0.642735 -0.555571 -0.527478 +v -0.597545 -0.634394 -0.490392 +v -0.546601 -0.707107 -0.448583 +v -0.490393 -0.773011 -0.402454 +v -0.429462 -0.831470 -0.352449 +v -0.364395 -0.881922 -0.299050 +v -0.295818 -0.923880 -0.242771 +v -0.224393 -0.956941 -0.184154 +v -0.150807 -0.980785 -0.123763 +v -0.075768 -0.995185 -0.062181 +v -0.069309 0.995185 -0.069308 +v -0.137950 0.980785 -0.137949 +v -0.205263 0.956940 -0.205262 +v -0.270598 0.923880 -0.270598 +v -0.333328 0.881921 -0.333327 +v -0.392848 0.831470 -0.392847 +v -0.448584 0.773010 -0.448583 +v -0.500000 0.707107 -0.500000 +v -0.546601 0.634393 -0.546600 +v -0.587938 0.555570 -0.587937 +v -0.623613 0.471397 -0.623612 +v -0.653282 0.382683 -0.653281 +v -0.676659 0.290285 -0.676659 +v -0.693521 0.195090 -0.693520 +v -0.703702 0.098017 -0.703701 +v -0.707107 -0.000000 -0.707106 +v -0.703702 -0.098017 -0.703701 +v -0.693521 -0.195091 -0.693520 +v -0.676659 -0.290285 -0.676658 +v -0.653282 -0.382684 -0.653281 +v -0.623613 -0.471397 -0.623612 +v -0.587938 -0.555571 -0.587937 +v -0.546601 -0.634394 -0.546600 +v -0.500000 -0.707107 -0.499999 +v -0.448584 -0.773011 -0.448583 +v -0.392848 -0.831470 -0.392847 +v -0.333328 -0.881922 -0.333327 +v -0.270598 -0.923880 -0.270597 +v -0.205262 -0.956941 -0.205262 +v -0.137950 -0.980785 -0.137949 +v -0.069309 -0.995185 -0.069308 +v -0.062182 0.995185 -0.075768 +v -0.123764 0.980785 -0.150807 +v -0.184155 0.956940 -0.224393 +v -0.242772 0.923880 -0.295818 +v -0.299051 0.881921 -0.364394 +v -0.352451 0.831470 -0.429461 +v -0.402455 0.773010 -0.490392 +v -0.448584 0.707107 -0.546601 +v -0.490393 0.634393 -0.597545 +v -0.527479 0.555570 -0.642734 +v -0.559485 0.471397 -0.681734 +v -0.586103 0.382683 -0.714168 +v -0.607077 0.290285 -0.739725 +v -0.622204 0.195090 -0.758157 +v -0.631339 0.098017 -0.769288 +v -0.634393 -0.000000 -0.773010 +v -0.631339 -0.098017 -0.769288 +v -0.622204 -0.195091 -0.758157 +v -0.607077 -0.290285 -0.739724 +v -0.586103 -0.382684 -0.714168 +v -0.559485 -0.471397 -0.681734 +v -0.527479 -0.555571 -0.642734 +v -0.490393 -0.634394 -0.597545 +v -0.448584 -0.707107 -0.546600 +v -0.402455 -0.773011 -0.490392 +v -0.352450 -0.831470 -0.429461 +v -0.299051 -0.881922 -0.364394 +v -0.242772 -0.923880 -0.295817 +v -0.184155 -0.956941 -0.224392 +v -0.123764 -0.980785 -0.150806 +v -0.062181 -0.995185 -0.075767 +v -0.054456 0.995185 -0.081498 +v -0.108387 0.980785 -0.162211 +v -0.161274 0.956940 -0.241363 +v -0.212608 0.923880 -0.318189 +v -0.261894 0.881921 -0.391952 +v -0.308659 0.831470 -0.461940 +v -0.352450 0.773010 -0.527478 +v -0.392848 0.707107 -0.587938 +v -0.429462 0.634393 -0.642734 +v -0.461940 0.555570 -0.691341 +v -0.489969 0.471397 -0.733290 +v -0.513280 0.382683 -0.768177 +v -0.531648 0.290285 -0.795666 +v -0.544896 0.195090 -0.815493 +v -0.552895 0.098017 -0.827465 +v -0.555570 -0.000000 -0.831469 +v -0.552895 -0.098017 -0.827465 +v -0.544896 -0.195091 -0.815493 +v -0.531648 -0.290285 -0.795666 +v -0.513280 -0.382684 -0.768177 +v -0.489969 -0.471397 -0.733290 +v -0.461940 -0.555571 -0.691341 +v -0.429462 -0.634394 -0.642734 +v -0.392848 -0.707107 -0.587937 +v -0.352450 -0.773011 -0.527478 +v -0.308658 -0.831470 -0.461939 +v -0.261894 -0.881922 -0.391951 +v -0.212607 -0.923880 -0.318189 +v -0.161274 -0.956941 -0.241362 +v -0.108386 -0.980785 -0.162211 +v -0.054455 -0.995185 -0.081497 +v -0.046205 0.995185 -0.086443 +v -0.091965 0.980785 -0.172054 +v -0.136840 0.956940 -0.256008 +v -0.180396 0.923880 -0.337496 +v -0.222215 0.881921 -0.415734 +v -0.261894 0.831470 -0.489969 +v -0.299051 0.773010 -0.559484 +v -0.333328 0.707107 -0.623612 +v -0.364395 0.634393 -0.681734 +v -0.391952 0.555570 -0.733290 +v -0.415735 0.471397 -0.777785 +v -0.435514 0.382683 -0.814788 +v -0.451099 0.290285 -0.843946 +v -0.462340 0.195090 -0.864975 +v -0.469127 0.098017 -0.877674 +v -0.471397 -0.000000 -0.881921 +v -0.469127 -0.098017 -0.877674 +v -0.462340 -0.195091 -0.864975 +v -0.451099 -0.290285 -0.843945 +v -0.435514 -0.382684 -0.814788 +v -0.415735 -0.471397 -0.777785 +v -0.391952 -0.555571 -0.733290 +v -0.364395 -0.634394 -0.681734 +v -0.333328 -0.707107 -0.623612 +v -0.299051 -0.773011 -0.559484 +v -0.261894 -0.831470 -0.489969 +v -0.222215 -0.881922 -0.415734 +v -0.180396 -0.923880 -0.337496 +v -0.136839 -0.956941 -0.256008 +v -0.091965 -0.980785 -0.172053 +v -0.046205 -0.995185 -0.086443 +v -0.037510 0.995185 -0.090556 +v -0.074658 0.980785 -0.180240 +v -0.111087 0.956940 -0.268188 +v -0.146447 0.923880 -0.353553 +v -0.180396 0.881921 -0.435513 +v -0.212608 0.831470 -0.513280 +v -0.242772 0.773010 -0.586103 +v -0.270598 0.707107 -0.653281 +v -0.295818 0.634393 -0.714168 +v -0.318190 0.555570 -0.768177 +v -0.337497 0.471397 -0.814789 +v -0.353553 0.382683 -0.853553 +v -0.366205 0.290285 -0.884097 +v -0.375331 0.195090 -0.906127 +v -0.380841 0.098017 -0.919430 +v -0.382684 -0.000000 -0.923879 +v -0.380841 -0.098017 -0.919430 +v -0.375331 -0.195091 -0.906127 +v -0.366205 -0.290285 -0.884097 +v -0.353554 -0.382684 -0.853553 +v -0.337497 -0.471397 -0.814788 +v -0.318190 -0.555571 -0.768177 +v -0.295818 -0.634394 -0.714168 +v -0.270598 -0.707107 -0.653281 +v -0.242772 -0.773011 -0.586102 +v -0.212608 -0.831470 -0.513279 +v -0.180396 -0.881922 -0.435513 +v -0.146446 -0.923880 -0.353552 +v -0.111087 -0.956941 -0.268187 +v -0.074658 -0.980785 -0.180239 +v -0.037510 -0.995185 -0.090555 +v 0.000000 -1.000000 0.000001 +v -0.028453 0.995185 -0.093796 +v -0.056632 0.980785 -0.186690 +v -0.084265 0.956940 -0.277785 +v -0.111087 0.923880 -0.366205 +v -0.136839 0.881921 -0.451098 +v -0.161274 0.831470 -0.531648 +v -0.184155 0.773010 -0.607076 +v -0.205262 0.707107 -0.676659 +v -0.224393 0.634393 -0.739724 +v -0.241363 0.555570 -0.795666 +v -0.256008 0.471397 -0.843946 +v -0.268188 0.382683 -0.884097 +v -0.277785 0.290285 -0.915734 +v -0.284707 0.195090 -0.938553 +v -0.288887 0.098017 -0.952332 +v -0.290285 -0.000000 -0.956940 +v -0.288887 -0.098017 -0.952332 +v -0.284707 -0.195091 -0.938553 +v -0.277785 -0.290285 -0.915734 +v -0.268188 -0.382684 -0.884097 +v -0.256008 -0.471397 -0.843946 +v -0.241363 -0.555571 -0.795666 +v -0.224393 -0.634394 -0.739724 +v -0.205262 -0.707107 -0.676658 +v -0.184155 -0.773011 -0.607076 +v -0.161274 -0.831470 -0.531647 +v -0.136839 -0.881922 -0.451098 +v -0.111087 -0.923880 -0.366204 +v -0.084265 -0.956941 -0.277784 +v -0.056632 -0.980785 -0.186689 +v -0.028453 -0.995185 -0.093796 +v -0.019122 0.995185 -0.096134 +v -0.038060 0.980785 -0.191342 +v -0.056632 0.956940 -0.284707 +v -0.074658 0.923880 -0.375330 +v -0.091965 0.881921 -0.462339 +v -0.108386 0.831470 -0.544895 +v -0.123764 0.773010 -0.622203 +v -0.137950 0.707107 -0.693520 +v -0.150807 0.634393 -0.758157 +v -0.162212 0.555570 -0.815493 +v -0.172054 0.471397 -0.864975 +v -0.180240 0.382683 -0.906127 +v -0.186690 0.290285 -0.938553 +v -0.191342 0.195090 -0.961940 +v -0.194151 0.098017 -0.976062 +v -0.195090 -0.000000 -0.980785 +v -0.194151 -0.098017 -0.976062 +v -0.191342 -0.195091 -0.961940 +v -0.186690 -0.290285 -0.938552 +v -0.180240 -0.382684 -0.906127 +v -0.172054 -0.471397 -0.864975 +v -0.162212 -0.555571 -0.815493 +v -0.150807 -0.634394 -0.758157 +v -0.137950 -0.707107 -0.693519 +v -0.123764 -0.773011 -0.622203 +v -0.108386 -0.831470 -0.544895 +v -0.091965 -0.881922 -0.462338 +v -0.074658 -0.923880 -0.375329 +v -0.056632 -0.956941 -0.284706 +v -0.038060 -0.980785 -0.191341 +v -0.019122 -0.995185 -0.096133 +v -0.009607 0.995185 -0.097545 +v -0.019122 0.980785 -0.194151 +v -0.028453 0.956940 -0.288887 +v -0.037510 0.923880 -0.380840 +v -0.046205 0.881921 -0.469126 +v -0.054455 0.831470 -0.552895 +v -0.062181 0.773010 -0.631338 +v -0.069309 0.707107 -0.703702 +v -0.075768 0.634393 -0.769288 +v -0.081498 0.555570 -0.827465 +v -0.086443 0.471397 -0.877674 +v -0.090556 0.382683 -0.919430 +v -0.093796 0.290285 -0.952332 +v -0.096134 0.195090 -0.976063 +v -0.097545 0.098017 -0.990392 +v -0.098017 -0.000000 -0.995184 +v -0.097545 -0.098017 -0.990392 +v -0.096134 -0.195091 -0.976063 +v -0.093797 -0.290285 -0.952332 +v -0.090556 -0.382684 -0.919430 +v -0.086443 -0.471397 -0.877674 +v -0.081498 -0.555571 -0.827465 +v -0.075768 -0.634394 -0.769288 +v -0.069308 -0.707107 -0.703701 +v -0.062181 -0.773011 -0.631338 +v -0.054455 -0.831470 -0.552895 +v -0.046205 -0.881922 -0.469126 +v -0.037509 -0.923880 -0.380840 +v -0.028453 -0.956941 -0.288886 +v -0.019122 -0.980785 -0.194150 +v -0.009607 -0.995185 -0.097544 +v -0.000000 0.471397 -0.881921 +v -0.000000 -0.195091 -0.980785 +v -0.000000 -0.382684 -0.923879 +v 0.000000 -0.923880 -0.382682 +v -0.000000 -0.980785 -0.195090 +v -0.000000 -0.995185 -0.098016 +vt 0.750000 0.281250 +vt 0.734375 0.312500 +vt 0.734375 0.281250 +vt 0.750000 0.718750 +vt 0.734375 0.687500 +vt 0.750000 0.687500 +vt 0.750000 0.250000 +vt 0.734375 0.250000 +vt 0.750000 0.656250 +vt 0.734375 0.656250 +vt 0.750000 0.218750 +vt 0.734375 0.218750 +vt 0.750000 0.625000 +vt 0.734375 0.625000 +vt 0.750000 0.187500 +vt 0.734375 0.187500 +vt 0.750000 0.593750 +vt 0.734375 0.593750 +vt 0.750000 0.156250 +vt 0.734375 0.156250 +vt 0.750000 0.562500 +vt 0.734375 0.562500 +vt 0.750000 0.968750 +vt 0.742188 1.000000 +vt 0.734375 0.968750 +vt 0.734375 0.125000 +vt 0.750000 0.125000 +vt 0.750000 0.531250 +vt 0.734375 0.531250 +vt 0.734375 0.937500 +vt 0.750000 0.937500 +vt 0.734375 0.093750 +vt 0.750000 0.093750 +vt 0.734375 0.500000 +vt 0.750000 0.500000 +vt 0.734375 0.906250 +vt 0.750000 0.906250 +vt 0.734375 0.062500 +vt 0.750000 0.062500 +vt 0.734375 0.468750 +vt 0.750000 0.468750 +vt 0.750000 0.875000 +vt 0.734375 0.875000 +vt 0.734375 0.031250 +vt 0.750000 0.031250 +vt 0.734375 0.437500 +vt 0.750000 0.437500 +vt 0.750000 0.843750 +vt 0.734375 0.843750 +vt 0.742187 0.000000 +vt 0.750000 0.406250 +vt 0.734375 0.406250 +vt 0.734375 0.812500 +vt 0.750000 0.812500 +vt 0.734375 0.375000 +vt 0.750000 0.375000 +vt 0.734375 0.781250 +vt 0.750000 0.781250 +vt 0.734375 0.343750 +vt 0.750000 0.343750 +vt 0.734375 0.750000 +vt 0.750000 0.750000 +vt 0.750000 0.312500 +vt 0.734375 0.718750 +vt 0.718750 0.437500 +vt 0.718750 0.843750 +vt 0.726562 0.000000 +vt 0.718750 0.031250 +vt 0.718750 0.406250 +vt 0.718750 0.812500 +vt 0.718750 0.375000 +vt 0.718750 0.781250 +vt 0.718750 0.343750 +vt 0.718750 0.750000 +vt 0.718750 0.312500 +vt 0.718750 0.718750 +vt 0.718750 0.281250 +vt 0.718750 0.687500 +vt 0.718750 0.250000 +vt 0.718750 0.656250 +vt 0.718750 0.218750 +vt 0.718750 0.625000 +vt 0.718750 0.187500 +vt 0.718750 0.593750 +vt 0.718750 0.156250 +vt 0.718750 0.562500 +vt 0.726563 1.000000 +vt 0.718750 0.968750 +vt 0.718750 0.125000 +vt 0.718750 0.531250 +vt 0.718750 0.937500 +vt 0.718750 0.093750 +vt 0.718750 0.500000 +vt 0.718750 0.906250 +vt 0.718750 0.062500 +vt 0.718750 0.468750 +vt 0.718750 0.875000 +vt 0.703125 0.406250 +vt 0.703125 0.375000 +vt 0.703125 0.781250 +vt 0.703125 0.343750 +vt 0.703125 0.750000 +vt 0.703125 0.312500 +vt 0.703125 0.718750 +vt 0.703125 0.281250 +vt 0.703125 0.687500 +vt 0.703125 0.250000 +vt 0.703125 0.656250 +vt 0.703125 0.218750 +vt 0.703125 0.625000 +vt 0.703125 0.187500 +vt 0.703125 0.593750 +vt 0.703125 0.156250 +vt 0.703125 0.562500 +vt 0.710938 1.000000 +vt 0.703125 0.968750 +vt 0.703125 0.125000 +vt 0.703125 0.531250 +vt 0.703125 0.937500 +vt 0.703125 0.093750 +vt 0.703125 0.500000 +vt 0.703125 0.906250 +vt 0.703125 0.062500 +vt 0.703125 0.468750 +vt 0.703125 0.875000 +vt 0.703124 0.031250 +vt 0.703125 0.437500 +vt 0.703125 0.843750 +vt 0.710937 0.000000 +vt 0.703125 0.812500 +vt 0.687500 0.312500 +vt 0.687500 0.718750 +vt 0.687500 0.281250 +vt 0.687500 0.687500 +vt 0.687500 0.250000 +vt 0.687500 0.656250 +vt 0.687500 0.218750 +vt 0.687500 0.625000 +vt 0.687500 0.187500 +vt 0.687500 0.593750 +vt 0.687500 0.156250 +vt 0.687500 0.562500 +vt 0.695312 1.000000 +vt 0.687499 0.968750 +vt 0.687500 0.125000 +vt 0.687500 0.531250 +vt 0.687500 0.937500 +vt 0.687500 0.093750 +vt 0.687500 0.500000 +vt 0.687500 0.906250 +vt 0.687500 0.062500 +vt 0.687500 0.468750 +vt 0.687500 0.875000 +vt 0.687499 0.031250 +vt 0.687500 0.437500 +vt 0.687500 0.843750 +vt 0.695312 0.000000 +vt 0.687500 0.406250 +vt 0.687500 0.812500 +vt 0.687500 0.375000 +vt 0.687500 0.781250 +vt 0.687500 0.343750 +vt 0.687500 0.750000 +vt 0.671875 0.281250 +vt 0.671875 0.250000 +vt 0.671875 0.687500 +vt 0.671875 0.656250 +vt 0.671875 0.218750 +vt 0.671875 0.625000 +vt 0.671875 0.187500 +vt 0.671875 0.593750 +vt 0.671875 0.156250 +vt 0.671875 0.562500 +vt 0.679687 1.000000 +vt 0.671874 0.968750 +vt 0.671875 0.125000 +vt 0.671875 0.531250 +vt 0.671875 0.937500 +vt 0.671875 0.093750 +vt 0.671875 0.500000 +vt 0.671875 0.906250 +vt 0.671875 0.062500 +vt 0.671875 0.468750 +vt 0.671875 0.875000 +vt 0.671874 0.031250 +vt 0.671875 0.437500 +vt 0.671875 0.843750 +vt 0.679687 0.000000 +vt 0.671875 0.406250 +vt 0.671875 0.812500 +vt 0.671875 0.375000 +vt 0.671875 0.781250 +vt 0.671875 0.343750 +vt 0.671875 0.750000 +vt 0.671875 0.312500 +vt 0.671875 0.718750 +vt 0.656250 0.187500 +vt 0.656250 0.593750 +vt 0.656250 0.156250 +vt 0.656250 0.562500 +vt 0.664062 1.000000 +vt 0.656249 0.968750 +vt 0.656250 0.125000 +vt 0.656250 0.531250 +vt 0.656250 0.937500 +vt 0.656250 0.093750 +vt 0.656250 0.500000 +vt 0.656250 0.906250 +vt 0.656250 0.062500 +vt 0.656250 0.468750 +vt 0.656250 0.875000 +vt 0.656249 0.031250 +vt 0.656250 0.437500 +vt 0.656250 0.843750 +vt 0.664061 0.000000 +vt 0.656250 0.406250 +vt 0.656250 0.812500 +vt 0.656250 0.375000 +vt 0.656250 0.781250 +vt 0.656250 0.343750 +vt 0.656250 0.750000 +vt 0.656250 0.312500 +vt 0.656250 0.718750 +vt 0.656250 0.281250 +vt 0.656250 0.687500 +vt 0.656250 0.250000 +vt 0.656250 0.656250 +vt 0.656250 0.218750 +vt 0.656250 0.625000 +vt 0.648437 1.000000 +vt 0.640624 0.968750 +vt 0.640625 0.125000 +vt 0.640625 0.562500 +vt 0.640625 0.531250 +vt 0.640624 0.937500 +vt 0.640625 0.093750 +vt 0.640625 0.500000 +vt 0.640625 0.906250 +vt 0.640624 0.062500 +vt 0.640625 0.468750 +vt 0.640625 0.875000 +vt 0.640624 0.031250 +vt 0.640625 0.437500 +vt 0.640625 0.843750 +vt 0.648436 0.000000 +vt 0.640625 0.406250 +vt 0.640625 0.812500 +vt 0.640625 0.375000 +vt 0.640625 0.781250 +vt 0.640625 0.343750 +vt 0.640625 0.750000 +vt 0.640625 0.312500 +vt 0.640625 0.718750 +vt 0.640625 0.281250 +vt 0.640625 0.687500 +vt 0.640625 0.250000 +vt 0.640625 0.656250 +vt 0.640625 0.218750 +vt 0.640625 0.625000 +vt 0.640625 0.187500 +vt 0.640625 0.593750 +vt 0.640625 0.156250 +vt 0.625000 0.906250 +vt 0.624999 0.062500 +vt 0.625000 0.500000 +vt 0.625000 0.468750 +vt 0.625000 0.875000 +vt 0.624999 0.031250 +vt 0.625000 0.437500 +vt 0.625000 0.843750 +vt 0.632811 0.000000 +vt 0.625000 0.406250 +vt 0.625000 0.812500 +vt 0.625000 0.375000 +vt 0.625000 0.781250 +vt 0.625000 0.343750 +vt 0.625000 0.750000 +vt 0.625000 0.312500 +vt 0.625000 0.718750 +vt 0.625000 0.281250 +vt 0.625000 0.687500 +vt 0.625000 0.250000 +vt 0.625000 0.656250 +vt 0.625000 0.218750 +vt 0.625000 0.625000 +vt 0.625000 0.187500 +vt 0.625000 0.593750 +vt 0.625000 0.156250 +vt 0.625000 0.562500 +vt 0.632811 1.000000 +vt 0.624999 0.968750 +vt 0.625000 0.125000 +vt 0.625000 0.531250 +vt 0.624999 0.937500 +vt 0.625000 0.093750 +vt 0.609375 0.843750 +vt 0.617186 0.000000 +vt 0.609374 0.031250 +vt 0.609375 0.437500 +vt 0.609375 0.406250 +vt 0.609375 0.812500 +vt 0.609375 0.375000 +vt 0.609375 0.781250 +vt 0.609375 0.343750 +vt 0.609375 0.750000 +vt 0.609375 0.312500 +vt 0.609375 0.718750 +vt 0.609375 0.281250 +vt 0.609375 0.687500 +vt 0.609375 0.250000 +vt 0.609375 0.656250 +vt 0.609375 0.218750 +vt 0.609375 0.625000 +vt 0.609375 0.187500 +vt 0.609375 0.593750 +vt 0.609375 0.156250 +vt 0.609375 0.562500 +vt 0.617186 1.000000 +vt 0.609374 0.968750 +vt 0.609375 0.125000 +vt 0.609375 0.531250 +vt 0.609374 0.937500 +vt 0.609375 0.093750 +vt 0.609375 0.500000 +vt 0.609375 0.906250 +vt 0.609374 0.062500 +vt 0.609375 0.468750 +vt 0.609375 0.875000 +vt 0.593750 0.781250 +vt 0.593750 0.375000 +vt 0.593750 0.343750 +vt 0.593750 0.750000 +vt 0.593750 0.312500 +vt 0.593750 0.718750 +vt 0.593750 0.281250 +vt 0.593750 0.687500 +vt 0.593750 0.250000 +vt 0.593750 0.656250 +vt 0.593750 0.218750 +vt 0.593750 0.625000 +vt 0.593750 0.187500 +vt 0.593750 0.593750 +vt 0.593750 0.156250 +vt 0.593750 0.562500 +vt 0.601561 1.000000 +vt 0.593749 0.968750 +vt 0.593750 0.125000 +vt 0.593750 0.531250 +vt 0.593749 0.937500 +vt 0.593750 0.093750 +vt 0.593750 0.500000 +vt 0.593750 0.906250 +vt 0.593749 0.062500 +vt 0.593750 0.468750 +vt 0.593750 0.875000 +vt 0.593749 0.031250 +vt 0.593750 0.437500 +vt 0.593750 0.843750 +vt 0.601561 0.000000 +vt 0.593750 0.406250 +vt 0.593750 0.812500 +vt 0.578125 0.718750 +vt 0.578125 0.312500 +vt 0.578125 0.281250 +vt 0.578125 0.687500 +vt 0.578125 0.250000 +vt 0.578125 0.656250 +vt 0.578125 0.218750 +vt 0.578125 0.625000 +vt 0.578125 0.187500 +vt 0.578125 0.593750 +vt 0.578125 0.156250 +vt 0.578125 0.562500 +vt 0.585936 1.000000 +vt 0.578124 0.968750 +vt 0.578125 0.125000 +vt 0.578125 0.531250 +vt 0.578124 0.937500 +vt 0.578124 0.093750 +vt 0.578125 0.500000 +vt 0.578125 0.906250 +vt 0.578124 0.062500 +vt 0.578125 0.468750 +vt 0.578125 0.875000 +vt 0.578124 0.031250 +vt 0.578125 0.437500 +vt 0.578125 0.843750 +vt 0.585936 0.000000 +vt 0.578125 0.406250 +vt 0.578125 0.812500 +vt 0.578125 0.375000 +vt 0.578125 0.781250 +vt 0.578125 0.343750 +vt 0.578125 0.750000 +vt 0.562500 0.687500 +vt 0.562500 0.656250 +vt 0.562500 0.250000 +vt 0.562500 0.218750 +vt 0.562500 0.625000 +vt 0.562500 0.187500 +vt 0.562500 0.593750 +vt 0.562500 0.156250 +vt 0.562500 0.562500 +vt 0.570311 1.000000 +vt 0.562499 0.968750 +vt 0.562500 0.125000 +vt 0.562500 0.531250 +vt 0.562499 0.937500 +vt 0.562499 0.093750 +vt 0.562500 0.500000 +vt 0.562499 0.906250 +vt 0.562499 0.062500 +vt 0.562500 0.468750 +vt 0.562500 0.875000 +vt 0.562499 0.031250 +vt 0.562500 0.437500 +vt 0.562500 0.843750 +vt 0.570311 0.000000 +vt 0.562500 0.406250 +vt 0.562500 0.812500 +vt 0.562500 0.375000 +vt 0.562500 0.781250 +vt 0.562500 0.343750 +vt 0.562500 0.750000 +vt 0.562500 0.312500 +vt 0.562500 0.718750 +vt 0.562500 0.281250 +vt 0.546875 0.593750 +vt 0.546875 0.187500 +vt 0.546875 0.156250 +vt 0.546875 0.562500 +vt 0.554686 1.000000 +vt 0.546874 0.968750 +vt 0.546875 0.125000 +vt 0.546875 0.531250 +vt 0.546874 0.937500 +vt 0.546874 0.093750 +vt 0.546875 0.500000 +vt 0.546874 0.906250 +vt 0.546874 0.062500 +vt 0.546875 0.468750 +vt 0.546875 0.875000 +vt 0.546874 0.031250 +vt 0.546875 0.437500 +vt 0.546875 0.843750 +vt 0.554686 0.000000 +vt 0.546875 0.406250 +vt 0.546875 0.812500 +vt 0.546875 0.375000 +vt 0.546875 0.781250 +vt 0.546875 0.343750 +vt 0.546875 0.750000 +vt 0.546875 0.312500 +vt 0.546875 0.718750 +vt 0.546875 0.281250 +vt 0.546875 0.687500 +vt 0.546875 0.250000 +vt 0.546875 0.656250 +vt 0.546875 0.218750 +vt 0.546875 0.625000 +vt 0.531250 0.562500 +vt 0.531250 0.531250 +vt 0.531249 0.937500 +vt 0.531249 0.093750 +vt 0.531250 0.500000 +vt 0.531249 0.906250 +vt 0.531249 0.062500 +vt 0.531250 0.468750 +vt 0.531250 0.875000 +vt 0.531249 0.031250 +vt 0.531250 0.437500 +vt 0.531250 0.843750 +vt 0.539060 0.000000 +vt 0.531250 0.406250 +vt 0.531250 0.812500 +vt 0.531250 0.375000 +vt 0.531250 0.781250 +vt 0.531250 0.343750 +vt 0.531250 0.750000 +vt 0.531250 0.312500 +vt 0.531250 0.718750 +vt 0.531250 0.281250 +vt 0.531250 0.687500 +vt 0.531250 0.250000 +vt 0.531250 0.656250 +vt 0.531250 0.218750 +vt 0.531250 0.625000 +vt 0.531250 0.187500 +vt 0.531250 0.593750 +vt 0.531250 0.156250 +vt 0.539061 1.000000 +vt 0.531249 0.968750 +vt 0.531250 0.125000 +vt 0.515625 0.500000 +vt 0.515625 0.468750 +vt 0.515624 0.906250 +vt 0.515625 0.875000 +vt 0.515624 0.031250 +vt 0.515625 0.437500 +vt 0.515625 0.843750 +vt 0.523435 0.000000 +vt 0.515625 0.406250 +vt 0.515625 0.812500 +vt 0.515625 0.375000 +vt 0.515625 0.781250 +vt 0.515625 0.343750 +vt 0.515625 0.750000 +vt 0.515625 0.312500 +vt 0.515625 0.718750 +vt 0.515625 0.281250 +vt 0.515625 0.687500 +vt 0.515625 0.250000 +vt 0.515625 0.656250 +vt 0.515625 0.218750 +vt 0.515625 0.625000 +vt 0.515625 0.187500 +vt 0.515625 0.593750 +vt 0.515625 0.156250 +vt 0.515625 0.562500 +vt 0.523435 1.000000 +vt 0.515624 0.968750 +vt 0.515625 0.125000 +vt 0.515625 0.531250 +vt 0.515624 0.937500 +vt 0.515624 0.093750 +vt 0.515624 0.062500 +vt 0.500000 0.437500 +vt 0.500000 0.406250 +vt 0.500000 0.812500 +vt 0.500000 0.375000 +vt 0.500000 0.781250 +vt 0.500000 0.343750 +vt 0.500000 0.750000 +vt 0.500000 0.312500 +vt 0.500000 0.718750 +vt 0.500000 0.281250 +vt 0.500000 0.687500 +vt 0.500000 0.250000 +vt 0.500000 0.656250 +vt 0.500000 0.218750 +vt 0.500000 0.625000 +vt 0.500000 0.187500 +vt 0.500000 0.593750 +vt 0.500000 0.156250 +vt 0.500000 0.562500 +vt 0.507810 1.000000 +vt 0.499999 0.968750 +vt 0.500000 0.125000 +vt 0.500000 0.531250 +vt 0.499999 0.937500 +vt 0.499999 0.093750 +vt 0.500000 0.500000 +vt 0.499999 0.906250 +vt 0.499999 0.062500 +vt 0.500000 0.468750 +vt 0.500000 0.875000 +vt 0.499999 0.031250 +vt 0.500000 0.843750 +vt 0.507810 0.000000 +vt 0.484375 0.375000 +vt 0.484375 0.343750 +vt 0.484375 0.750000 +vt 0.484375 0.312500 +vt 0.484375 0.718750 +vt 0.484375 0.281250 +vt 0.484375 0.687500 +vt 0.484375 0.250000 +vt 0.484375 0.656250 +vt 0.484375 0.218750 +vt 0.484375 0.625000 +vt 0.484375 0.187500 +vt 0.484375 0.593750 +vt 0.484375 0.156250 +vt 0.484375 0.562500 +vt 0.492185 1.000000 +vt 0.484374 0.968750 +vt 0.484375 0.125000 +vt 0.484375 0.531250 +vt 0.484374 0.937500 +vt 0.484374 0.093750 +vt 0.484375 0.500000 +vt 0.484374 0.906250 +vt 0.484374 0.062500 +vt 0.484375 0.468750 +vt 0.484375 0.875000 +vt 0.484374 0.031250 +vt 0.484375 0.437500 +vt 0.484375 0.843750 +vt 0.492185 0.000000 +vt 0.484375 0.406250 +vt 0.484375 0.812500 +vt 0.484375 0.781250 +vt 0.468750 0.312500 +vt 0.468750 0.281250 +vt 0.468750 0.687500 +vt 0.468750 0.250000 +vt 0.468750 0.656250 +vt 0.468750 0.218750 +vt 0.468750 0.625000 +vt 0.468750 0.187500 +vt 0.468750 0.593750 +vt 0.468750 0.156250 +vt 0.468750 0.562500 +vt 0.476560 1.000000 +vt 0.468749 0.968750 +vt 0.468750 0.125000 +vt 0.468750 0.531250 +vt 0.468749 0.937500 +vt 0.468749 0.093750 +vt 0.468750 0.500000 +vt 0.468749 0.906250 +vt 0.468749 0.062500 +vt 0.468750 0.468750 +vt 0.468750 0.875000 +vt 0.468749 0.031250 +vt 0.468750 0.437500 +vt 0.468750 0.843750 +vt 0.476560 0.000000 +vt 0.468750 0.406250 +vt 0.468750 0.812500 +vt 0.468750 0.375000 +vt 0.468750 0.781250 +vt 0.468750 0.343750 +vt 0.468750 0.750000 +vt 0.468750 0.718750 +vt 0.453125 0.218750 +vt 0.453125 0.625000 +vt 0.453125 0.187500 +vt 0.453125 0.593750 +vt 0.453125 0.156250 +vt 0.453125 0.562500 +vt 0.460935 1.000000 +vt 0.453124 0.968750 +vt 0.453125 0.125000 +vt 0.453125 0.531250 +vt 0.453124 0.937500 +vt 0.453124 0.093750 +vt 0.453125 0.500000 +vt 0.453124 0.906250 +vt 0.453124 0.062500 +vt 0.453125 0.468750 +vt 0.453125 0.875000 +vt 0.453124 0.031250 +vt 0.453125 0.437500 +vt 0.453125 0.843750 +vt 0.460935 0.000000 +vt 0.453125 0.406250 +vt 0.453125 0.812500 +vt 0.453125 0.375000 +vt 0.453125 0.781250 +vt 0.453125 0.343750 +vt 0.453125 0.750000 +vt 0.453125 0.312500 +vt 0.453125 0.718750 +vt 0.453125 0.281250 +vt 0.453125 0.687500 +vt 0.453125 0.250000 +vt 0.453125 0.656250 +vt 0.437500 0.187500 +vt 0.437500 0.156250 +vt 0.437500 0.562500 +vt 0.445310 1.000000 +vt 0.437499 0.968750 +vt 0.437500 0.125000 +vt 0.437500 0.531250 +vt 0.437499 0.937500 +vt 0.437499 0.093750 +vt 0.437500 0.500000 +vt 0.437499 0.906250 +vt 0.437499 0.062500 +vt 0.437500 0.468750 +vt 0.437500 0.875000 +vt 0.437499 0.031250 +vt 0.437500 0.437500 +vt 0.437500 0.843750 +vt 0.445311 0.000000 +vt 0.437500 0.406250 +vt 0.437500 0.812500 +vt 0.437500 0.375000 +vt 0.437500 0.781250 +vt 0.437500 0.343750 +vt 0.437500 0.750000 +vt 0.437500 0.312500 +vt 0.437500 0.718750 +vt 0.437500 0.281250 +vt 0.437500 0.687500 +vt 0.437500 0.250000 +vt 0.437500 0.656250 +vt 0.437500 0.218750 +vt 0.437500 0.625000 +vt 0.437500 0.593750 +vt 0.421874 0.093750 +vt 0.421875 0.500000 +vt 0.421874 0.906250 +vt 0.421874 0.062500 +vt 0.421875 0.468750 +vt 0.421875 0.875000 +vt 0.421874 0.031250 +vt 0.421875 0.437500 +vt 0.421875 0.843750 +vt 0.429686 0.000000 +vt 0.421875 0.406250 +vt 0.421875 0.812500 +vt 0.421875 0.375000 +vt 0.421875 0.781250 +vt 0.421875 0.343750 +vt 0.421875 0.750000 +vt 0.421875 0.312500 +vt 0.421875 0.718750 +vt 0.421875 0.281250 +vt 0.421875 0.687500 +vt 0.421875 0.250000 +vt 0.421875 0.656250 +vt 0.421875 0.218750 +vt 0.421875 0.625000 +vt 0.421875 0.187500 +vt 0.421875 0.593750 +vt 0.421875 0.156250 +vt 0.421875 0.562500 +vt 0.429685 1.000000 +vt 0.421874 0.968750 +vt 0.421875 0.125000 +vt 0.421875 0.531250 +vt 0.421874 0.937500 +vt 0.406249 0.031250 +vt 0.406250 0.437500 +vt 0.406250 0.843750 +vt 0.414061 0.000000 +vt 0.406250 0.406250 +vt 0.406250 0.812500 +vt 0.406250 0.375000 +vt 0.406250 0.781250 +vt 0.406250 0.343750 +vt 0.406250 0.750000 +vt 0.406250 0.312500 +vt 0.406250 0.718750 +vt 0.406250 0.281250 +vt 0.406250 0.687500 +vt 0.406250 0.250000 +vt 0.406250 0.656250 +vt 0.406250 0.218750 +vt 0.406250 0.625000 +vt 0.406250 0.187500 +vt 0.406250 0.593750 +vt 0.406250 0.156250 +vt 0.406250 0.562500 +vt 0.414060 1.000000 +vt 0.406249 0.968750 +vt 0.406250 0.125000 +vt 0.406250 0.531250 +vt 0.406249 0.937500 +vt 0.406250 0.093750 +vt 0.406250 0.500000 +vt 0.406250 0.906250 +vt 0.406249 0.062500 +vt 0.406250 0.468750 +vt 0.406250 0.875000 +vt 0.390625 0.375000 +vt 0.390625 0.781250 +vt 0.390625 0.343750 +vt 0.390625 0.750000 +vt 0.390625 0.312500 +vt 0.390625 0.718750 +vt 0.390625 0.281250 +vt 0.390625 0.687500 +vt 0.390625 0.250000 +vt 0.390625 0.656250 +vt 0.390625 0.218750 +vt 0.390625 0.625000 +vt 0.390625 0.187500 +vt 0.390625 0.593750 +vt 0.390625 0.156250 +vt 0.390625 0.562500 +vt 0.398435 1.000000 +vt 0.390624 0.968750 +vt 0.390625 0.125000 +vt 0.390625 0.531250 +vt 0.390624 0.937500 +vt 0.390625 0.093750 +vt 0.390625 0.500000 +vt 0.390625 0.906250 +vt 0.390624 0.062500 +vt 0.390625 0.468750 +vt 0.390625 0.875000 +vt 0.390624 0.031250 +vt 0.390625 0.437500 +vt 0.390625 0.843750 +vt 0.398436 0.000000 +vt 0.390625 0.406250 +vt 0.390625 0.812500 +vt 0.375000 0.343750 +vt 0.375000 0.312500 +vt 0.375000 0.718750 +vt 0.375000 0.281250 +vt 0.375000 0.687500 +vt 0.375000 0.250000 +vt 0.375000 0.656250 +vt 0.375000 0.218750 +vt 0.375000 0.625000 +vt 0.375000 0.187500 +vt 0.375000 0.593750 +vt 0.375000 0.156250 +vt 0.375000 0.562500 +vt 0.382810 1.000000 +vt 0.374999 0.968750 +vt 0.375000 0.125000 +vt 0.375000 0.531250 +vt 0.374999 0.937500 +vt 0.375000 0.093750 +vt 0.375000 0.500000 +vt 0.375000 0.906250 +vt 0.374999 0.062500 +vt 0.375000 0.468750 +vt 0.375000 0.875000 +vt 0.374999 0.031250 +vt 0.375000 0.437500 +vt 0.375000 0.843750 +vt 0.382811 0.000000 +vt 0.375000 0.406250 +vt 0.375000 0.812500 +vt 0.375000 0.375000 +vt 0.375000 0.781250 +vt 0.375000 0.750000 +vt 0.359375 0.250000 +vt 0.359375 0.656250 +vt 0.359375 0.218750 +vt 0.359375 0.625000 +vt 0.359375 0.187500 +vt 0.359375 0.593750 +vt 0.359375 0.156250 +vt 0.359375 0.562500 +vt 0.367186 1.000000 +vt 0.359374 0.968750 +vt 0.359375 0.125000 +vt 0.359375 0.531250 +vt 0.359374 0.937500 +vt 0.359375 0.093750 +vt 0.359375 0.500000 +vt 0.359375 0.906250 +vt 0.359374 0.062500 +vt 0.359375 0.468750 +vt 0.359375 0.875000 +vt 0.359374 0.031250 +vt 0.359375 0.437500 +vt 0.359375 0.843750 +vt 0.367186 0.000000 +vt 0.359375 0.406250 +vt 0.359375 0.812500 +vt 0.359375 0.375000 +vt 0.359375 0.781250 +vt 0.359375 0.343750 +vt 0.359375 0.750000 +vt 0.359375 0.312500 +vt 0.359375 0.718750 +vt 0.359375 0.281250 +vt 0.359375 0.687500 +vt 0.343750 0.187500 +vt 0.343750 0.625000 +vt 0.343750 0.593750 +vt 0.343750 0.156250 +vt 0.343750 0.562500 +vt 0.351561 1.000000 +vt 0.343749 0.968750 +vt 0.343750 0.125000 +vt 0.343750 0.531250 +vt 0.343750 0.937500 +vt 0.343750 0.093750 +vt 0.343750 0.500000 +vt 0.343750 0.906250 +vt 0.343750 0.062500 +vt 0.343750 0.468750 +vt 0.343750 0.875000 +vt 0.343749 0.031250 +vt 0.343750 0.437500 +vt 0.343750 0.843750 +vt 0.351561 0.000000 +vt 0.343750 0.406250 +vt 0.343750 0.812500 +vt 0.343750 0.375000 +vt 0.343750 0.781250 +vt 0.343750 0.343750 +vt 0.343750 0.750000 +vt 0.343750 0.312500 +vt 0.343750 0.718750 +vt 0.343750 0.281250 +vt 0.343750 0.687500 +vt 0.343750 0.250000 +vt 0.343750 0.656250 +vt 0.343750 0.218750 +vt 0.328125 0.218750 +vt 0.328125 0.625000 +vt 0.328125 0.187500 +vt 0.328125 0.593750 +vt 0.328125 0.156250 +vt 0.328125 0.562500 +vt 0.335936 1.000000 +vt 0.328124 0.968750 +vt 0.328125 0.125000 +vt 0.328125 0.531250 +vt 0.328125 0.937500 +vt 0.328125 0.093750 +vt 0.328125 0.500000 +vt 0.328125 0.906250 +vt 0.328125 0.062500 +vt 0.328125 0.468750 +vt 0.328125 0.875000 +vt 0.328124 0.031250 +vt 0.328125 0.437500 +vt 0.328125 0.843750 +vt 0.335936 0.000000 +vt 0.328125 0.406250 +vt 0.328125 0.812500 +vt 0.328125 0.375000 +vt 0.328125 0.781250 +vt 0.328125 0.343750 +vt 0.328125 0.750000 +vt 0.328125 0.312500 +vt 0.328125 0.718750 +vt 0.328125 0.281250 +vt 0.328125 0.687500 +vt 0.328125 0.250000 +vt 0.328125 0.656250 +vt 0.312500 0.187500 +vt 0.312500 0.156250 +vt 0.312500 0.562500 +vt 0.320311 1.000000 +vt 0.312499 0.968750 +vt 0.312500 0.125000 +vt 0.312500 0.531250 +vt 0.312500 0.937500 +vt 0.312500 0.093750 +vt 0.312500 0.500000 +vt 0.312500 0.906250 +vt 0.312500 0.062500 +vt 0.312500 0.468750 +vt 0.312500 0.875000 +vt 0.312499 0.031250 +vt 0.312500 0.437500 +vt 0.312500 0.843750 +vt 0.320312 0.000000 +vt 0.312500 0.406250 +vt 0.312500 0.812500 +vt 0.312500 0.375000 +vt 0.312500 0.781250 +vt 0.312500 0.343750 +vt 0.312500 0.750000 +vt 0.312500 0.312500 +vt 0.312500 0.718750 +vt 0.312500 0.281250 +vt 0.312500 0.687500 +vt 0.312500 0.250000 +vt 0.312500 0.656250 +vt 0.312500 0.218750 +vt 0.312500 0.625000 +vt 0.312500 0.593750 +vt 0.296875 0.937500 +vt 0.296875 0.093750 +vt 0.296875 0.531250 +vt 0.296875 0.500000 +vt 0.296875 0.906250 +vt 0.296875 0.062500 +vt 0.296875 0.468750 +vt 0.296875 0.875000 +vt 0.296874 0.031250 +vt 0.296875 0.437500 +vt 0.296875 0.843750 +vt 0.304687 0.000000 +vt 0.296875 0.406250 +vt 0.296875 0.812500 +vt 0.296875 0.375000 +vt 0.296875 0.781250 +vt 0.296875 0.343750 +vt 0.296875 0.750000 +vt 0.296875 0.312500 +vt 0.296875 0.718750 +vt 0.296875 0.281250 +vt 0.296875 0.687500 +vt 0.296875 0.250000 +vt 0.296875 0.656250 +vt 0.296875 0.218750 +vt 0.296875 0.625000 +vt 0.296875 0.187500 +vt 0.296875 0.593750 +vt 0.296875 0.156250 +vt 0.296875 0.562500 +vt 0.304686 1.000000 +vt 0.296874 0.968750 +vt 0.296875 0.125000 +vt 0.281250 0.906250 +vt 0.281250 0.875000 +vt 0.281250 0.031250 +vt 0.281250 0.437500 +vt 0.281250 0.843750 +vt 0.289062 0.000000 +vt 0.281250 0.406250 +vt 0.281250 0.812500 +vt 0.281250 0.375000 +vt 0.281250 0.781250 +vt 0.281250 0.343750 +vt 0.281250 0.750000 +vt 0.281250 0.312500 +vt 0.281250 0.718750 +vt 0.281250 0.281250 +vt 0.281250 0.687500 +vt 0.281250 0.250000 +vt 0.281250 0.656250 +vt 0.281250 0.218750 +vt 0.281250 0.625000 +vt 0.281250 0.187500 +vt 0.281250 0.593750 +vt 0.281250 0.156250 +vt 0.281250 0.562500 +vt 0.289061 1.000000 +vt 0.281250 0.968750 +vt 0.281250 0.125000 +vt 0.281250 0.531250 +vt 0.281250 0.937500 +vt 0.281250 0.093750 +vt 0.281250 0.500000 +vt 0.281250 0.062500 +vt 0.281250 0.468750 +vt 0.265625 0.812500 +vt 0.265625 0.375000 +vt 0.265625 0.781250 +vt 0.265625 0.343750 +vt 0.265625 0.750000 +vt 0.265625 0.312500 +vt 0.265625 0.718750 +vt 0.265625 0.281250 +vt 0.265625 0.687500 +vt 0.265625 0.250000 +vt 0.265625 0.656250 +vt 0.265625 0.218750 +vt 0.265625 0.625000 +vt 0.265625 0.187500 +vt 0.265625 0.593750 +vt 0.265625 0.156250 +vt 0.265625 0.562500 +vt 0.273436 1.000000 +vt 0.265625 0.968750 +vt 0.265625 0.125000 +vt 0.265625 0.531250 +vt 0.265625 0.937500 +vt 0.265625 0.093750 +vt 0.265625 0.500000 +vt 0.265625 0.906250 +vt 0.265625 0.062500 +vt 0.265625 0.468750 +vt 0.265625 0.875000 +vt 0.265625 0.031250 +vt 0.265625 0.437500 +vt 0.265625 0.843750 +vt 0.273437 0.000000 +vt 0.265625 0.406250 +vt 0.250000 0.750000 +vt 0.250000 0.343750 +vt 0.250000 0.312500 +vt 0.250000 0.718750 +vt 0.250000 0.281250 +vt 0.250000 0.687500 +vt 0.250000 0.250000 +vt 0.250000 0.656250 +vt 0.250000 0.218750 +vt 0.250000 0.625000 +vt 0.250000 0.187500 +vt 0.250000 0.593750 +vt 0.250000 0.156250 +vt 0.250000 0.562500 +vt 0.257812 1.000000 +vt 0.250000 0.968750 +vt 0.250000 0.125000 +vt 0.250000 0.531250 +vt 0.250000 0.937500 +vt 0.250000 0.093750 +vt 0.250000 0.500000 +vt 0.250000 0.906250 +vt 0.250000 0.062500 +vt 0.250000 0.468750 +vt 0.250000 0.875000 +vt 0.250000 0.031250 +vt 0.250000 0.437500 +vt 0.250000 0.843750 +vt 0.257812 0.000000 +vt 0.250000 0.406250 +vt 0.250000 0.812500 +vt 0.250000 0.375000 +vt 0.250000 0.781250 +vt 0.234375 0.687500 +vt 0.234375 0.250000 +vt 0.234375 0.656250 +vt 0.234375 0.218750 +vt 0.234375 0.625000 +vt 0.234375 0.187500 +vt 0.234375 0.593750 +vt 0.234375 0.156250 +vt 0.234375 0.562500 +vt 0.242187 1.000000 +vt 0.234375 0.968750 +vt 0.234375 0.125000 +vt 0.234375 0.531250 +vt 0.234375 0.937500 +vt 0.234375 0.093750 +vt 0.234375 0.500000 +vt 0.234375 0.906250 +vt 0.234375 0.062500 +vt 0.234375 0.468750 +vt 0.234375 0.875000 +vt 0.234375 0.031250 +vt 0.234375 0.437500 +vt 0.234375 0.843750 +vt 0.242187 0.000000 +vt 0.234375 0.406250 +vt 0.234375 0.812500 +vt 0.234375 0.375000 +vt 0.234375 0.781250 +vt 0.234375 0.343750 +vt 0.234375 0.750000 +vt 0.234375 0.312500 +vt 0.234375 0.718750 +vt 0.234375 0.281250 +vt 0.218750 0.625000 +vt 0.218750 0.218750 +vt 0.218750 0.187500 +vt 0.218750 0.593750 +vt 0.218750 0.156250 +vt 0.218750 0.562500 +vt 0.226562 1.000000 +vt 0.218750 0.968750 +vt 0.218750 0.125000 +vt 0.218750 0.531250 +vt 0.218750 0.937500 +vt 0.218750 0.093750 +vt 0.218750 0.500000 +vt 0.218750 0.906250 +vt 0.218750 0.062500 +vt 0.218750 0.468750 +vt 0.218750 0.875000 +vt 0.218750 0.031250 +vt 0.218750 0.437500 +vt 0.218750 0.843750 +vt 0.226563 0.000000 +vt 0.218750 0.406250 +vt 0.218750 0.812500 +vt 0.218750 0.375000 +vt 0.218750 0.781250 +vt 0.218750 0.343750 +vt 0.218750 0.750000 +vt 0.218750 0.312500 +vt 0.218750 0.718750 +vt 0.218750 0.281250 +vt 0.218750 0.687500 +vt 0.218750 0.250000 +vt 0.218750 0.656250 +vt 0.203125 0.562500 +vt 0.210937 1.000000 +vt 0.203125 0.968750 +vt 0.203125 0.125000 +vt 0.203125 0.531250 +vt 0.203125 0.937500 +vt 0.203125 0.093750 +vt 0.203125 0.500000 +vt 0.203125 0.906250 +vt 0.203125 0.062500 +vt 0.203125 0.468750 +vt 0.203125 0.875000 +vt 0.203125 0.031250 +vt 0.203125 0.437500 +vt 0.203125 0.843750 +vt 0.210938 0.000000 +vt 0.203125 0.406250 +vt 0.203125 0.812500 +vt 0.203125 0.375000 +vt 0.203125 0.781250 +vt 0.203125 0.343750 +vt 0.203125 0.750000 +vt 0.203125 0.312500 +vt 0.203125 0.718750 +vt 0.203125 0.281250 +vt 0.203125 0.687500 +vt 0.203125 0.250000 +vt 0.203125 0.656250 +vt 0.203125 0.218750 +vt 0.203125 0.625000 +vt 0.203125 0.187500 +vt 0.203125 0.593750 +vt 0.203125 0.156250 +vt 0.187500 0.531250 +vt 0.187500 0.500000 +vt 0.187500 0.906250 +vt 0.187500 0.093750 +vt 0.187500 0.062500 +vt 0.187500 0.468750 +vt 0.187500 0.875000 +vt 0.187500 0.031250 +vt 0.187500 0.437500 +vt 0.187500 0.843750 +vt 0.195313 0.000000 +vt 0.187500 0.406250 +vt 0.187500 0.812500 +vt 0.187500 0.375000 +vt 0.187500 0.781250 +vt 0.187500 0.343750 +vt 0.187500 0.750000 +vt 0.187500 0.312500 +vt 0.187500 0.718750 +vt 0.187500 0.281250 +vt 0.187500 0.687500 +vt 0.187500 0.250000 +vt 0.187500 0.656250 +vt 0.187500 0.218750 +vt 0.187500 0.625000 +vt 0.187500 0.187500 +vt 0.187500 0.593750 +vt 0.187500 0.156250 +vt 0.187500 0.562500 +vt 0.195312 1.000000 +vt 0.187500 0.968750 +vt 0.187500 0.125000 +vt 0.187500 0.937500 +vt 0.171875 0.437500 +vt 0.171875 0.843750 +vt 0.179688 0.000000 +vt 0.171875 0.031250 +vt 0.171875 0.406250 +vt 0.171875 0.812500 +vt 0.171875 0.375000 +vt 0.171875 0.781250 +vt 0.171875 0.343750 +vt 0.171875 0.750000 +vt 0.171875 0.312500 +vt 0.171875 0.718750 +vt 0.171875 0.281250 +vt 0.171875 0.687500 +vt 0.171875 0.250000 +vt 0.171875 0.656250 +vt 0.171875 0.218750 +vt 0.171875 0.625000 +vt 0.171875 0.187500 +vt 0.171875 0.593750 +vt 0.171875 0.156250 +vt 0.171875 0.562500 +vt 0.179688 1.000000 +vt 0.171875 0.968750 +vt 0.171875 0.125000 +vt 0.171875 0.531250 +vt 0.171875 0.937500 +vt 0.171875 0.093750 +vt 0.171875 0.500000 +vt 0.171875 0.906250 +vt 0.171875 0.062500 +vt 0.171875 0.468750 +vt 0.171875 0.875000 +vt 0.156250 0.375000 +vt 0.156250 0.812500 +vt 0.156250 0.781250 +vt 0.156250 0.343750 +vt 0.156250 0.750000 +vt 0.156250 0.312500 +vt 0.156250 0.718750 +vt 0.156250 0.281250 +vt 0.156250 0.687500 +vt 0.156250 0.250000 +vt 0.156250 0.656250 +vt 0.156250 0.218750 +vt 0.156250 0.625000 +vt 0.156250 0.187500 +vt 0.156250 0.593750 +vt 0.156250 0.156250 +vt 0.156250 0.562500 +vt 0.164063 1.000000 +vt 0.156251 0.968750 +vt 0.156250 0.125000 +vt 0.156250 0.531250 +vt 0.156250 0.937500 +vt 0.156250 0.093750 +vt 0.156250 0.500000 +vt 0.156250 0.906250 +vt 0.156250 0.062500 +vt 0.156250 0.468750 +vt 0.156250 0.875000 +vt 0.156251 0.031250 +vt 0.156250 0.437500 +vt 0.156250 0.843750 +vt 0.164063 0.000000 +vt 0.156250 0.406250 +vt 0.140625 0.343750 +vt 0.140625 0.312500 +vt 0.140625 0.718750 +vt 0.140625 0.281250 +vt 0.140625 0.687500 +vt 0.140625 0.250000 +vt 0.140625 0.656250 +vt 0.140625 0.218750 +vt 0.140625 0.625000 +vt 0.140625 0.187500 +vt 0.140625 0.593750 +vt 0.140625 0.156250 +vt 0.140625 0.562500 +vt 0.148438 1.000000 +vt 0.140626 0.968750 +vt 0.140625 0.125000 +vt 0.140625 0.531250 +vt 0.140625 0.937500 +vt 0.140625 0.093750 +vt 0.140625 0.500000 +vt 0.140625 0.906250 +vt 0.140625 0.062500 +vt 0.140625 0.468750 +vt 0.140625 0.875000 +vt 0.140626 0.031250 +vt 0.140625 0.437500 +vt 0.140625 0.843750 +vt 0.148439 0.000000 +vt 0.140625 0.406250 +vt 0.140625 0.812500 +vt 0.140625 0.375000 +vt 0.140625 0.781250 +vt 0.140625 0.750000 +vt 0.125000 0.250000 +vt 0.125000 0.656250 +vt 0.125000 0.218750 +vt 0.125000 0.625000 +vt 0.125000 0.187500 +vt 0.125000 0.593750 +vt 0.125000 0.156250 +vt 0.125000 0.562500 +vt 0.132813 1.000000 +vt 0.125001 0.968750 +vt 0.125000 0.125000 +vt 0.125000 0.531250 +vt 0.125000 0.937500 +vt 0.125000 0.093750 +vt 0.125000 0.500000 +vt 0.125000 0.906250 +vt 0.125000 0.062500 +vt 0.125000 0.468750 +vt 0.125000 0.875000 +vt 0.125001 0.031250 +vt 0.125000 0.437500 +vt 0.125000 0.843750 +vt 0.132814 0.000000 +vt 0.125000 0.406250 +vt 0.125000 0.812500 +vt 0.125000 0.375000 +vt 0.125000 0.781250 +vt 0.125000 0.343750 +vt 0.125000 0.750000 +vt 0.125000 0.312500 +vt 0.125000 0.718750 +vt 0.125000 0.281250 +vt 0.125000 0.687500 +vt 0.109375 0.218750 +vt 0.109375 0.187500 +vt 0.109375 0.625000 +vt 0.109375 0.593750 +vt 0.109375 0.156250 +vt 0.109375 0.562500 +vt 0.117188 1.000000 +vt 0.109376 0.968750 +vt 0.109375 0.125000 +vt 0.109375 0.531250 +vt 0.109375 0.937500 +vt 0.109375 0.093750 +vt 0.109375 0.500000 +vt 0.109375 0.906250 +vt 0.109375 0.062500 +vt 0.109375 0.468750 +vt 0.109375 0.875000 +vt 0.109376 0.031250 +vt 0.109375 0.437500 +vt 0.109375 0.843750 +vt 0.117189 0.000000 +vt 0.109375 0.406250 +vt 0.109375 0.812500 +vt 0.109375 0.375000 +vt 0.109375 0.781250 +vt 0.109375 0.343750 +vt 0.109375 0.750000 +vt 0.109375 0.312500 +vt 0.109375 0.718750 +vt 0.109375 0.281250 +vt 0.109375 0.687500 +vt 0.109375 0.250000 +vt 0.109375 0.656250 +vt 0.101564 1.000000 +vt 0.093751 0.968750 +vt 0.093750 0.156250 +vt 0.093750 0.125000 +vt 0.093750 0.562500 +vt 0.093750 0.531250 +vt 0.093750 0.937500 +vt 0.093750 0.093750 +vt 0.093750 0.500000 +vt 0.093750 0.906250 +vt 0.093750 0.062500 +vt 0.093750 0.468750 +vt 0.093750 0.875000 +vt 0.093751 0.031250 +vt 0.093750 0.437500 +vt 0.093750 0.843750 +vt 0.101564 0.000000 +vt 0.093750 0.406250 +vt 0.093750 0.812500 +vt 0.093750 0.375000 +vt 0.093750 0.781250 +vt 0.093750 0.343750 +vt 0.093750 0.750000 +vt 0.093750 0.312500 +vt 0.093750 0.718750 +vt 0.093750 0.281250 +vt 0.093750 0.687500 +vt 0.093750 0.250000 +vt 0.093750 0.656250 +vt 0.093750 0.218750 +vt 0.093750 0.625000 +vt 0.093750 0.187500 +vt 0.093750 0.593750 +vt 0.078125 0.906250 +vt 0.078125 0.062500 +vt 0.078125 0.500000 +vt 0.078125 0.468750 +vt 0.078125 0.875000 +vt 0.078126 0.031250 +vt 0.078125 0.437500 +vt 0.078125 0.843750 +vt 0.085939 0.000000 +vt 0.078125 0.406250 +vt 0.078125 0.812500 +vt 0.078125 0.375000 +vt 0.078125 0.781250 +vt 0.078125 0.343750 +vt 0.078125 0.750000 +vt 0.078125 0.312500 +vt 0.078125 0.718750 +vt 0.078125 0.281250 +vt 0.078125 0.687500 +vt 0.078125 0.250000 +vt 0.078125 0.656250 +vt 0.078125 0.218750 +vt 0.078125 0.625000 +vt 0.078125 0.187500 +vt 0.078125 0.593750 +vt 0.078125 0.156250 +vt 0.078125 0.562500 +vt 0.085939 1.000000 +vt 0.078126 0.968750 +vt 0.078125 0.125000 +vt 0.078125 0.531250 +vt 0.078125 0.937500 +vt 0.078125 0.093750 +vt 0.062500 0.843750 +vt 0.070314 0.000000 +vt 0.062501 0.031250 +vt 0.062500 0.437500 +vt 0.062500 0.406250 +vt 0.062500 0.812500 +vt 0.062500 0.375000 +vt 0.062500 0.781250 +vt 0.062500 0.343750 +vt 0.062500 0.750000 +vt 0.062500 0.312500 +vt 0.062500 0.718750 +vt 0.062500 0.281250 +vt 0.062500 0.687500 +vt 0.062500 0.250000 +vt 0.062500 0.656250 +vt 0.062500 0.218750 +vt 0.062500 0.625000 +vt 0.062500 0.187500 +vt 0.062500 0.593750 +vt 0.062500 0.156250 +vt 0.062500 0.562500 +vt 0.070314 1.000000 +vt 0.062501 0.968750 +vt 0.062500 0.125000 +vt 0.062500 0.531250 +vt 0.062500 0.937500 +vt 0.062500 0.093750 +vt 0.062500 0.500000 +vt 0.062500 0.906250 +vt 0.062501 0.062500 +vt 0.062500 0.468750 +vt 0.062500 0.875000 +vt 0.046875 0.812500 +vt 0.046875 0.781250 +vt 0.046875 0.375000 +vt 0.046875 0.343750 +vt 0.046875 0.750000 +vt 0.046875 0.312500 +vt 0.046875 0.718750 +vt 0.046875 0.281250 +vt 0.046875 0.687500 +vt 0.046875 0.250000 +vt 0.046875 0.656250 +vt 0.046875 0.218750 +vt 0.046875 0.625000 +vt 0.046875 0.187500 +vt 0.046875 0.593750 +vt 0.046875 0.156250 +vt 0.046875 0.562500 +vt 0.054689 1.000000 +vt 0.046876 0.968750 +vt 0.046875 0.125000 +vt 0.046875 0.531250 +vt 0.046876 0.937500 +vt 0.046875 0.093750 +vt 0.046875 0.500000 +vt 0.046875 0.906250 +vt 0.046876 0.062500 +vt 0.046875 0.468750 +vt 0.046875 0.875000 +vt 0.046876 0.031250 +vt 0.046875 0.437500 +vt 0.046875 0.843750 +vt 0.054689 0.000000 +vt 0.046875 0.406250 +vt 0.031250 0.718750 +vt 0.031250 0.312500 +vt 0.031250 0.281250 +vt 0.031250 0.687500 +vt 0.031250 0.250000 +vt 0.031250 0.656250 +vt 0.031250 0.218750 +vt 0.031250 0.625000 +vt 0.031250 0.187500 +vt 0.031250 0.593750 +vt 0.031250 0.156250 +vt 0.031250 0.562500 +vt 0.039064 1.000000 +vt 0.031251 0.968750 +vt 0.031250 0.125000 +vt 0.031250 0.531250 +vt 0.031251 0.937500 +vt 0.031250 0.093750 +vt 0.031250 0.500000 +vt 0.031250 0.906250 +vt 0.031251 0.062500 +vt 0.031250 0.468750 +vt 0.031250 0.875000 +vt 0.031251 0.031250 +vt 0.031250 0.437500 +vt 0.031250 0.843750 +vt 0.039064 0.000000 +vt 0.031250 0.406250 +vt 0.031250 0.812500 +vt 0.031250 0.375000 +vt 0.031250 0.781250 +vt 0.031250 0.343750 +vt 0.031250 0.750000 +vt 0.015625 0.656250 +vt 0.015625 0.218750 +vt 0.015625 0.625000 +vt 0.015625 0.187500 +vt 0.015625 0.593750 +vt 0.015625 0.156250 +vt 0.015625 0.562500 +vt 0.023439 1.000000 +vt 0.015626 0.968750 +vt 0.015625 0.125000 +vt 0.015625 0.531250 +vt 0.015626 0.937500 +vt 0.015625 0.093750 +vt 0.015625 0.500000 +vt 0.015625 0.906250 +vt 0.015626 0.062500 +vt 0.015625 0.468750 +vt 0.015625 0.875000 +vt 0.015626 0.031250 +vt 0.015625 0.437500 +vt 0.015625 0.843750 +vt 0.023439 0.000000 +vt 0.015625 0.406250 +vt 0.015625 0.812500 +vt 0.015625 0.375000 +vt 0.015625 0.781250 +vt 0.015625 0.343750 +vt 0.015625 0.750000 +vt 0.015625 0.312500 +vt 0.015625 0.718750 +vt 0.015625 0.281250 +vt 0.015625 0.687500 +vt 0.015625 0.250000 +vt 0.000000 0.625000 +vt 0.000000 0.593750 +vt 0.000000 0.156250 +vt 0.000000 0.562500 +vt 0.007814 1.000000 +vt 0.000001 0.968750 +vt 0.000000 0.125000 +vt 0.000000 0.531250 +vt 0.000001 0.937500 +vt 0.000000 0.093750 +vt 0.000000 0.500000 +vt 0.000000 0.906250 +vt 0.000001 0.062500 +vt 0.000000 0.468750 +vt 0.000000 0.875000 +vt 0.000001 0.031250 +vt 0.000000 0.437500 +vt 0.000000 0.843750 +vt 0.007814 0.000000 +vt 0.000000 0.406250 +vt 0.000000 0.812500 +vt 0.000000 0.375000 +vt 0.000000 0.781250 +vt 0.000000 0.343750 +vt 0.000000 0.750000 +vt 0.000000 0.312500 +vt 0.000000 0.718750 +vt 0.000000 0.281250 +vt 0.000000 0.687500 +vt 0.000000 0.250000 +vt 0.000000 0.656250 +vt 0.000000 0.218750 +vt 0.000000 0.187500 +vt 1.000000 0.531250 +vt 0.984375 0.562500 +vt 0.984375 0.531250 +vt 1.000001 0.968750 +vt 0.984375 0.937500 +vt 1.000001 0.937500 +vt 1.000000 0.093750 +vt 0.984375 0.125000 +vt 0.984375 0.093750 +vt 0.984375 0.500000 +vt 1.000000 0.500000 +vt 0.984375 0.906250 +vt 1.000000 0.906250 +vt 0.984375 0.062500 +vt 1.000001 0.062500 +vt 1.000000 0.468750 +vt 0.984375 0.468750 +vt 0.984375 0.875000 +vt 1.000000 0.875000 +vt 0.984376 0.031250 +vt 1.000001 0.031250 +vt 0.984375 0.437500 +vt 1.000000 0.437500 +vt 0.984375 0.843750 +vt 1.000000 0.843750 +vt 0.992189 0.000000 +vt 1.000000 0.406250 +vt 0.984375 0.406250 +vt 1.000000 0.812500 +vt 0.984375 0.812500 +vt 0.984375 0.375000 +vt 1.000000 0.375000 +vt 0.984375 0.781250 +vt 1.000000 0.781250 +vt 1.000000 0.343750 +vt 0.984375 0.343750 +vt 0.984375 0.750000 +vt 1.000000 0.750000 +vt 1.000000 0.312500 +vt 0.984375 0.312500 +vt 0.984375 0.718750 +vt 1.000000 0.718750 +vt 0.984375 0.281250 +vt 1.000000 0.281250 +vt 1.000000 0.687500 +vt 0.984375 0.687500 +vt 0.984375 0.250000 +vt 1.000000 0.250000 +vt 0.984375 0.656250 +vt 1.000000 0.656250 +vt 0.984375 0.218750 +vt 1.000000 0.218750 +vt 0.984375 0.625000 +vt 1.000000 0.625000 +vt 0.984375 0.187500 +vt 1.000000 0.187500 +vt 1.000000 0.593750 +vt 0.984375 0.593750 +vt 0.984375 0.156250 +vt 1.000000 0.156250 +vt 1.000000 0.562500 +vt 0.992189 1.000000 +vt 0.984376 0.968750 +vt 1.000000 0.125000 +vt 0.968750 0.500000 +vt 0.968750 0.468750 +vt 0.968750 0.875000 +vt 0.968751 0.031250 +vt 0.968750 0.437500 +vt 0.968750 0.843750 +vt 0.976564 0.000000 +vt 0.968750 0.406250 +vt 0.968750 0.812500 +vt 0.968750 0.375000 +vt 0.968750 0.781250 +vt 0.968750 0.343750 +vt 0.968750 0.750000 +vt 0.968750 0.312500 +vt 0.968750 0.718750 +vt 0.968750 0.281250 +vt 0.968750 0.687500 +vt 0.968750 0.250000 +vt 0.968750 0.656250 +vt 0.968750 0.218750 +vt 0.968750 0.625000 +vt 0.968750 0.187500 +vt 0.968750 0.593750 +vt 0.968750 0.156250 +vt 0.968750 0.562500 +vt 0.976564 1.000000 +vt 0.968751 0.968750 +vt 0.968750 0.125000 +vt 0.968750 0.531250 +vt 0.968750 0.937500 +vt 0.968750 0.093750 +vt 0.968750 0.906250 +vt 0.968750 0.062500 +vt 0.953125 0.437500 +vt 0.953125 0.406250 +vt 0.953125 0.843750 +vt 0.953125 0.812500 +vt 0.953125 0.375000 +vt 0.953125 0.781250 +vt 0.953125 0.343750 +vt 0.953125 0.750000 +vt 0.953125 0.312500 +vt 0.953125 0.718750 +vt 0.953125 0.281250 +vt 0.953125 0.687500 +vt 0.953125 0.250000 +vt 0.953125 0.656250 +vt 0.953125 0.218750 +vt 0.953125 0.625000 +vt 0.953125 0.187500 +vt 0.953125 0.593750 +vt 0.953125 0.156250 +vt 0.953125 0.562500 +vt 0.960939 1.000000 +vt 0.953126 0.968750 +vt 0.953125 0.125000 +vt 0.953125 0.531250 +vt 0.953125 0.937500 +vt 0.953125 0.093750 +vt 0.953125 0.500000 +vt 0.953125 0.906250 +vt 0.953125 0.062500 +vt 0.953125 0.468750 +vt 0.953125 0.875000 +vt 0.953126 0.031250 +vt 0.960939 0.000000 +vt 0.937500 0.500000 +vt 0.937500 0.906250 +vt 0.937500 0.062500 +vt 0.937500 0.468750 +vt 0.937500 0.875000 +vt 0.937501 0.031250 +vt 0.937500 0.437500 +vt 0.937500 0.843750 +vt 0.945314 0.000000 +vt 0.937500 0.406250 +vt 0.937500 0.812500 +vt 0.937500 0.375000 +vt 0.937500 0.781250 +vt 0.937500 0.343750 +vt 0.937500 0.750000 +vt 0.937500 0.312500 +vt 0.937500 0.718750 +vt 0.937500 0.281250 +vt 0.937500 0.687500 +vt 0.937500 0.250000 +vt 0.937500 0.656250 +vt 0.937500 0.218750 +vt 0.937500 0.625000 +vt 0.937500 0.187500 +vt 0.937500 0.593750 +vt 0.937500 0.156250 +vt 0.937500 0.562500 +vt 0.945314 1.000000 +vt 0.937501 0.968750 +vt 0.937500 0.125000 +vt 0.937500 0.531250 +vt 0.937500 0.937500 +vt 0.937500 0.093750 +vt 0.921875 0.437500 +vt 0.921875 0.843750 +vt 0.929689 0.000000 +vt 0.921876 0.031250 +vt 0.921875 0.406250 +vt 0.921875 0.812500 +vt 0.921875 0.375000 +vt 0.921875 0.781250 +vt 0.921875 0.343750 +vt 0.921875 0.750000 +vt 0.921875 0.312500 +vt 0.921875 0.718750 +vt 0.921875 0.281250 +vt 0.921875 0.687500 +vt 0.921875 0.250000 +vt 0.921875 0.656250 +vt 0.921875 0.218750 +vt 0.921875 0.625000 +vt 0.921875 0.187500 +vt 0.921875 0.593750 +vt 0.921875 0.156250 +vt 0.921875 0.562500 +vt 0.929689 1.000000 +vt 0.921876 0.968750 +vt 0.921875 0.125000 +vt 0.921875 0.531250 +vt 0.921875 0.937500 +vt 0.921875 0.093750 +vt 0.921875 0.500000 +vt 0.921875 0.906250 +vt 0.921875 0.062500 +vt 0.921875 0.468750 +vt 0.921875 0.875000 +vt 0.906250 0.375000 +vt 0.906250 0.812500 +vt 0.906250 0.781250 +vt 0.906250 0.343750 +vt 0.906250 0.750000 +vt 0.906250 0.312500 +vt 0.906250 0.718750 +vt 0.906250 0.281250 +vt 0.906250 0.687500 +vt 0.906250 0.250000 +vt 0.906250 0.656250 +vt 0.906250 0.218750 +vt 0.906250 0.625000 +vt 0.906250 0.187500 +vt 0.906250 0.593750 +vt 0.906250 0.156250 +vt 0.906250 0.562500 +vt 0.914064 1.000000 +vt 0.906251 0.968750 +vt 0.906250 0.125000 +vt 0.906250 0.531250 +vt 0.906250 0.937500 +vt 0.906250 0.093750 +vt 0.906250 0.500000 +vt 0.906250 0.906250 +vt 0.906250 0.062500 +vt 0.906250 0.468750 +vt 0.906250 0.875000 +vt 0.906251 0.031250 +vt 0.906250 0.437500 +vt 0.906250 0.843750 +vt 0.914064 0.000000 +vt 0.906250 0.406250 +vt 0.890625 0.343750 +vt 0.890625 0.312500 +vt 0.890625 0.718750 +vt 0.890625 0.281250 +vt 0.890625 0.687500 +vt 0.890625 0.250000 +vt 0.890625 0.656250 +vt 0.890625 0.218750 +vt 0.890625 0.625000 +vt 0.890625 0.187500 +vt 0.890625 0.593750 +vt 0.890625 0.156250 +vt 0.890625 0.562500 +vt 0.898439 1.000000 +vt 0.890626 0.968750 +vt 0.890625 0.125000 +vt 0.890625 0.531250 +vt 0.890625 0.937500 +vt 0.890625 0.093750 +vt 0.890625 0.500000 +vt 0.890625 0.906250 +vt 0.890625 0.062500 +vt 0.890625 0.468750 +vt 0.890625 0.875000 +vt 0.890626 0.031250 +vt 0.890625 0.437500 +vt 0.890625 0.843750 +vt 0.898439 0.000000 +vt 0.890625 0.406250 +vt 0.890625 0.812500 +vt 0.890625 0.375000 +vt 0.890625 0.781250 +vt 0.890625 0.750000 +vt 0.875000 0.250000 +vt 0.875000 0.656250 +vt 0.875000 0.218750 +vt 0.875000 0.625000 +vt 0.875000 0.187500 +vt 0.875000 0.593750 +vt 0.875000 0.156250 +vt 0.875000 0.562500 +vt 0.882814 1.000000 +vt 0.875001 0.968750 +vt 0.875000 0.125000 +vt 0.875000 0.531250 +vt 0.875000 0.937500 +vt 0.875000 0.093750 +vt 0.875000 0.500000 +vt 0.875000 0.906250 +vt 0.875000 0.062500 +vt 0.875000 0.468750 +vt 0.875000 0.875000 +vt 0.875001 0.031250 +vt 0.875000 0.437500 +vt 0.875000 0.843750 +vt 0.882814 0.000000 +vt 0.875000 0.406250 +vt 0.875000 0.812500 +vt 0.875000 0.375000 +vt 0.875000 0.781250 +vt 0.875000 0.343750 +vt 0.875000 0.750000 +vt 0.875000 0.312500 +vt 0.875000 0.718750 +vt 0.875000 0.281250 +vt 0.875000 0.687500 +vt 0.859375 0.187500 +vt 0.859375 0.625000 +vt 0.859375 0.593750 +vt 0.859375 0.156250 +vt 0.859375 0.562500 +vt 0.867189 1.000000 +vt 0.859376 0.968750 +vt 0.859375 0.125000 +vt 0.859375 0.531250 +vt 0.859375 0.937500 +vt 0.859375 0.093750 +vt 0.859375 0.500000 +vt 0.859375 0.906250 +vt 0.859375 0.062500 +vt 0.859375 0.468750 +vt 0.859375 0.875000 +vt 0.859376 0.031250 +vt 0.859375 0.437500 +vt 0.859375 0.843750 +vt 0.867189 0.000000 +vt 0.859375 0.406250 +vt 0.859375 0.812500 +vt 0.859375 0.375000 +vt 0.859375 0.781250 +vt 0.859375 0.343750 +vt 0.859375 0.750000 +vt 0.859375 0.312500 +vt 0.859375 0.718750 +vt 0.859375 0.281250 +vt 0.859375 0.687500 +vt 0.859375 0.250000 +vt 0.859375 0.656250 +vt 0.859375 0.218750 +vt 0.851564 1.000000 +vt 0.843751 0.968750 +vt 0.843750 0.125000 +vt 0.843750 0.562500 +vt 0.843750 0.531250 +vt 0.843750 0.937500 +vt 0.843750 0.093750 +vt 0.843750 0.500000 +vt 0.843750 0.906250 +vt 0.843750 0.062500 +vt 0.843750 0.468750 +vt 0.843750 0.875000 +vt 0.843751 0.031250 +vt 0.843750 0.437500 +vt 0.843750 0.843750 +vt 0.851564 0.000000 +vt 0.843750 0.406250 +vt 0.843750 0.812500 +vt 0.843750 0.375000 +vt 0.843750 0.781250 +vt 0.843750 0.343750 +vt 0.843750 0.750000 +vt 0.843750 0.312500 +vt 0.843750 0.718750 +vt 0.843750 0.281250 +vt 0.843750 0.687500 +vt 0.843750 0.250000 +vt 0.843750 0.656250 +vt 0.843750 0.218750 +vt 0.843750 0.625000 +vt 0.843750 0.187500 +vt 0.843750 0.593750 +vt 0.843750 0.156250 +vt 0.828125 0.906250 +vt 0.828125 0.062500 +vt 0.828125 0.500000 +vt 0.828125 0.468750 +vt 0.828125 0.875000 +vt 0.828125 0.031250 +vt 0.828125 0.437500 +vt 0.828125 0.843750 +vt 0.835938 0.000000 +vt 0.828125 0.406250 +vt 0.828125 0.812500 +vt 0.828125 0.375000 +vt 0.828125 0.781250 +vt 0.828125 0.343750 +vt 0.828125 0.750000 +vt 0.828125 0.312500 +vt 0.828125 0.718750 +vt 0.828125 0.281250 +vt 0.828125 0.687500 +vt 0.828125 0.250000 +vt 0.828125 0.656250 +vt 0.828125 0.218750 +vt 0.828125 0.625000 +vt 0.828125 0.187500 +vt 0.828125 0.593750 +vt 0.828125 0.156250 +vt 0.828125 0.562500 +vt 0.835939 1.000000 +vt 0.828125 0.968750 +vt 0.828125 0.125000 +vt 0.828125 0.531250 +vt 0.828125 0.937500 +vt 0.828125 0.093750 +vt 0.812500 0.843750 +vt 0.820313 0.000000 +vt 0.812500 0.031250 +vt 0.812500 0.437500 +vt 0.812500 0.406250 +vt 0.812500 0.812500 +vt 0.812500 0.375000 +vt 0.812500 0.781250 +vt 0.812500 0.343750 +vt 0.812500 0.750000 +vt 0.812500 0.312500 +vt 0.812500 0.718750 +vt 0.812500 0.281250 +vt 0.812500 0.687500 +vt 0.812500 0.250000 +vt 0.812500 0.656250 +vt 0.812500 0.218750 +vt 0.812500 0.625000 +vt 0.812500 0.187500 +vt 0.812500 0.593750 +vt 0.812500 0.156250 +vt 0.812500 0.562500 +vt 0.820314 1.000000 +vt 0.812500 0.968750 +vt 0.812500 0.125000 +vt 0.812500 0.531250 +vt 0.812500 0.937500 +vt 0.812500 0.093750 +vt 0.812500 0.500000 +vt 0.812500 0.906250 +vt 0.812500 0.062500 +vt 0.812500 0.468750 +vt 0.812500 0.875000 +vt 0.796875 0.812500 +vt 0.796875 0.781250 +vt 0.796875 0.375000 +vt 0.796875 0.343750 +vt 0.796875 0.750000 +vt 0.796875 0.312500 +vt 0.796875 0.718750 +vt 0.796875 0.281250 +vt 0.796875 0.687500 +vt 0.796875 0.250000 +vt 0.796875 0.656250 +vt 0.796875 0.218750 +vt 0.796875 0.625000 +vt 0.796875 0.187500 +vt 0.796875 0.593750 +vt 0.796875 0.156250 +vt 0.796875 0.562500 +vt 0.804689 1.000000 +vt 0.796875 0.968750 +vt 0.796875 0.125000 +vt 0.796875 0.531250 +vt 0.796875 0.937500 +vt 0.796875 0.093750 +vt 0.796875 0.500000 +vt 0.796875 0.906250 +vt 0.796875 0.062500 +vt 0.796875 0.468750 +vt 0.796875 0.875000 +vt 0.796875 0.031250 +vt 0.796875 0.437500 +vt 0.796875 0.843750 +vt 0.804688 0.000000 +vt 0.796875 0.406250 +vt 0.781250 0.718750 +vt 0.781250 0.312500 +vt 0.781250 0.281250 +vt 0.781250 0.687500 +vt 0.781250 0.250000 +vt 0.781250 0.656250 +vt 0.781250 0.218750 +vt 0.781250 0.625000 +vt 0.781250 0.187500 +vt 0.781250 0.593750 +vt 0.781250 0.156250 +vt 0.781250 0.562500 +vt 0.789063 1.000000 +vt 0.781250 0.968750 +vt 0.781250 0.125000 +vt 0.781250 0.531250 +vt 0.781250 0.937500 +vt 0.781250 0.093750 +vt 0.781250 0.500000 +vt 0.781250 0.906250 +vt 0.781250 0.062500 +vt 0.781250 0.468750 +vt 0.781250 0.875000 +vt 0.781250 0.031250 +vt 0.781250 0.437500 +vt 0.781250 0.843750 +vt 0.789063 0.000000 +vt 0.781250 0.406250 +vt 0.781250 0.812500 +vt 0.781250 0.375000 +vt 0.781250 0.781250 +vt 0.781250 0.343750 +vt 0.781250 0.750000 +vt 0.765625 0.656250 +vt 0.765625 0.218750 +vt 0.765625 0.625000 +vt 0.765625 0.187500 +vt 0.765625 0.593750 +vt 0.765625 0.156250 +vt 0.765625 0.562500 +vt 0.773438 1.000000 +vt 0.765625 0.968750 +vt 0.765625 0.125000 +vt 0.765625 0.531250 +vt 0.765625 0.937500 +vt 0.765625 0.093750 +vt 0.765625 0.500000 +vt 0.765625 0.906250 +vt 0.765625 0.062500 +vt 0.765625 0.468750 +vt 0.765625 0.875000 +vt 0.765625 0.031250 +vt 0.765625 0.437500 +vt 0.765625 0.843750 +vt 0.773438 0.000000 +vt 0.765625 0.406250 +vt 0.765625 0.812500 +vt 0.765625 0.375000 +vt 0.765625 0.781250 +vt 0.765625 0.343750 +vt 0.765625 0.750000 +vt 0.765625 0.312500 +vt 0.765625 0.718750 +vt 0.765625 0.281250 +vt 0.765625 0.687500 +vt 0.765625 0.250000 +vt 0.757813 1.000000 +vt 0.757812 0.000000 +vn 0.0394 -0.5952 -0.8026 +vn 0.0394 0.5952 -0.8026 +vn 0.0364 -0.6711 -0.7405 +vn 0.0421 0.5136 -0.8570 +vn 0.0330 -0.7405 -0.6712 +vn 0.0444 0.4271 -0.9031 +vn 0.0293 -0.8029 -0.5954 +vn 0.0462 0.3365 -0.9405 +vn 0.0252 -0.8575 -0.5139 +vn 0.0476 0.2427 -0.9689 +vn 0.0024 0.9988 -0.0491 +vn 0.0210 -0.9038 -0.4275 +vn 0.0485 0.1466 -0.9880 +vn 0.0072 0.9892 -0.1467 +vn 0.0165 -0.9414 -0.3368 +vn 0.0490 0.0490 -0.9976 +vn 0.0119 0.9700 -0.2430 +vn 0.0119 -0.9700 -0.2430 +vn 0.0490 -0.0490 -0.9976 +vn 0.0165 0.9414 -0.3368 +vn 0.0072 -0.9892 -0.1467 +vn 0.0485 -0.1466 -0.9880 +vn 0.0210 0.9038 -0.4275 +vn 0.0024 -0.9988 -0.0491 +vn 0.0476 -0.2427 -0.9689 +vn 0.0252 0.8575 -0.5139 +vn 0.0462 -0.3365 -0.9405 +vn 0.0293 0.8029 -0.5954 +vn 0.0444 -0.4271 -0.9031 +vn 0.0330 0.7405 -0.6712 +vn 0.0421 -0.5136 -0.8570 +vn 0.0364 0.6711 -0.7405 +vn 0.1451 -0.1466 -0.9785 +vn 0.0628 0.9038 -0.4233 +vn 0.0072 -0.9988 -0.0486 +vn 0.1423 -0.2427 -0.9596 +vn 0.0755 0.8575 -0.5090 +vn 0.1382 -0.3365 -0.9315 +vn 0.0875 0.8029 -0.5897 +vn 0.1327 -0.4271 -0.8944 +vn 0.0986 0.7405 -0.6647 +vn 0.1259 -0.5136 -0.8487 +vn 0.1088 0.6711 -0.7333 +vn 0.1179 -0.5952 -0.7949 +vn 0.1179 0.5952 -0.7949 +vn 0.1088 -0.6711 -0.7333 +vn 0.1259 0.5136 -0.8487 +vn 0.0986 -0.7405 -0.6647 +vn 0.1327 0.4271 -0.8944 +vn 0.0875 -0.8029 -0.5897 +vn 0.1382 0.3365 -0.9315 +vn 0.0755 -0.8575 -0.5090 +vn 0.1423 0.2427 -0.9596 +vn 0.0072 0.9988 -0.0486 +vn 0.0628 -0.9038 -0.4233 +vn 0.1451 0.1466 -0.9785 +vn 0.0216 0.9892 -0.1453 +vn 0.0495 -0.9414 -0.3336 +vn 0.1466 0.0490 -0.9880 +vn 0.0357 0.9700 -0.2406 +vn 0.0357 -0.9700 -0.2406 +vn 0.1466 -0.0490 -0.9880 +vn 0.0495 0.9414 -0.3336 +vn 0.0216 -0.9892 -0.1453 +vn 0.2288 -0.3365 -0.9135 +vn 0.1449 0.8029 -0.5783 +vn 0.2197 -0.4271 -0.8771 +vn 0.1633 0.7405 -0.6519 +vn 0.2085 -0.5136 -0.8323 +vn 0.1801 0.6711 -0.7191 +vn 0.1952 -0.5952 -0.7795 +vn 0.1952 0.5952 -0.7795 +vn 0.1801 -0.6711 -0.7191 +vn 0.2085 0.5136 -0.8323 +vn 0.1633 -0.7405 -0.6519 +vn 0.2197 0.4271 -0.8771 +vn 0.1449 -0.8029 -0.5783 +vn 0.2288 0.3365 -0.9135 +vn 0.1250 -0.8575 -0.4991 +vn 0.2357 0.2427 -0.9410 +vn 0.0119 0.9988 -0.0477 +vn 0.1040 -0.9038 -0.4151 +vn 0.2404 0.1466 -0.9596 +vn 0.0357 0.9892 -0.1425 +vn 0.0819 -0.9414 -0.3271 +vn 0.2427 0.0490 -0.9689 +vn 0.0591 0.9700 -0.2360 +vn 0.0591 -0.9700 -0.2360 +vn 0.2427 -0.0490 -0.9689 +vn 0.0819 0.9414 -0.3271 +vn 0.0357 -0.9892 -0.1425 +vn 0.2404 -0.1466 -0.9596 +vn 0.1040 0.9038 -0.4152 +vn 0.0119 -0.9988 -0.0477 +vn 0.2357 -0.2427 -0.9410 +vn 0.1250 0.8575 -0.4991 +vn 0.2891 -0.5136 -0.8078 +vn 0.2498 0.6711 -0.6980 +vn 0.2707 -0.5952 -0.7566 +vn 0.2707 0.5952 -0.7566 +vn 0.2498 -0.6711 -0.6980 +vn 0.2891 0.5136 -0.8078 +vn 0.2264 -0.7405 -0.6327 +vn 0.3046 0.4271 -0.8513 +vn 0.2008 -0.8029 -0.5613 +vn 0.3172 0.3365 -0.8866 +vn 0.1733 -0.8575 -0.4845 +vn 0.3268 0.2427 -0.9134 +vn 0.0166 0.9988 -0.0463 +vn 0.1442 -0.9038 -0.4030 +vn 0.3333 0.1466 -0.9314 +vn 0.0495 0.9892 -0.1383 +vn 0.1136 -0.9414 -0.3175 +vn 0.3365 0.0490 -0.9404 +vn 0.0820 0.9700 -0.2290 +vn 0.0820 -0.9700 -0.2290 +vn 0.3365 -0.0490 -0.9404 +vn 0.1136 0.9414 -0.3175 +vn 0.0495 -0.9892 -0.1383 +vn 0.3333 -0.1466 -0.9314 +vn 0.1442 0.9038 -0.4030 +vn 0.0166 -0.9988 -0.0463 +vn 0.3268 -0.2427 -0.9134 +vn 0.1733 0.8575 -0.4845 +vn 0.3172 -0.3365 -0.8866 +vn 0.2008 0.8029 -0.5613 +vn 0.3046 -0.4271 -0.8513 +vn 0.2264 0.7405 -0.6327 +vn 0.3170 -0.6711 -0.6702 +vn 0.3668 0.5136 -0.7756 +vn 0.2873 -0.7405 -0.6075 +vn 0.3866 0.4271 -0.8174 +vn 0.2549 -0.8029 -0.5389 +vn 0.4026 0.3365 -0.8513 +vn 0.2200 -0.8575 -0.4652 +vn 0.4148 0.2427 -0.8770 +vn 0.0210 0.9988 -0.0444 +vn 0.1830 -0.9038 -0.3869 +vn 0.4229 0.1466 -0.8942 +vn 0.0628 0.9892 -0.1328 +vn 0.1442 -0.9414 -0.3049 +vn 0.4270 0.0490 -0.9029 +vn 0.1040 0.9700 -0.2199 +vn 0.1040 -0.9700 -0.2199 +vn 0.4270 -0.0490 -0.9029 +vn 0.1442 0.9414 -0.3049 +vn 0.0628 -0.9892 -0.1328 +vn 0.4229 -0.1466 -0.8942 +vn 0.1830 0.9038 -0.3869 +vn 0.0210 -0.9988 -0.0444 +vn 0.4148 -0.2427 -0.8770 +vn 0.2200 0.8575 -0.4652 +vn 0.4026 -0.3365 -0.8513 +vn 0.2549 0.8029 -0.5389 +vn 0.3866 -0.4271 -0.8174 +vn 0.2873 0.7405 -0.6075 +vn 0.3668 -0.5136 -0.7756 +vn 0.3170 0.6711 -0.6702 +vn 0.3436 -0.5952 -0.7264 +vn 0.3436 0.5952 -0.7264 +vn 0.3065 -0.8029 -0.5113 +vn 0.4841 0.3365 -0.8077 +vn 0.2645 -0.8575 -0.4413 +vn 0.4987 0.2427 -0.8321 +vn 0.0253 0.9988 -0.0421 +vn 0.2200 -0.9038 -0.3671 +vn 0.5086 0.1466 -0.8485 +vn 0.0755 0.9892 -0.1260 +vn 0.1734 -0.9414 -0.2893 +vn 0.5135 0.0490 -0.8567 +vn 0.1251 0.9700 -0.2086 +vn 0.1251 -0.9700 -0.2086 +vn 0.5135 -0.0490 -0.8567 +vn 0.1734 0.9414 -0.2893 +vn 0.0755 -0.9892 -0.1260 +vn 0.5086 -0.1466 -0.8485 +vn 0.2200 0.9038 -0.3671 +vn 0.0253 -0.9988 -0.0421 +vn 0.4987 -0.2427 -0.8321 +vn 0.2645 0.8575 -0.4414 +vn 0.4841 -0.3365 -0.8077 +vn 0.3065 0.8029 -0.5113 +vn 0.4648 -0.4271 -0.7755 +vn 0.3455 0.7405 -0.5764 +vn 0.4411 -0.5136 -0.7359 +vn 0.3811 0.6711 -0.6359 +vn 0.4131 -0.5952 -0.6892 +vn 0.4131 0.5952 -0.6892 +vn 0.3811 -0.6711 -0.6359 +vn 0.4411 0.5136 -0.7359 +vn 0.3455 -0.7405 -0.5764 +vn 0.4648 0.4271 -0.7755 +vn 0.0293 0.9988 -0.0395 +vn 0.2549 -0.9038 -0.3438 +vn 0.5893 0.1466 -0.7945 +vn 0.0875 0.9892 -0.1180 +vn 0.2009 -0.9414 -0.2709 +vn 0.5950 0.0490 -0.8022 +vn 0.1449 0.9700 -0.1954 +vn 0.1449 -0.9700 -0.1954 +vn 0.5950 -0.0490 -0.8022 +vn 0.2009 0.9414 -0.2709 +vn 0.0875 -0.9892 -0.1180 +vn 0.5893 -0.1466 -0.7945 +vn 0.2549 0.9038 -0.3438 +vn 0.0293 -0.9988 -0.0395 +vn 0.5779 -0.2427 -0.7792 +vn 0.3065 0.8575 -0.4133 +vn 0.5610 -0.3365 -0.7564 +vn 0.3551 0.8029 -0.4788 +vn 0.5386 -0.4271 -0.7263 +vn 0.4003 0.7405 -0.5398 +vn 0.5111 -0.5136 -0.6892 +vn 0.4416 0.6711 -0.5955 +vn 0.4787 -0.5952 -0.6454 +vn 0.4787 0.5952 -0.6454 +vn 0.4416 -0.6711 -0.5955 +vn 0.5111 0.5136 -0.6892 +vn 0.4003 -0.7405 -0.5398 +vn 0.5386 0.4271 -0.7262 +vn 0.3551 -0.8029 -0.4788 +vn 0.5610 0.3365 -0.7564 +vn 0.3065 -0.8575 -0.4133 +vn 0.5779 0.2427 -0.7792 +vn 0.1634 0.9700 -0.1802 +vn 0.1634 -0.9700 -0.1802 +vn 0.6708 -0.0490 -0.7401 +vn 0.2265 0.9414 -0.2499 +vn 0.0987 -0.9892 -0.1088 +vn 0.6643 -0.1466 -0.7330 +vn 0.2874 0.9038 -0.3171 +vn 0.0330 -0.9988 -0.0364 +vn 0.6515 -0.2427 -0.7188 +vn 0.3456 0.8575 -0.3813 +vn 0.6324 -0.3365 -0.6977 +vn 0.4004 0.8029 -0.4417 +vn 0.6072 -0.4271 -0.6700 +vn 0.4513 0.7405 -0.4979 +vn 0.5762 -0.5136 -0.6357 +vn 0.4979 0.6711 -0.5493 +vn 0.5396 -0.5952 -0.5954 +vn 0.5396 0.5952 -0.5954 +vn 0.4979 -0.6711 -0.5493 +vn 0.5762 0.5136 -0.6357 +vn 0.4513 -0.7405 -0.4979 +vn 0.6072 0.4271 -0.6700 +vn 0.4004 -0.8029 -0.4417 +vn 0.6324 0.3365 -0.6977 +vn 0.3456 -0.8575 -0.3813 +vn 0.6515 0.2427 -0.7188 +vn 0.0330 0.9988 -0.0364 +vn 0.2874 -0.9038 -0.3171 +vn 0.6643 0.1466 -0.7330 +vn 0.0987 0.9892 -0.1089 +vn 0.2265 -0.9414 -0.2499 +vn 0.6708 0.0490 -0.7401 +vn 0.3171 0.9038 -0.2874 +vn 0.0364 -0.9988 -0.0330 +vn 0.7188 -0.2427 -0.6515 +vn 0.3813 0.8575 -0.3456 +vn 0.6977 -0.3365 -0.6324 +vn 0.4417 0.8029 -0.4004 +vn 0.6700 -0.4271 -0.6072 +vn 0.4979 0.7405 -0.4513 +vn 0.6357 -0.5136 -0.5762 +vn 0.5493 0.6711 -0.4979 +vn 0.5954 -0.5952 -0.5396 +vn 0.5954 0.5952 -0.5396 +vn 0.5493 -0.6711 -0.4979 +vn 0.6357 0.5136 -0.5762 +vn 0.4979 -0.7405 -0.4513 +vn 0.6700 0.4271 -0.6072 +vn 0.4417 -0.8029 -0.4004 +vn 0.6977 0.3365 -0.6324 +vn 0.3813 -0.8575 -0.3456 +vn 0.7188 0.2427 -0.6515 +vn 0.0364 0.9988 -0.0330 +vn 0.3171 -0.9038 -0.2874 +vn 0.7330 0.1466 -0.6643 +vn 0.1088 0.9892 -0.0987 +vn 0.2499 -0.9414 -0.2265 +vn 0.7401 0.0490 -0.6708 +vn 0.1802 0.9700 -0.1634 +vn 0.1802 -0.9700 -0.1634 +vn 0.7401 -0.0490 -0.6708 +vn 0.2499 0.9414 -0.2265 +vn 0.1088 -0.9892 -0.0987 +vn 0.7329 -0.1466 -0.6643 +vn 0.4788 0.8029 -0.3551 +vn 0.7263 -0.4271 -0.5386 +vn 0.5398 0.7405 -0.4003 +vn 0.6892 -0.5136 -0.5111 +vn 0.5955 0.6711 -0.4416 +vn 0.6454 -0.5952 -0.4787 +vn 0.6454 0.5952 -0.4787 +vn 0.5955 -0.6711 -0.4416 +vn 0.6892 0.5136 -0.5111 +vn 0.5398 -0.7405 -0.4003 +vn 0.7263 0.4271 -0.5386 +vn 0.4788 -0.8029 -0.3551 +vn 0.7564 0.3365 -0.5610 +vn 0.4133 -0.8575 -0.3065 +vn 0.7792 0.2427 -0.5779 +vn 0.0395 0.9988 -0.0293 +vn 0.3438 -0.9038 -0.2549 +vn 0.7945 0.1466 -0.5893 +vn 0.1180 0.9892 -0.0875 +vn 0.2709 -0.9414 -0.2009 +vn 0.8022 0.0490 -0.5950 +vn 0.1954 0.9700 -0.1449 +vn 0.1954 -0.9700 -0.1449 +vn 0.8022 -0.0490 -0.5950 +vn 0.2709 0.9414 -0.2009 +vn 0.1180 -0.9892 -0.0875 +vn 0.7945 -0.1466 -0.5893 +vn 0.3438 0.9038 -0.2549 +vn 0.0395 -0.9988 -0.0293 +vn 0.7792 -0.2427 -0.5779 +vn 0.4133 0.8575 -0.3065 +vn 0.7564 -0.3365 -0.5610 +vn 0.6359 0.6711 -0.3811 +vn 0.6892 -0.5952 -0.4131 +vn 0.6892 0.5952 -0.4131 +vn 0.6359 -0.6711 -0.3811 +vn 0.7359 0.5136 -0.4411 +vn 0.5764 -0.7405 -0.3455 +vn 0.7755 0.4271 -0.4648 +vn 0.5113 -0.8029 -0.3065 +vn 0.8077 0.3365 -0.4841 +vn 0.4414 -0.8575 -0.2645 +vn 0.8321 0.2427 -0.4987 +vn 0.0421 0.9988 -0.0253 +vn 0.3671 -0.9038 -0.2200 +vn 0.8485 0.1466 -0.5086 +vn 0.1260 0.9892 -0.0755 +vn 0.2893 -0.9414 -0.1734 +vn 0.8567 0.0490 -0.5135 +vn 0.2086 0.9700 -0.1251 +vn 0.2086 -0.9700 -0.1251 +vn 0.8567 -0.0490 -0.5135 +vn 0.2893 0.9414 -0.1734 +vn 0.1260 -0.9892 -0.0755 +vn 0.8485 -0.1466 -0.5086 +vn 0.3671 0.9038 -0.2200 +vn 0.0421 -0.9988 -0.0253 +vn 0.8321 -0.2427 -0.4987 +vn 0.4414 0.8575 -0.2645 +vn 0.8077 -0.3365 -0.4841 +vn 0.5113 0.8029 -0.3065 +vn 0.7755 -0.4271 -0.4648 +vn 0.5764 0.7405 -0.3455 +vn 0.7359 -0.5136 -0.4411 +vn 0.7756 0.5136 -0.3668 +vn 0.6075 -0.7405 -0.2873 +vn 0.8174 0.4271 -0.3866 +vn 0.5389 -0.8029 -0.2549 +vn 0.8513 0.3365 -0.4026 +vn 0.4652 -0.8575 -0.2200 +vn 0.8770 0.2427 -0.4148 +vn 0.0444 0.9988 -0.0210 +vn 0.3869 -0.9038 -0.1830 +vn 0.8942 0.1466 -0.4229 +vn 0.1328 0.9892 -0.0628 +vn 0.3049 -0.9414 -0.1442 +vn 0.9029 0.0490 -0.4270 +vn 0.2199 0.9700 -0.1040 +vn 0.2199 -0.9700 -0.1040 +vn 0.9029 -0.0490 -0.4270 +vn 0.3049 0.9414 -0.1442 +vn 0.1328 -0.9892 -0.0628 +vn 0.8942 -0.1466 -0.4229 +vn 0.3869 0.9038 -0.1830 +vn 0.0444 -0.9988 -0.0210 +vn 0.8770 -0.2427 -0.4148 +vn 0.4652 0.8575 -0.2200 +vn 0.8513 -0.3365 -0.4026 +vn 0.5389 0.8029 -0.2549 +vn 0.8174 -0.4271 -0.3866 +vn 0.6075 0.7405 -0.2873 +vn 0.7756 -0.5136 -0.3668 +vn 0.6702 0.6711 -0.3170 +vn 0.7264 -0.5952 -0.3436 +vn 0.7264 0.5952 -0.3436 +vn 0.6702 -0.6711 -0.3170 +vn 0.8866 0.3365 -0.3172 +vn 0.4845 -0.8575 -0.1733 +vn 0.9134 0.2427 -0.3268 +vn 0.0463 0.9988 -0.0165 +vn 0.4030 -0.9038 -0.1442 +vn 0.9314 0.1466 -0.3333 +vn 0.1383 0.9892 -0.0495 +vn 0.3175 -0.9414 -0.1136 +vn 0.9404 0.0490 -0.3365 +vn 0.2290 0.9700 -0.0819 +vn 0.2290 -0.9700 -0.0819 +vn 0.9404 -0.0490 -0.3365 +vn 0.3175 0.9414 -0.1136 +vn 0.1383 -0.9892 -0.0495 +vn 0.9314 -0.1466 -0.3333 +vn 0.4030 0.9038 -0.1442 +vn 0.0463 -0.9988 -0.0166 +vn 0.9134 -0.2427 -0.3268 +vn 0.4845 0.8575 -0.1734 +vn 0.8866 -0.3365 -0.3172 +vn 0.5613 0.8029 -0.2008 +vn 0.8513 -0.4271 -0.3046 +vn 0.6327 0.7405 -0.2264 +vn 0.8078 -0.5136 -0.2891 +vn 0.6980 0.6711 -0.2498 +vn 0.7566 -0.5952 -0.2707 +vn 0.7566 0.5952 -0.2707 +vn 0.6980 -0.6711 -0.2498 +vn 0.8078 0.5136 -0.2891 +vn 0.6327 -0.7405 -0.2264 +vn 0.8513 0.4271 -0.3046 +vn 0.5613 -0.8029 -0.2008 +vn 0.9596 0.1466 -0.2404 +vn 0.1425 0.9892 -0.0357 +vn 0.3271 -0.9414 -0.0819 +vn 0.9689 0.0490 -0.2427 +vn 0.2360 0.9700 -0.0591 +vn 0.2360 -0.9700 -0.0591 +vn 0.9689 -0.0490 -0.2427 +vn 0.3271 0.9414 -0.0819 +vn 0.1425 -0.9892 -0.0357 +vn 0.9596 -0.1466 -0.2404 +vn 0.4151 0.9038 -0.1040 +vn 0.0477 -0.9988 -0.0119 +vn 0.9410 -0.2427 -0.2357 +vn 0.4991 0.8575 -0.1250 +vn 0.9135 -0.3365 -0.2288 +vn 0.5783 0.8029 -0.1449 +vn 0.8771 -0.4271 -0.2197 +vn 0.6519 0.7405 -0.1633 +vn 0.8323 -0.5136 -0.2085 +vn 0.7191 0.6711 -0.1801 +vn 0.7795 -0.5952 -0.1952 +vn 0.7795 0.5952 -0.1952 +vn 0.7191 -0.6711 -0.1801 +vn 0.8323 0.5136 -0.2085 +vn 0.6519 -0.7405 -0.1633 +vn 0.8771 0.4271 -0.2197 +vn 0.5783 -0.8029 -0.1449 +vn 0.9135 0.3365 -0.2288 +vn 0.4991 -0.8575 -0.1250 +vn 0.9410 0.2427 -0.2357 +vn 0.0477 0.9988 -0.0119 +vn 0.4152 -0.9038 -0.1040 +vn 0.9880 -0.0490 -0.1466 +vn 0.3336 0.9414 -0.0495 +vn 0.1453 -0.9892 -0.0216 +vn 0.9785 -0.1466 -0.1451 +vn 0.4233 0.9038 -0.0628 +vn 0.0486 -0.9988 -0.0072 +vn 0.9596 -0.2427 -0.1423 +vn 0.5090 0.8575 -0.0755 +vn 0.9315 -0.3365 -0.1382 +vn 0.5897 0.8029 -0.0875 +vn 0.8944 -0.4271 -0.1327 +vn 0.6647 0.7405 -0.0986 +vn 0.8487 -0.5136 -0.1259 +vn 0.7333 0.6711 -0.1088 +vn 0.7949 -0.5952 -0.1179 +vn 0.7949 0.5952 -0.1179 +vn 0.7333 -0.6711 -0.1088 +vn 0.8487 0.5136 -0.1259 +vn 0.6647 -0.7405 -0.0986 +vn 0.8944 0.4271 -0.1327 +vn 0.5897 -0.8029 -0.0875 +vn 0.9315 0.3365 -0.1382 +vn 0.5090 -0.8575 -0.0755 +vn 0.9596 0.2427 -0.1423 +vn 0.0486 0.9988 -0.0072 +vn 0.4233 -0.9038 -0.0628 +vn 0.9785 0.1466 -0.1451 +vn 0.1453 0.9892 -0.0216 +vn 0.3336 -0.9414 -0.0495 +vn 0.9880 0.0490 -0.1466 +vn 0.2406 0.9700 -0.0357 +vn 0.2406 -0.9700 -0.0357 +vn 0.9689 -0.2427 -0.0476 +vn 0.5139 0.8575 -0.0252 +vn 0.9405 -0.3365 -0.0462 +vn 0.5954 0.8029 -0.0293 +vn 0.9031 -0.4271 -0.0444 +vn 0.6712 0.7405 -0.0330 +vn 0.8570 -0.5136 -0.0421 +vn 0.7405 0.6711 -0.0364 +vn 0.8026 -0.5952 -0.0394 +vn 0.8026 0.5952 -0.0394 +vn 0.7405 -0.6711 -0.0364 +vn 0.8570 0.5136 -0.0421 +vn 0.6712 -0.7405 -0.0330 +vn 0.9031 0.4271 -0.0444 +vn 0.5954 -0.8029 -0.0292 +vn 0.9405 0.3365 -0.0462 +vn 0.5139 -0.8575 -0.0252 +vn 0.9689 0.2427 -0.0476 +vn 0.0491 0.9988 -0.0024 +vn 0.4275 -0.9038 -0.0210 +vn 0.9880 0.1466 -0.0485 +vn 0.1467 0.9892 -0.0072 +vn 0.3368 -0.9414 -0.0165 +vn 0.9976 0.0490 -0.0490 +vn 0.2430 0.9700 -0.0119 +vn 0.2430 -0.9700 -0.0119 +vn 0.9976 -0.0490 -0.0490 +vn 0.3368 0.9414 -0.0166 +vn 0.1467 -0.9892 -0.0072 +vn 0.9880 -0.1466 -0.0485 +vn 0.4275 0.9038 -0.0210 +vn 0.0491 -0.9988 -0.0024 +vn 0.9031 -0.4271 0.0444 +vn 0.6712 0.7405 0.0330 +vn 0.8570 -0.5136 0.0421 +vn 0.7405 0.6711 0.0364 +vn 0.8026 -0.5952 0.0394 +vn 0.8026 0.5952 0.0394 +vn 0.7405 -0.6711 0.0364 +vn 0.8570 0.5136 0.0421 +vn 0.6712 -0.7405 0.0330 +vn 0.9031 0.4271 0.0444 +vn 0.5954 -0.8029 0.0293 +vn 0.9405 0.3365 0.0462 +vn 0.5139 -0.8575 0.0252 +vn 0.9689 0.2427 0.0476 +vn 0.0491 0.9988 0.0024 +vn 0.4275 -0.9038 0.0210 +vn 0.9880 0.1466 0.0485 +vn 0.1467 0.9892 0.0072 +vn 0.3368 -0.9414 0.0165 +vn 0.9976 0.0490 0.0490 +vn 0.2430 0.9700 0.0119 +vn 0.2430 -0.9700 0.0119 +vn 0.9976 -0.0490 0.0490 +vn 0.3368 0.9414 0.0165 +vn 0.1467 -0.9892 0.0072 +vn 0.9880 -0.1466 0.0485 +vn 0.4275 0.9038 0.0210 +vn 0.0491 -0.9988 0.0024 +vn 0.9689 -0.2427 0.0476 +vn 0.5139 0.8575 0.0252 +vn 0.9405 -0.3365 0.0462 +vn 0.5954 0.8029 0.0293 +vn 0.7949 -0.5952 0.1179 +vn 0.7949 0.5952 0.1179 +vn 0.7333 -0.6711 0.1088 +vn 0.8487 0.5136 0.1259 +vn 0.6647 -0.7405 0.0986 +vn 0.8944 0.4271 0.1327 +vn 0.5897 -0.8029 0.0875 +vn 0.9315 0.3365 0.1382 +vn 0.5090 -0.8575 0.0755 +vn 0.9596 0.2427 0.1423 +vn 0.0486 0.9988 0.0072 +vn 0.4233 -0.9038 0.0628 +vn 0.9785 0.1466 0.1451 +vn 0.1453 0.9892 0.0216 +vn 0.3336 -0.9414 0.0495 +vn 0.9880 0.0490 0.1466 +vn 0.2406 0.9700 0.0357 +vn 0.2406 -0.9700 0.0357 +vn 0.9880 -0.0490 0.1466 +vn 0.3336 0.9414 0.0495 +vn 0.1453 -0.9892 0.0216 +vn 0.9785 -0.1466 0.1451 +vn 0.4233 0.9038 0.0628 +vn 0.0486 -0.9988 0.0072 +vn 0.9596 -0.2427 0.1423 +vn 0.5090 0.8575 0.0755 +vn 0.9315 -0.3365 0.1382 +vn 0.5897 0.8029 0.0875 +vn 0.8944 -0.4271 0.1327 +vn 0.6647 0.7405 0.0986 +vn 0.8487 -0.5136 0.1259 +vn 0.7333 0.6711 0.1088 +vn 0.6519 -0.7405 0.1633 +vn 0.8771 0.4271 0.2197 +vn 0.5783 -0.8029 0.1449 +vn 0.9135 0.3365 0.2288 +vn 0.4991 -0.8575 0.1250 +vn 0.9410 0.2427 0.2357 +vn 0.0477 0.9988 0.0119 +vn 0.4151 -0.9038 0.1040 +vn 0.9596 0.1466 0.2404 +vn 0.1425 0.9892 0.0357 +vn 0.3271 -0.9414 0.0819 +vn 0.9689 0.0490 0.2427 +vn 0.2360 0.9700 0.0591 +vn 0.2360 -0.9700 0.0591 +vn 0.9689 -0.0490 0.2427 +vn 0.3271 0.9414 0.0819 +vn 0.1425 -0.9892 0.0357 +vn 0.9596 -0.1466 0.2404 +vn 0.4152 0.9038 0.1040 +vn 0.0477 -0.9988 0.0119 +vn 0.9410 -0.2427 0.2357 +vn 0.4991 0.8575 0.1250 +vn 0.9135 -0.3365 0.2288 +vn 0.5783 0.8029 0.1449 +vn 0.8771 -0.4271 0.2197 +vn 0.6519 0.7405 0.1633 +vn 0.8323 -0.5136 0.2085 +vn 0.7191 0.6711 0.1801 +vn 0.7795 -0.5952 0.1952 +vn 0.7795 0.5952 0.1952 +vn 0.7191 -0.6711 0.1801 +vn 0.8323 0.5136 0.2085 +vn 0.4845 -0.8575 0.1733 +vn 0.9134 0.2427 0.3268 +vn 0.0463 0.9988 0.0165 +vn 0.4030 -0.9038 0.1442 +vn 0.9314 0.1466 0.3333 +vn 0.1383 0.9892 0.0495 +vn 0.3175 -0.9414 0.1136 +vn 0.9404 0.0490 0.3365 +vn 0.2290 0.9700 0.0820 +vn 0.2290 -0.9700 0.0820 +vn 0.9404 -0.0490 0.3365 +vn 0.3175 0.9414 0.1136 +vn 0.1383 -0.9892 0.0495 +vn 0.9314 -0.1466 0.3333 +vn 0.4030 0.9038 0.1442 +vn 0.0463 -0.9988 0.0166 +vn 0.9134 -0.2427 0.3268 +vn 0.4845 0.8575 0.1734 +vn 0.8866 -0.3365 0.3172 +vn 0.5613 0.8029 0.2008 +vn 0.8513 -0.4271 0.3046 +vn 0.6327 0.7405 0.2264 +vn 0.8078 -0.5136 0.2891 +vn 0.6980 0.6711 0.2498 +vn 0.7566 -0.5952 0.2707 +vn 0.7566 0.5952 0.2707 +vn 0.6980 -0.6711 0.2498 +vn 0.8078 0.5136 0.2891 +vn 0.6327 -0.7405 0.2264 +vn 0.8513 0.4271 0.3046 +vn 0.5613 -0.8029 0.2008 +vn 0.8866 0.3365 0.3172 +vn 0.3049 -0.9414 0.1442 +vn 0.9029 0.0490 0.4270 +vn 0.2199 0.9700 0.1040 +vn 0.2199 -0.9700 0.1040 +vn 0.9029 -0.0490 0.4270 +vn 0.3049 0.9414 0.1442 +vn 0.1328 -0.9892 0.0628 +vn 0.8942 -0.1466 0.4229 +vn 0.3869 0.9038 0.1830 +vn 0.0444 -0.9988 0.0210 +vn 0.8770 -0.2427 0.4148 +vn 0.4652 0.8575 0.2200 +vn 0.8513 -0.3365 0.4026 +vn 0.5389 0.8029 0.2549 +vn 0.8174 -0.4271 0.3866 +vn 0.6075 0.7405 0.2873 +vn 0.7756 -0.5136 0.3668 +vn 0.6702 0.6711 0.3170 +vn 0.7264 -0.5952 0.3436 +vn 0.7264 0.5952 0.3436 +vn 0.6702 -0.6711 0.3170 +vn 0.7756 0.5136 0.3668 +vn 0.6075 -0.7405 0.2873 +vn 0.8174 0.4271 0.3866 +vn 0.5389 -0.8029 0.2549 +vn 0.8513 0.3365 0.4026 +vn 0.4652 -0.8575 0.2200 +vn 0.8770 0.2427 0.4148 +vn 0.0444 0.9988 0.0210 +vn 0.3869 -0.9038 0.1830 +vn 0.8942 0.1466 0.4229 +vn 0.1328 0.9892 0.0628 +vn 0.1260 -0.9892 0.0755 +vn 0.8485 -0.1466 0.5086 +vn 0.3671 0.9038 0.2200 +vn 0.0421 -0.9988 0.0253 +vn 0.8321 -0.2427 0.4987 +vn 0.4414 0.8575 0.2645 +vn 0.8077 -0.3365 0.4841 +vn 0.5113 0.8029 0.3065 +vn 0.7755 -0.4271 0.4648 +vn 0.5764 0.7405 0.3455 +vn 0.7359 -0.5136 0.4411 +vn 0.6359 0.6711 0.3811 +vn 0.6892 -0.5952 0.4131 +vn 0.6892 0.5952 0.4131 +vn 0.6359 -0.6711 0.3811 +vn 0.7359 0.5136 0.4411 +vn 0.5764 -0.7405 0.3455 +vn 0.7755 0.4271 0.4648 +vn 0.5113 -0.8029 0.3065 +vn 0.8077 0.3365 0.4841 +vn 0.4414 -0.8575 0.2645 +vn 0.8321 0.2427 0.4987 +vn 0.0421 0.9988 0.0253 +vn 0.3671 -0.9038 0.2200 +vn 0.8485 0.1466 0.5086 +vn 0.1260 0.9892 0.0755 +vn 0.2893 -0.9414 0.1734 +vn 0.8567 0.0490 0.5135 +vn 0.2086 0.9700 0.1251 +vn 0.2086 -0.9700 0.1251 +vn 0.8567 -0.0490 0.5135 +vn 0.2893 0.9414 0.1734 +vn 0.7564 -0.3365 0.5610 +vn 0.4788 0.8029 0.3551 +vn 0.7263 -0.4271 0.5386 +vn 0.5398 0.7405 0.4003 +vn 0.6892 -0.5136 0.5111 +vn 0.5955 0.6711 0.4416 +vn 0.6454 -0.5952 0.4787 +vn 0.6454 0.5952 0.4787 +vn 0.5955 -0.6711 0.4416 +vn 0.6892 0.5136 0.5111 +vn 0.5398 -0.7405 0.4003 +vn 0.7263 0.4271 0.5386 +vn 0.4788 -0.8029 0.3551 +vn 0.7564 0.3365 0.5610 +vn 0.4133 -0.8575 0.3065 +vn 0.7792 0.2427 0.5779 +vn 0.0395 0.9988 0.0293 +vn 0.3438 -0.9038 0.2549 +vn 0.7945 0.1466 0.5893 +vn 0.1180 0.9892 0.0875 +vn 0.2709 -0.9414 0.2009 +vn 0.8022 0.0490 0.5950 +vn 0.1954 0.9700 0.1449 +vn 0.1954 -0.9700 0.1449 +vn 0.8022 -0.0490 0.5950 +vn 0.2709 0.9414 0.2009 +vn 0.1180 -0.9892 0.0875 +vn 0.7945 -0.1466 0.5893 +vn 0.3438 0.9038 0.2549 +vn 0.0395 -0.9988 0.0293 +vn 0.7792 -0.2427 0.5779 +vn 0.4133 0.8575 0.3065 +vn 0.6357 -0.5136 0.5762 +vn 0.5493 0.6711 0.4979 +vn 0.5954 -0.5952 0.5396 +vn 0.5954 0.5952 0.5396 +vn 0.5493 -0.6711 0.4979 +vn 0.6357 0.5136 0.5762 +vn 0.4979 -0.7405 0.4513 +vn 0.6700 0.4271 0.6072 +vn 0.4417 -0.8029 0.4004 +vn 0.6977 0.3365 0.6324 +vn 0.3813 -0.8575 0.3456 +vn 0.7188 0.2427 0.6515 +vn 0.0364 0.9988 0.0330 +vn 0.3171 -0.9038 0.2874 +vn 0.7330 0.1466 0.6643 +vn 0.1088 0.9892 0.0987 +vn 0.2499 -0.9414 0.2265 +vn 0.7401 0.0490 0.6708 +vn 0.1802 0.9700 0.1634 +vn 0.1802 -0.9700 0.1634 +vn 0.7401 -0.0490 0.6708 +vn 0.2499 0.9414 0.2265 +vn 0.1088 -0.9892 0.0987 +vn 0.7330 -0.1466 0.6643 +vn 0.3171 0.9038 0.2874 +vn 0.0364 -0.9988 0.0330 +vn 0.7188 -0.2427 0.6515 +vn 0.3813 0.8575 0.3456 +vn 0.6977 -0.3365 0.6324 +vn 0.4417 0.8029 0.4004 +vn 0.6700 -0.4271 0.6072 +vn 0.4979 0.7405 0.4513 +vn 0.4979 -0.6711 0.5493 +vn 0.5762 0.5136 0.6357 +vn 0.4513 -0.7405 0.4979 +vn 0.6072 0.4271 0.6700 +vn 0.4004 -0.8029 0.4417 +vn 0.6324 0.3365 0.6977 +vn 0.3456 -0.8575 0.3813 +vn 0.6515 0.2427 0.7188 +vn 0.0330 0.9988 0.0364 +vn 0.2874 -0.9038 0.3171 +vn 0.6643 0.1466 0.7330 +vn 0.0987 0.9892 0.1089 +vn 0.2265 -0.9414 0.2499 +vn 0.6708 0.0490 0.7401 +vn 0.1634 0.9700 0.1802 +vn 0.1634 -0.9700 0.1802 +vn 0.6708 -0.0490 0.7401 +vn 0.2265 0.9414 0.2499 +vn 0.0987 -0.9891 0.1089 +vn 0.6643 -0.1466 0.7330 +vn 0.2874 0.9038 0.3171 +vn 0.0330 -0.9988 0.0364 +vn 0.6515 -0.2427 0.7188 +vn 0.3456 0.8575 0.3813 +vn 0.6324 -0.3365 0.6977 +vn 0.4004 0.8029 0.4417 +vn 0.6072 -0.4271 0.6700 +vn 0.4513 0.7405 0.4979 +vn 0.5762 -0.5136 0.6357 +vn 0.4979 0.6711 0.5493 +vn 0.5396 -0.5952 0.5954 +vn 0.5396 0.5952 0.5954 +vn 0.3551 -0.8029 0.4788 +vn 0.5610 0.3365 0.7564 +vn 0.3065 -0.8575 0.4133 +vn 0.5779 0.2427 0.7792 +vn 0.0293 0.9988 0.0395 +vn 0.2549 -0.9038 0.3438 +vn 0.5893 0.1466 0.7945 +vn 0.0875 0.9892 0.1180 +vn 0.2009 -0.9414 0.2709 +vn 0.5950 0.0490 0.8022 +vn 0.1449 0.9700 0.1954 +vn 0.1449 -0.9700 0.1954 +vn 0.5950 -0.0490 0.8022 +vn 0.2009 0.9414 0.2709 +vn 0.0875 -0.9892 0.1180 +vn 0.5893 -0.1466 0.7945 +vn 0.2549 0.9038 0.3438 +vn 0.0293 -0.9988 0.0395 +vn 0.5779 -0.2427 0.7792 +vn 0.3065 0.8575 0.4133 +vn 0.5610 -0.3365 0.7564 +vn 0.3551 0.8029 0.4788 +vn 0.5386 -0.4271 0.7263 +vn 0.4003 0.7405 0.5398 +vn 0.5111 -0.5136 0.6892 +vn 0.4416 0.6711 0.5955 +vn 0.4787 -0.5952 0.6454 +vn 0.4787 0.5952 0.6454 +vn 0.4416 -0.6711 0.5955 +vn 0.5111 0.5136 0.6892 +vn 0.4003 -0.7405 0.5398 +vn 0.5386 0.4271 0.7263 +vn 0.3455 -0.7405 0.5764 +vn 0.4648 0.4271 0.7755 +vn 0.3065 -0.8029 0.5113 +vn 0.4841 0.3365 0.8077 +vn 0.2645 -0.8575 0.4414 +vn 0.4987 0.2427 0.8321 +vn 0.0253 0.9988 0.0421 +vn 0.2200 -0.9038 0.3671 +vn 0.5086 0.1466 0.8485 +vn 0.0755 0.9892 0.1260 +vn 0.1734 -0.9414 0.2893 +vn 0.5135 0.0490 0.8567 +vn 0.1251 0.9700 0.2086 +vn 0.1251 -0.9700 0.2086 +vn 0.5135 -0.0490 0.8567 +vn 0.1734 0.9414 0.2893 +vn 0.0755 -0.9892 0.1260 +vn 0.5086 -0.1466 0.8485 +vn 0.2200 0.9038 0.3671 +vn 0.0253 -0.9988 0.0421 +vn 0.4987 -0.2427 0.8321 +vn 0.2645 0.8575 0.4414 +vn 0.4841 -0.3365 0.8077 +vn 0.3065 0.8029 0.5113 +vn 0.4648 -0.4271 0.7755 +vn 0.3455 0.7405 0.5764 +vn 0.4411 -0.5136 0.7359 +vn 0.3811 0.6711 0.6359 +vn 0.4131 -0.5952 0.6892 +vn 0.4131 0.5952 0.6892 +vn 0.3811 -0.6711 0.6359 +vn 0.4411 0.5136 0.7359 +vn 0.2200 -0.8575 0.4652 +vn 0.4148 0.2427 0.8770 +vn 0.0210 0.9988 0.0444 +vn 0.1830 -0.9038 0.3869 +vn 0.4229 0.1466 0.8942 +vn 0.0628 0.9892 0.1328 +vn 0.1442 -0.9414 0.3049 +vn 0.4270 0.0490 0.9029 +vn 0.1040 0.9700 0.2199 +vn 0.1040 -0.9700 0.2199 +vn 0.4270 -0.0490 0.9029 +vn 0.1442 0.9414 0.3049 +vn 0.0628 -0.9892 0.1328 +vn 0.4229 -0.1466 0.8942 +vn 0.1830 0.9038 0.3869 +vn 0.0210 -0.9988 0.0444 +vn 0.4148 -0.2427 0.8770 +vn 0.2200 0.8575 0.4652 +vn 0.4026 -0.3365 0.8513 +vn 0.2549 0.8029 0.5389 +vn 0.3866 -0.4271 0.8174 +vn 0.2873 0.7405 0.6075 +vn 0.3668 -0.5136 0.7756 +vn 0.3170 0.6711 0.6702 +vn 0.3436 -0.5952 0.7264 +vn 0.3436 0.5952 0.7264 +vn 0.3170 -0.6711 0.6702 +vn 0.3668 0.5136 0.7756 +vn 0.2873 -0.7405 0.6075 +vn 0.3866 0.4271 0.8174 +vn 0.2549 -0.8029 0.5389 +vn 0.4026 0.3365 0.8513 +vn 0.0495 0.9892 0.1383 +vn 0.1136 -0.9414 0.3175 +vn 0.3365 0.0490 0.9404 +vn 0.0819 0.9700 0.2290 +vn 0.0820 -0.9700 0.2290 +vn 0.3365 -0.0490 0.9404 +vn 0.1136 0.9414 0.3175 +vn 0.0495 -0.9892 0.1383 +vn 0.3333 -0.1466 0.9314 +vn 0.1442 0.9038 0.4030 +vn 0.0166 -0.9988 0.0463 +vn 0.3268 -0.2427 0.9134 +vn 0.1733 0.8575 0.4845 +vn 0.3172 -0.3365 0.8866 +vn 0.2008 0.8029 0.5613 +vn 0.3046 -0.4271 0.8513 +vn 0.2264 0.7405 0.6327 +vn 0.2890 -0.5136 0.8078 +vn 0.2498 0.6711 0.6980 +vn 0.2707 -0.5952 0.7566 +vn 0.2707 0.5952 0.7566 +vn 0.2498 -0.6711 0.6980 +vn 0.2891 0.5136 0.8078 +vn 0.2264 -0.7405 0.6327 +vn 0.3046 0.4271 0.8513 +vn 0.2008 -0.8029 0.5613 +vn 0.3172 0.3365 0.8866 +vn 0.1733 -0.8575 0.4845 +vn 0.3268 0.2427 0.9134 +vn 0.0166 0.9988 0.0463 +vn 0.1442 -0.9038 0.4030 +vn 0.3333 0.1466 0.9314 +vn 0.0819 0.9414 0.3271 +vn 0.0357 -0.9892 0.1425 +vn 0.2404 -0.1466 0.9596 +vn 0.1040 0.9038 0.4152 +vn 0.0119 -0.9988 0.0477 +vn 0.2357 -0.2427 0.9410 +vn 0.1250 0.8575 0.4991 +vn 0.2288 -0.3365 0.9135 +vn 0.1449 0.8029 0.5783 +vn 0.2197 -0.4271 0.8771 +vn 0.1633 0.7405 0.6519 +vn 0.2085 -0.5136 0.8323 +vn 0.1801 0.6711 0.7191 +vn 0.1952 -0.5952 0.7795 +vn 0.1952 0.5952 0.7795 +vn 0.1801 -0.6711 0.7191 +vn 0.2085 0.5136 0.8323 +vn 0.1633 -0.7405 0.6519 +vn 0.2197 0.4271 0.8771 +vn 0.1449 -0.8029 0.5783 +vn 0.2288 0.3365 0.9135 +vn 0.1250 -0.8575 0.4991 +vn 0.2357 0.2427 0.9410 +vn 0.0119 0.9988 0.0477 +vn 0.1040 -0.9038 0.4151 +vn 0.2404 0.1466 0.9596 +vn 0.0357 0.9892 0.1425 +vn 0.0819 -0.9414 0.3271 +vn 0.2427 0.0490 0.9689 +vn 0.0591 0.9700 0.2360 +vn 0.0591 -0.9700 0.2360 +vn 0.2427 -0.0490 0.9689 +vn 0.0755 0.8575 0.5090 +vn 0.1382 -0.3365 0.9315 +vn 0.0875 0.8029 0.5897 +vn 0.1327 -0.4271 0.8944 +vn 0.0986 0.7405 0.6647 +vn 0.1259 -0.5136 0.8487 +vn 0.1088 0.6711 0.7333 +vn 0.1179 -0.5952 0.7949 +vn 0.1179 0.5952 0.7949 +vn 0.1088 -0.6711 0.7333 +vn 0.1259 0.5136 0.8487 +vn 0.0986 -0.7405 0.6647 +vn 0.1327 0.4271 0.8944 +vn 0.0875 -0.8029 0.5897 +vn 0.1382 0.3365 0.9315 +vn 0.0755 -0.8575 0.5090 +vn 0.1423 0.2427 0.9596 +vn 0.0072 0.9988 0.0486 +vn 0.0628 -0.9038 0.4233 +vn 0.1451 0.1466 0.9785 +vn 0.0216 0.9892 0.1453 +vn 0.0495 -0.9414 0.3336 +vn 0.1466 0.0490 0.9880 +vn 0.0357 0.9700 0.2406 +vn 0.0357 -0.9700 0.2406 +vn 0.1466 -0.0490 0.9880 +vn 0.0495 0.9414 0.3336 +vn 0.0216 -0.9892 0.1453 +vn 0.1451 -0.1466 0.9785 +vn 0.0628 0.9038 0.4233 +vn 0.0072 -0.9988 0.0486 +vn 0.1423 -0.2427 0.9596 +vn 0.0330 0.7405 0.6712 +vn 0.0421 -0.5136 0.8570 +vn 0.0364 0.6711 0.7405 +vn 0.0394 -0.5952 0.8026 +vn 0.0394 0.5952 0.8026 +vn 0.0364 -0.6711 0.7405 +vn 0.0421 0.5136 0.8570 +vn 0.0330 -0.7405 0.6712 +vn 0.0444 0.4271 0.9031 +vn 0.0293 -0.8029 0.5954 +vn 0.0462 0.3365 0.9405 +vn 0.0252 -0.8575 0.5139 +vn 0.0476 0.2427 0.9689 +vn 0.0024 0.9988 0.0491 +vn 0.0210 -0.9038 0.4275 +vn 0.0485 0.1466 0.9880 +vn 0.0072 0.9892 0.1467 +vn 0.0165 -0.9414 0.3368 +vn 0.0490 0.0490 0.9976 +vn 0.0119 0.9700 0.2430 +vn 0.0119 -0.9700 0.2430 +vn 0.0490 -0.0490 0.9976 +vn 0.0165 0.9414 0.3368 +vn 0.0072 -0.9892 0.1467 +vn 0.0485 -0.1466 0.9880 +vn 0.0210 0.9038 0.4275 +vn 0.0024 -0.9988 0.0491 +vn 0.0476 -0.2427 0.9689 +vn 0.0252 0.8575 0.5139 +vn 0.0462 -0.3365 0.9405 +vn 0.0293 0.8029 0.5954 +vn 0.0444 -0.4271 0.9031 +vn -0.0394 0.5952 0.8026 +vn -0.0364 -0.6711 0.7405 +vn -0.0421 0.5136 0.8570 +vn -0.0330 -0.7405 0.6712 +vn -0.0444 0.4271 0.9031 +vn -0.0293 -0.8029 0.5954 +vn -0.0462 0.3365 0.9405 +vn -0.0252 -0.8575 0.5139 +vn -0.0476 0.2427 0.9689 +vn -0.0024 0.9988 0.0491 +vn -0.0210 -0.9038 0.4275 +vn -0.0485 0.1466 0.9880 +vn -0.0072 0.9892 0.1467 +vn -0.0165 -0.9414 0.3368 +vn -0.0490 0.0490 0.9976 +vn -0.0119 0.9700 0.2430 +vn -0.0119 -0.9700 0.2430 +vn -0.0490 -0.0490 0.9976 +vn -0.0165 0.9414 0.3368 +vn -0.0072 -0.9892 0.1467 +vn -0.0485 -0.1466 0.9880 +vn -0.0210 0.9038 0.4275 +vn -0.0024 -0.9988 0.0491 +vn -0.0476 -0.2427 0.9689 +vn -0.0252 0.8575 0.5139 +vn -0.0462 -0.3365 0.9405 +vn -0.0293 0.8029 0.5954 +vn -0.0444 -0.4271 0.9031 +vn -0.0330 0.7405 0.6712 +vn -0.0421 -0.5136 0.8570 +vn -0.0364 0.6711 0.7405 +vn -0.0394 -0.5952 0.8026 +vn -0.1327 0.4271 0.8944 +vn -0.0875 -0.8029 0.5897 +vn -0.1382 0.3365 0.9315 +vn -0.0755 -0.8575 0.5090 +vn -0.1423 0.2427 0.9596 +vn -0.0072 0.9988 0.0486 +vn -0.0628 -0.9038 0.4233 +vn -0.1451 0.1466 0.9785 +vn -0.0216 0.9892 0.1453 +vn -0.0495 -0.9414 0.3336 +vn -0.1466 0.0490 0.9880 +vn -0.0357 0.9700 0.2406 +vn -0.0357 -0.9700 0.2406 +vn -0.1466 -0.0490 0.9880 +vn -0.0495 0.9414 0.3336 +vn -0.0216 -0.9892 0.1453 +vn -0.1451 -0.1466 0.9785 +vn -0.0628 0.9038 0.4233 +vn -0.0072 -0.9988 0.0486 +vn -0.1423 -0.2427 0.9596 +vn -0.0755 0.8575 0.5090 +vn -0.1382 -0.3365 0.9315 +vn -0.0875 0.8029 0.5897 +vn -0.1327 -0.4271 0.8944 +vn -0.0986 0.7405 0.6647 +vn -0.1259 -0.5136 0.8487 +vn -0.1088 0.6711 0.7333 +vn -0.1179 -0.5952 0.7949 +vn -0.1179 0.5952 0.7949 +vn -0.1088 -0.6711 0.7333 +vn -0.1259 0.5136 0.8487 +vn -0.0986 -0.7405 0.6647 +vn -0.2357 0.2427 0.9410 +vn -0.0119 0.9988 0.0477 +vn -0.1040 -0.9038 0.4151 +vn -0.2404 0.1466 0.9596 +vn -0.0357 0.9892 0.1425 +vn -0.0819 -0.9414 0.3271 +vn -0.2427 0.0490 0.9689 +vn -0.0591 0.9700 0.2360 +vn -0.0591 -0.9700 0.2360 +vn -0.2427 -0.0490 0.9689 +vn -0.0819 0.9414 0.3271 +vn -0.0357 -0.9892 0.1425 +vn -0.2404 -0.1466 0.9596 +vn -0.1040 0.9038 0.4152 +vn -0.0119 -0.9988 0.0477 +vn -0.2357 -0.2427 0.9410 +vn -0.1250 0.8575 0.4991 +vn -0.2288 -0.3365 0.9135 +vn -0.1449 0.8029 0.5783 +vn -0.2197 -0.4271 0.8771 +vn -0.1633 0.7405 0.6519 +vn -0.2085 -0.5136 0.8323 +vn -0.1801 0.6711 0.7191 +vn -0.1952 -0.5952 0.7795 +vn -0.1952 0.5952 0.7795 +vn -0.1801 -0.6711 0.7191 +vn -0.2085 0.5136 0.8323 +vn -0.1633 -0.7405 0.6519 +vn -0.2197 0.4271 0.8771 +vn -0.1449 -0.8029 0.5783 +vn -0.2288 0.3365 0.9135 +vn -0.1250 -0.8575 0.4991 +vn -0.3365 0.0490 0.9404 +vn -0.0819 0.9700 0.2290 +vn -0.0819 -0.9700 0.2290 +vn -0.3365 -0.0490 0.9404 +vn -0.1136 0.9414 0.3175 +vn -0.0495 -0.9892 0.1383 +vn -0.3333 -0.1466 0.9314 +vn -0.1442 0.9038 0.4030 +vn -0.0166 -0.9988 0.0463 +vn -0.3268 -0.2427 0.9134 +vn -0.1733 0.8575 0.4845 +vn -0.3172 -0.3365 0.8866 +vn -0.2008 0.8029 0.5613 +vn -0.3046 -0.4271 0.8513 +vn -0.2264 0.7405 0.6327 +vn -0.2891 -0.5136 0.8078 +vn -0.2498 0.6711 0.6980 +vn -0.2707 -0.5952 0.7566 +vn -0.2707 0.5952 0.7566 +vn -0.2498 -0.6711 0.6980 +vn -0.2891 0.5136 0.8078 +vn -0.2264 -0.7405 0.6327 +vn -0.3046 0.4271 0.8513 +vn -0.2008 -0.8029 0.5613 +vn -0.3172 0.3365 0.8866 +vn -0.1733 -0.8575 0.4845 +vn -0.3268 0.2427 0.9134 +vn -0.0166 0.9988 0.0463 +vn -0.1442 -0.9038 0.4030 +vn -0.3333 0.1466 0.9314 +vn -0.0495 0.9892 0.1383 +vn -0.1136 -0.9414 0.3175 +vn -0.4229 -0.1466 0.8942 +vn -0.1830 0.9038 0.3869 +vn -0.0210 -0.9988 0.0444 +vn -0.4148 -0.2427 0.8770 +vn -0.2200 0.8575 0.4652 +vn -0.4026 -0.3365 0.8513 +vn -0.2549 0.8029 0.5389 +vn -0.3866 -0.4271 0.8174 +vn -0.2873 0.7405 0.6075 +vn -0.3668 -0.5136 0.7756 +vn -0.3170 0.6711 0.6702 +vn -0.3436 -0.5952 0.7264 +vn -0.3436 0.5952 0.7264 +vn -0.3170 -0.6711 0.6702 +vn -0.3668 0.5136 0.7756 +vn -0.2873 -0.7405 0.6075 +vn -0.3866 0.4271 0.8174 +vn -0.2549 -0.8029 0.5389 +vn -0.4026 0.3365 0.8513 +vn -0.2200 -0.8575 0.4652 +vn -0.4148 0.2427 0.8770 +vn -0.0210 0.9988 0.0444 +vn -0.1830 -0.9038 0.3869 +vn -0.4229 0.1466 0.8942 +vn -0.0628 0.9892 0.1328 +vn -0.1442 -0.9414 0.3049 +vn -0.4270 0.0490 0.9029 +vn -0.1040 0.9700 0.2199 +vn -0.1040 -0.9700 0.2199 +vn -0.4270 -0.0490 0.9029 +vn -0.1442 0.9414 0.3049 +vn -0.0628 -0.9892 0.1328 +vn -0.4841 -0.3365 0.8077 +vn -0.3065 0.8029 0.5113 +vn -0.4648 -0.4271 0.7755 +vn -0.3455 0.7405 0.5764 +vn -0.4411 -0.5136 0.7359 +vn -0.3811 0.6711 0.6359 +vn -0.4131 -0.5952 0.6892 +vn -0.4131 0.5952 0.6892 +vn -0.3811 -0.6711 0.6359 +vn -0.4411 0.5136 0.7359 +vn -0.3455 -0.7405 0.5764 +vn -0.4648 0.4271 0.7755 +vn -0.3065 -0.8029 0.5113 +vn -0.4841 0.3365 0.8077 +vn -0.2645 -0.8575 0.4414 +vn -0.4987 0.2427 0.8321 +vn -0.0253 0.9988 0.0421 +vn -0.2200 -0.9038 0.3671 +vn -0.5086 0.1466 0.8485 +vn -0.0755 0.9892 0.1260 +vn -0.1734 -0.9414 0.2893 +vn -0.5135 0.0490 0.8567 +vn -0.1251 0.9700 0.2086 +vn -0.1251 -0.9700 0.2086 +vn -0.5135 -0.0490 0.8567 +vn -0.1734 0.9414 0.2893 +vn -0.0755 -0.9892 0.1260 +vn -0.5086 -0.1466 0.8485 +vn -0.2200 0.9038 0.3671 +vn -0.0253 -0.9988 0.0421 +vn -0.4987 -0.2427 0.8321 +vn -0.2645 0.8575 0.4414 +vn -0.5111 -0.5136 0.6892 +vn -0.4416 0.6711 0.5955 +vn -0.4787 -0.5952 0.6454 +vn -0.4787 0.5952 0.6454 +vn -0.4416 -0.6711 0.5955 +vn -0.5111 0.5136 0.6892 +vn -0.4003 -0.7405 0.5398 +vn -0.5386 0.4271 0.7263 +vn -0.3551 -0.8029 0.4788 +vn -0.5610 0.3365 0.7564 +vn -0.3065 -0.8575 0.4133 +vn -0.5779 0.2427 0.7792 +vn -0.0293 0.9988 0.0395 +vn -0.2549 -0.9038 0.3438 +vn -0.5893 0.1466 0.7945 +vn -0.0875 0.9892 0.1180 +vn -0.2009 -0.9414 0.2709 +vn -0.5950 0.0490 0.8022 +vn -0.1449 0.9700 0.1954 +vn -0.1449 -0.9700 0.1954 +vn -0.5950 -0.0490 0.8022 +vn -0.2009 0.9414 0.2709 +vn -0.0875 -0.9892 0.1180 +vn -0.5893 -0.1466 0.7945 +vn -0.2549 0.9038 0.3438 +vn -0.0293 -0.9988 0.0395 +vn -0.5779 -0.2427 0.7792 +vn -0.3065 0.8575 0.4133 +vn -0.5610 -0.3365 0.7564 +vn -0.3551 0.8029 0.4788 +vn -0.5386 -0.4271 0.7263 +vn -0.4003 0.7405 0.5398 +vn -0.4979 -0.6711 0.5493 +vn -0.5762 0.5136 0.6357 +vn -0.4513 -0.7405 0.4979 +vn -0.6072 0.4271 0.6700 +vn -0.4004 -0.8029 0.4417 +vn -0.6324 0.3365 0.6977 +vn -0.3456 -0.8575 0.3813 +vn -0.6515 0.2427 0.7188 +vn -0.0330 0.9988 0.0364 +vn -0.2874 -0.9038 0.3171 +vn -0.6643 0.1466 0.7330 +vn -0.0987 0.9892 0.1088 +vn -0.2265 -0.9414 0.2499 +vn -0.6708 0.0490 0.7401 +vn -0.1634 0.9700 0.1802 +vn -0.1634 -0.9700 0.1802 +vn -0.6708 -0.0490 0.7401 +vn -0.2265 0.9414 0.2499 +vn -0.0987 -0.9892 0.1088 +vn -0.6643 -0.1466 0.7330 +vn -0.2874 0.9038 0.3171 +vn -0.0330 -0.9988 0.0364 +vn -0.6515 -0.2427 0.7188 +vn -0.3456 0.8575 0.3813 +vn -0.6324 -0.3365 0.6977 +vn -0.4004 0.8029 0.4417 +vn -0.6072 -0.4271 0.6700 +vn -0.4513 0.7405 0.4979 +vn -0.5762 -0.5136 0.6357 +vn -0.4979 0.6711 0.5493 +vn -0.5396 -0.5952 0.5954 +vn -0.5396 0.5952 0.5954 +vn -0.4417 -0.8029 0.4004 +vn -0.6977 0.3365 0.6324 +vn -0.3813 -0.8575 0.3456 +vn -0.7188 0.2427 0.6515 +vn -0.0364 0.9988 0.0330 +vn -0.3171 -0.9038 0.2874 +vn -0.7330 0.1466 0.6643 +vn -0.1088 0.9892 0.0987 +vn -0.2499 -0.9414 0.2265 +vn -0.7401 0.0490 0.6708 +vn -0.1802 0.9700 0.1634 +vn -0.1802 -0.9700 0.1634 +vn -0.7401 -0.0490 0.6708 +vn -0.2499 0.9414 0.2265 +vn -0.1088 -0.9892 0.0987 +vn -0.7330 -0.1466 0.6643 +vn -0.3171 0.9038 0.2874 +vn -0.0364 -0.9988 0.0330 +vn -0.7188 -0.2427 0.6515 +vn -0.3813 0.8575 0.3456 +vn -0.6977 -0.3365 0.6324 +vn -0.4417 0.8029 0.4004 +vn -0.6700 -0.4271 0.6072 +vn -0.4979 0.7405 0.4513 +vn -0.6357 -0.5136 0.5762 +vn -0.5493 0.6711 0.4979 +vn -0.5954 -0.5952 0.5396 +vn -0.5954 0.5952 0.5396 +vn -0.5493 -0.6711 0.4979 +vn -0.6357 0.5136 0.5762 +vn -0.4979 -0.7405 0.4513 +vn -0.6700 0.4271 0.6072 +vn -0.0395 0.9988 0.0293 +vn -0.3438 -0.9038 0.2549 +vn -0.7945 0.1466 0.5893 +vn -0.1180 0.9892 0.0875 +vn -0.2709 -0.9414 0.2009 +vn -0.8022 0.0490 0.5950 +vn -0.1954 0.9700 0.1449 +vn -0.1954 -0.9700 0.1449 +vn -0.8022 -0.0490 0.5950 +vn -0.2709 0.9414 0.2009 +vn -0.1180 -0.9891 0.0875 +vn -0.7945 -0.1466 0.5893 +vn -0.3438 0.9038 0.2549 +vn -0.0395 -0.9988 0.0293 +vn -0.7792 -0.2427 0.5779 +vn -0.4133 0.8575 0.3065 +vn -0.7564 -0.3365 0.5610 +vn -0.4788 0.8029 0.3551 +vn -0.7263 -0.4271 0.5386 +vn -0.5398 0.7405 0.4003 +vn -0.6892 -0.5136 0.5111 +vn -0.5955 0.6711 0.4416 +vn -0.6454 -0.5952 0.4787 +vn -0.6454 0.5952 0.4787 +vn -0.5955 -0.6711 0.4416 +vn -0.6892 0.5136 0.5111 +vn -0.5398 -0.7405 0.4003 +vn -0.7263 0.4271 0.5386 +vn -0.4788 -0.8029 0.3551 +vn -0.7564 0.3365 0.5610 +vn -0.4133 -0.8575 0.3065 +vn -0.7792 0.2427 0.5779 +vn -0.2086 0.9700 0.1251 +vn -0.2086 -0.9700 0.1251 +vn -0.8567 -0.0490 0.5135 +vn -0.2893 0.9414 0.1734 +vn -0.1260 -0.9892 0.0755 +vn -0.8485 -0.1466 0.5086 +vn -0.3671 0.9038 0.2200 +vn -0.0421 -0.9988 0.0253 +vn -0.8321 -0.2427 0.4987 +vn -0.4414 0.8575 0.2645 +vn -0.8077 -0.3365 0.4841 +vn -0.5113 0.8029 0.3065 +vn -0.7755 -0.4271 0.4648 +vn -0.5764 0.7405 0.3455 +vn -0.7359 -0.5136 0.4411 +vn -0.6359 0.6711 0.3811 +vn -0.6892 -0.5952 0.4131 +vn -0.6892 0.5952 0.4131 +vn -0.6359 -0.6711 0.3811 +vn -0.7359 0.5136 0.4411 +vn -0.5764 -0.7405 0.3455 +vn -0.7755 0.4271 0.4648 +vn -0.5113 -0.8029 0.3065 +vn -0.8077 0.3365 0.4841 +vn -0.4414 -0.8575 0.2645 +vn -0.8321 0.2427 0.4987 +vn -0.0421 0.9988 0.0253 +vn -0.3671 -0.9038 0.2200 +vn -0.8485 0.1466 0.5086 +vn -0.1260 0.9892 0.0755 +vn -0.2893 -0.9414 0.1734 +vn -0.8567 0.0490 0.5135 +vn -0.3869 0.9038 0.1830 +vn -0.0444 -0.9988 0.0210 +vn -0.8770 -0.2427 0.4148 +vn -0.4652 0.8575 0.2200 +vn -0.8513 -0.3365 0.4026 +vn -0.5389 0.8029 0.2549 +vn -0.8174 -0.4271 0.3866 +vn -0.6075 0.7405 0.2873 +vn -0.7756 -0.5136 0.3668 +vn -0.6702 0.6711 0.3170 +vn -0.7264 -0.5952 0.3436 +vn -0.7264 0.5952 0.3436 +vn -0.6702 -0.6711 0.3170 +vn -0.7756 0.5136 0.3668 +vn -0.6075 -0.7405 0.2873 +vn -0.8174 0.4271 0.3866 +vn -0.5389 -0.8029 0.2549 +vn -0.8513 0.3365 0.4026 +vn -0.4652 -0.8575 0.2200 +vn -0.8770 0.2427 0.4148 +vn -0.0444 0.9988 0.0210 +vn -0.3869 -0.9038 0.1830 +vn -0.8942 0.1466 0.4229 +vn -0.1328 0.9892 0.0628 +vn -0.3049 -0.9414 0.1442 +vn -0.9029 0.0490 0.4270 +vn -0.2199 0.9700 0.1040 +vn -0.2199 -0.9700 0.1040 +vn -0.9029 -0.0490 0.4270 +vn -0.3049 0.9414 0.1442 +vn -0.1328 -0.9892 0.0628 +vn -0.8942 -0.1466 0.4229 +vn -0.5613 0.8029 0.2008 +vn -0.8513 -0.4271 0.3046 +vn -0.6327 0.7405 0.2264 +vn -0.8078 -0.5136 0.2891 +vn -0.6980 0.6711 0.2498 +vn -0.7566 -0.5952 0.2707 +vn -0.7566 0.5952 0.2707 +vn -0.6980 -0.6711 0.2498 +vn -0.8078 0.5136 0.2891 +vn -0.6327 -0.7405 0.2264 +vn -0.8513 0.4271 0.3046 +vn -0.5613 -0.8029 0.2008 +vn -0.8866 0.3365 0.3172 +vn -0.4845 -0.8575 0.1733 +vn -0.9134 0.2427 0.3268 +vn -0.0463 0.9988 0.0165 +vn -0.4030 -0.9038 0.1442 +vn -0.9314 0.1466 0.3333 +vn -0.1383 0.9892 0.0495 +vn -0.3175 -0.9414 0.1136 +vn -0.9404 0.0490 0.3365 +vn -0.2290 0.9700 0.0820 +vn -0.2290 -0.9700 0.0820 +vn -0.9404 -0.0490 0.3365 +vn -0.3175 0.9414 0.1136 +vn -0.1383 -0.9892 0.0495 +vn -0.9314 -0.1466 0.3333 +vn -0.4030 0.9038 0.1442 +vn -0.0463 -0.9988 0.0166 +vn -0.9134 -0.2427 0.3268 +vn -0.4845 0.8575 0.1733 +vn -0.8866 -0.3365 0.3172 +vn -0.7191 0.6711 0.1801 +vn -0.7795 -0.5952 0.1952 +vn -0.7795 0.5952 0.1952 +vn -0.7191 -0.6711 0.1801 +vn -0.8323 0.5136 0.2085 +vn -0.6519 -0.7405 0.1633 +vn -0.8771 0.4271 0.2197 +vn -0.5783 -0.8029 0.1449 +vn -0.9135 0.3365 0.2288 +vn -0.4991 -0.8575 0.1250 +vn -0.9410 0.2427 0.2357 +vn -0.0477 0.9988 0.0119 +vn -0.4151 -0.9038 0.1040 +vn -0.9596 0.1466 0.2404 +vn -0.1425 0.9892 0.0357 +vn -0.3271 -0.9414 0.0819 +vn -0.9689 0.0490 0.2427 +vn -0.2360 0.9700 0.0591 +vn -0.2360 -0.9700 0.0591 +vn -0.9689 -0.0490 0.2427 +vn -0.3271 0.9414 0.0819 +vn -0.1425 -0.9892 0.0357 +vn -0.9596 -0.1466 0.2404 +vn -0.4152 0.9038 0.1040 +vn -0.0477 -0.9988 0.0119 +vn -0.9410 -0.2427 0.2357 +vn -0.4991 0.8575 0.1250 +vn -0.9135 -0.3365 0.2288 +vn -0.5783 0.8029 0.1449 +vn -0.8771 -0.4271 0.2197 +vn -0.6519 0.7405 0.1633 +vn -0.8323 -0.5136 0.2085 +vn -0.8487 0.5136 0.1259 +vn -0.6647 -0.7405 0.0986 +vn -0.8944 0.4271 0.1327 +vn -0.5897 -0.8029 0.0875 +vn -0.9315 0.3365 0.1382 +vn -0.5090 -0.8575 0.0755 +vn -0.9596 0.2427 0.1423 +vn -0.0486 0.9988 0.0072 +vn -0.4233 -0.9038 0.0628 +vn -0.9785 0.1466 0.1451 +vn -0.1453 0.9892 0.0215 +vn -0.3336 -0.9414 0.0495 +vn -0.9880 0.0490 0.1466 +vn -0.2406 0.9700 0.0357 +vn -0.2406 -0.9700 0.0357 +vn -0.9880 -0.0490 0.1466 +vn -0.3336 0.9414 0.0495 +vn -0.1453 -0.9892 0.0216 +vn -0.9785 -0.1466 0.1451 +vn -0.4233 0.9038 0.0628 +vn -0.0486 -0.9988 0.0072 +vn -0.9596 -0.2427 0.1423 +vn -0.5090 0.8575 0.0755 +vn -0.9315 -0.3365 0.1382 +vn -0.5897 0.8029 0.0875 +vn -0.8944 -0.4271 0.1327 +vn -0.6647 0.7405 0.0986 +vn -0.8487 -0.5136 0.1259 +vn -0.7333 0.6711 0.1088 +vn -0.7949 -0.5952 0.1179 +vn -0.7949 0.5952 0.1179 +vn -0.7333 -0.6711 0.1088 +vn -0.9405 0.3365 0.0462 +vn -0.5139 -0.8575 0.0252 +vn -0.9689 0.2427 0.0476 +vn -0.0491 0.9988 0.0024 +vn -0.4275 -0.9038 0.0210 +vn -0.9880 0.1466 0.0485 +vn -0.1467 0.9892 0.0072 +vn -0.3368 -0.9414 0.0166 +vn -0.9976 0.0490 0.0490 +vn -0.2430 0.9700 0.0119 +vn -0.2430 -0.9700 0.0119 +vn -0.9976 -0.0490 0.0490 +vn -0.3368 0.9414 0.0165 +vn -0.1467 -0.9892 0.0072 +vn -0.9880 -0.1466 0.0485 +vn -0.4275 0.9038 0.0210 +vn -0.0491 -0.9988 0.0024 +vn -0.9689 -0.2427 0.0476 +vn -0.5139 0.8575 0.0252 +vn -0.9405 -0.3365 0.0462 +vn -0.5954 0.8029 0.0293 +vn -0.9031 -0.4271 0.0444 +vn -0.6712 0.7405 0.0330 +vn -0.8570 -0.5136 0.0421 +vn -0.7405 0.6711 0.0364 +vn -0.8026 -0.5952 0.0394 +vn -0.8026 0.5952 0.0394 +vn -0.7405 -0.6711 0.0364 +vn -0.8570 0.5136 0.0421 +vn -0.6712 -0.7405 0.0330 +vn -0.9031 0.4271 0.0444 +vn -0.5954 -0.8029 0.0293 +vn -0.9880 0.1466 -0.0485 +vn -0.1467 0.9892 -0.0072 +vn -0.3368 -0.9414 -0.0165 +vn -0.9976 0.0490 -0.0490 +vn -0.2430 0.9700 -0.0119 +vn -0.2430 -0.9700 -0.0119 +vn -0.9976 -0.0490 -0.0490 +vn -0.3368 0.9414 -0.0165 +vn -0.1467 -0.9892 -0.0072 +vn -0.9880 -0.1466 -0.0485 +vn -0.4275 0.9038 -0.0210 +vn -0.0491 -0.9988 -0.0024 +vn -0.9689 -0.2427 -0.0476 +vn -0.5139 0.8575 -0.0252 +vn -0.9405 -0.3365 -0.0462 +vn -0.5954 0.8029 -0.0293 +vn -0.9031 -0.4271 -0.0444 +vn -0.6712 0.7405 -0.0330 +vn -0.8570 -0.5136 -0.0421 +vn -0.7405 0.6711 -0.0364 +vn -0.8026 -0.5952 -0.0394 +vn -0.8026 0.5952 -0.0394 +vn -0.7405 -0.6711 -0.0364 +vn -0.8570 0.5136 -0.0421 +vn -0.6712 -0.7405 -0.0330 +vn -0.9031 0.4271 -0.0444 +vn -0.5954 -0.8029 -0.0293 +vn -0.9405 0.3365 -0.0462 +vn -0.5139 -0.8575 -0.0252 +vn -0.9689 0.2427 -0.0476 +vn -0.0491 0.9988 -0.0024 +vn -0.4275 -0.9038 -0.0210 +vn -0.9880 -0.0490 -0.1466 +vn -0.3336 0.9414 -0.0495 +vn -0.1453 -0.9892 -0.0216 +vn -0.9785 -0.1466 -0.1451 +vn -0.4233 0.9038 -0.0628 +vn -0.0486 -0.9988 -0.0072 +vn -0.9596 -0.2427 -0.1423 +vn -0.5090 0.8575 -0.0755 +vn -0.9315 -0.3365 -0.1382 +vn -0.5897 0.8029 -0.0875 +vn -0.8944 -0.4271 -0.1327 +vn -0.6647 0.7405 -0.0986 +vn -0.8487 -0.5136 -0.1259 +vn -0.7333 0.6711 -0.1088 +vn -0.7949 -0.5952 -0.1179 +vn -0.7949 0.5952 -0.1179 +vn -0.7333 -0.6711 -0.1088 +vn -0.8487 0.5136 -0.1259 +vn -0.6647 -0.7405 -0.0986 +vn -0.8944 0.4271 -0.1327 +vn -0.5897 -0.8029 -0.0875 +vn -0.9315 0.3365 -0.1382 +vn -0.5090 -0.8575 -0.0755 +vn -0.9596 0.2427 -0.1423 +vn -0.0486 0.9988 -0.0072 +vn -0.4233 -0.9038 -0.0628 +vn -0.9785 0.1466 -0.1451 +vn -0.1453 0.9892 -0.0215 +vn -0.3336 -0.9414 -0.0495 +vn -0.9880 0.0490 -0.1466 +vn -0.2406 0.9700 -0.0357 +vn -0.2406 -0.9700 -0.0357 +vn -0.9410 -0.2427 -0.2357 +vn -0.4991 0.8575 -0.1250 +vn -0.9135 -0.3365 -0.2288 +vn -0.5783 0.8029 -0.1449 +vn -0.8771 -0.4271 -0.2197 +vn -0.6519 0.7405 -0.1633 +vn -0.8323 -0.5136 -0.2085 +vn -0.7191 0.6711 -0.1801 +vn -0.7795 -0.5952 -0.1952 +vn -0.7795 0.5952 -0.1952 +vn -0.7191 -0.6711 -0.1801 +vn -0.8323 0.5136 -0.2085 +vn -0.6519 -0.7405 -0.1633 +vn -0.8771 0.4271 -0.2197 +vn -0.5783 -0.8029 -0.1449 +vn -0.9135 0.3365 -0.2288 +vn -0.4991 -0.8575 -0.1250 +vn -0.9410 0.2427 -0.2357 +vn -0.0477 0.9988 -0.0119 +vn -0.4151 -0.9038 -0.1040 +vn -0.9596 0.1466 -0.2404 +vn -0.1425 0.9892 -0.0357 +vn -0.3271 -0.9414 -0.0819 +vn -0.9689 0.0490 -0.2427 +vn -0.2360 0.9700 -0.0591 +vn -0.2360 -0.9700 -0.0591 +vn -0.9689 -0.0490 -0.2427 +vn -0.3271 0.9414 -0.0819 +vn -0.1425 -0.9892 -0.0357 +vn -0.9596 -0.1465 -0.2404 +vn -0.4152 0.9038 -0.1040 +vn -0.0477 -0.9988 -0.0119 +vn -0.9404 0.0490 -0.3365 +vn -0.2290 0.9700 -0.0819 +vn -0.2290 -0.9700 -0.0820 +vn -0.9404 -0.0490 -0.3365 +vn -0.3175 0.9414 -0.1136 +vn -0.1383 -0.9892 -0.0495 +vn -0.9314 -0.1465 -0.3333 +vn -0.4030 0.9038 -0.1442 +vn -0.0463 -0.9988 -0.0166 +vn -0.9134 -0.2427 -0.3268 +vn -0.4845 0.8575 -0.1733 +vn -0.8866 -0.3365 -0.3172 +vn -0.5613 0.8029 -0.2008 +vn -0.8513 -0.4271 -0.3046 +vn -0.6327 0.7405 -0.2264 +vn -0.8078 -0.5136 -0.2891 +vn -0.6980 0.6711 -0.2498 +vn -0.7566 -0.5952 -0.2707 +vn -0.7566 0.5952 -0.2707 +vn -0.6980 -0.6711 -0.2498 +vn -0.8078 0.5136 -0.2891 +vn -0.6327 -0.7405 -0.2264 +vn -0.8513 0.4271 -0.3046 +vn -0.5613 -0.8029 -0.2008 +vn -0.8866 0.3365 -0.3172 +vn -0.4845 -0.8575 -0.1734 +vn -0.9134 0.2427 -0.3268 +vn -0.0463 0.9988 -0.0165 +vn -0.4030 -0.9038 -0.1442 +vn -0.9314 0.1466 -0.3333 +vn -0.1383 0.9892 -0.0495 +vn -0.3175 -0.9414 -0.1136 +vn -0.8942 -0.1465 -0.4229 +vn -0.3869 0.9038 -0.1830 +vn -0.0444 -0.9988 -0.0210 +vn -0.8770 -0.2427 -0.4148 +vn -0.4652 0.8575 -0.2200 +vn -0.8513 -0.3365 -0.4026 +vn -0.5389 0.8029 -0.2549 +vn -0.8174 -0.4271 -0.3866 +vn -0.6075 0.7405 -0.2873 +vn -0.7756 -0.5136 -0.3668 +vn -0.6702 0.6711 -0.3170 +vn -0.7264 -0.5952 -0.3436 +vn -0.7264 0.5952 -0.3436 +vn -0.6702 -0.6711 -0.3170 +vn -0.7756 0.5136 -0.3668 +vn -0.6075 -0.7405 -0.2873 +vn -0.8174 0.4271 -0.3866 +vn -0.5389 -0.8029 -0.2549 +vn -0.8513 0.3365 -0.4026 +vn -0.4652 -0.8575 -0.2200 +vn -0.8770 0.2427 -0.4148 +vn -0.0444 0.9988 -0.0210 +vn -0.3869 -0.9038 -0.1830 +vn -0.8942 0.1466 -0.4229 +vn -0.1328 0.9892 -0.0628 +vn -0.3049 -0.9414 -0.1442 +vn -0.9029 0.0490 -0.4270 +vn -0.2199 0.9700 -0.1040 +vn -0.2199 -0.9700 -0.1040 +vn -0.9029 -0.0490 -0.4270 +vn -0.3049 0.9414 -0.1442 +vn -0.1328 -0.9892 -0.0628 +vn -0.8077 -0.3365 -0.4841 +vn -0.5113 0.8029 -0.3065 +vn -0.7755 -0.4271 -0.4648 +vn -0.5764 0.7406 -0.3455 +vn -0.7359 -0.5136 -0.4411 +vn -0.6359 0.6711 -0.3811 +vn -0.6892 -0.5952 -0.4131 +vn -0.6892 0.5952 -0.4131 +vn -0.6359 -0.6711 -0.3811 +vn -0.7359 0.5136 -0.4411 +vn -0.5764 -0.7405 -0.3455 +vn -0.7755 0.4271 -0.4648 +vn -0.5113 -0.8029 -0.3065 +vn -0.8077 0.3365 -0.4841 +vn -0.4413 -0.8575 -0.2645 +vn -0.8321 0.2427 -0.4987 +vn -0.0421 0.9988 -0.0253 +vn -0.3671 -0.9038 -0.2200 +vn -0.8485 0.1466 -0.5086 +vn -0.1260 0.9892 -0.0755 +vn -0.2893 -0.9414 -0.1734 +vn -0.8567 0.0490 -0.5135 +vn -0.2086 0.9700 -0.1251 +vn -0.2086 -0.9700 -0.1251 +vn -0.8567 -0.0490 -0.5135 +vn -0.2893 0.9414 -0.1734 +vn -0.1260 -0.9892 -0.0755 +vn -0.8485 -0.1466 -0.5086 +vn -0.3671 0.9038 -0.2200 +vn -0.0421 -0.9988 -0.0253 +vn -0.8321 -0.2427 -0.4987 +vn -0.4414 0.8575 -0.2645 +vn -0.6892 -0.5136 -0.5111 +vn -0.5955 0.6711 -0.4416 +vn -0.6454 -0.5952 -0.4787 +vn -0.6454 0.5952 -0.4787 +vn -0.5955 -0.6711 -0.4416 +vn -0.6892 0.5136 -0.5111 +vn -0.5398 -0.7405 -0.4003 +vn -0.7263 0.4271 -0.5386 +vn -0.4788 -0.8029 -0.3551 +vn -0.7564 0.3365 -0.5610 +vn -0.4133 -0.8575 -0.3065 +vn -0.7792 0.2427 -0.5779 +vn -0.0395 0.9988 -0.0293 +vn -0.3438 -0.9038 -0.2549 +vn -0.7945 0.1466 -0.5893 +vn -0.1180 0.9892 -0.0875 +vn -0.2709 -0.9414 -0.2009 +vn -0.8022 0.0490 -0.5950 +vn -0.1954 0.9700 -0.1449 +vn -0.1954 -0.9700 -0.1449 +vn -0.8022 -0.0490 -0.5950 +vn -0.2709 0.9414 -0.2009 +vn -0.1180 -0.9892 -0.0875 +vn -0.7945 -0.1466 -0.5893 +vn -0.3438 0.9038 -0.2549 +vn -0.0395 -0.9988 -0.0293 +vn -0.7792 -0.2427 -0.5779 +vn -0.4133 0.8575 -0.3065 +vn -0.7564 -0.3365 -0.5610 +vn -0.4788 0.8029 -0.3551 +vn -0.7263 -0.4271 -0.5386 +vn -0.5398 0.7405 -0.4003 +vn -0.5493 -0.6711 -0.4979 +vn -0.6357 0.5136 -0.5762 +vn -0.4979 -0.7405 -0.4513 +vn -0.6700 0.4271 -0.6072 +vn -0.4417 -0.8029 -0.4004 +vn -0.6977 0.3365 -0.6324 +vn -0.3813 -0.8575 -0.3456 +vn -0.7188 0.2427 -0.6515 +vn -0.0364 0.9988 -0.0330 +vn -0.3171 -0.9038 -0.2874 +vn -0.7330 0.1465 -0.6643 +vn -0.1088 0.9892 -0.0987 +vn -0.2499 -0.9414 -0.2265 +vn -0.7401 0.0490 -0.6708 +vn -0.1802 0.9700 -0.1634 +vn -0.1802 -0.9700 -0.1634 +vn -0.7401 -0.0490 -0.6708 +vn -0.2499 0.9414 -0.2265 +vn -0.1088 -0.9892 -0.0987 +vn -0.7330 -0.1465 -0.6643 +vn -0.3171 0.9038 -0.2874 +vn -0.0364 -0.9988 -0.0330 +vn -0.7188 -0.2427 -0.6515 +vn -0.3813 0.8575 -0.3456 +vn -0.6977 -0.3365 -0.6324 +vn -0.4417 0.8029 -0.4004 +vn -0.6700 -0.4271 -0.6072 +vn -0.4979 0.7405 -0.4513 +vn -0.6357 -0.5136 -0.5762 +vn -0.5493 0.6711 -0.4979 +vn -0.5954 -0.5952 -0.5396 +vn -0.5954 0.5952 -0.5396 +vn -0.4004 -0.8029 -0.4417 +vn -0.6324 0.3365 -0.6977 +vn -0.3456 -0.8575 -0.3813 +vn -0.6515 0.2427 -0.7188 +vn -0.0330 0.9988 -0.0364 +vn -0.2874 -0.9038 -0.3171 +vn -0.6643 0.1465 -0.7330 +vn -0.0987 0.9892 -0.1089 +vn -0.2265 -0.9414 -0.2499 +vn -0.6708 0.0490 -0.7401 +vn -0.1634 0.9700 -0.1802 +vn -0.1634 -0.9700 -0.1802 +vn -0.6708 -0.0490 -0.7401 +vn -0.2265 0.9414 -0.2499 +vn -0.0987 -0.9892 -0.1089 +vn -0.6643 -0.1466 -0.7330 +vn -0.2874 0.9038 -0.3171 +vn -0.0330 -0.9988 -0.0364 +vn -0.6515 -0.2427 -0.7188 +vn -0.3456 0.8575 -0.3813 +vn -0.6324 -0.3365 -0.6977 +vn -0.4004 0.8029 -0.4417 +vn -0.6072 -0.4271 -0.6700 +vn -0.4513 0.7405 -0.4979 +vn -0.5762 -0.5136 -0.6357 +vn -0.4979 0.6711 -0.5493 +vn -0.5396 -0.5952 -0.5954 +vn -0.5396 0.5952 -0.5954 +vn -0.4979 -0.6711 -0.5493 +vn -0.5762 0.5136 -0.6357 +vn -0.4513 -0.7406 -0.4979 +vn -0.6072 0.4271 -0.6700 +vn -0.0293 0.9988 -0.0395 +vn -0.2549 -0.9038 -0.3438 +vn -0.5893 0.1466 -0.7945 +vn -0.0875 0.9892 -0.1180 +vn -0.2009 -0.9414 -0.2709 +vn -0.5950 0.0490 -0.8022 +vn -0.1449 0.9700 -0.1954 +vn -0.1449 -0.9700 -0.1954 +vn -0.5950 -0.0490 -0.8022 +vn -0.2009 0.9414 -0.2709 +vn -0.0875 -0.9891 -0.1180 +vn -0.5893 -0.1466 -0.7945 +vn -0.2549 0.9038 -0.3438 +vn -0.0293 -0.9988 -0.0395 +vn -0.5779 -0.2427 -0.7792 +vn -0.3065 0.8575 -0.4133 +vn -0.5610 -0.3365 -0.7564 +vn -0.3551 0.8029 -0.4788 +vn -0.5386 -0.4271 -0.7263 +vn -0.4003 0.7405 -0.5398 +vn -0.5111 -0.5136 -0.6892 +vn -0.4416 0.6711 -0.5955 +vn -0.4787 -0.5952 -0.6454 +vn -0.4787 0.5952 -0.6454 +vn -0.4416 -0.6711 -0.5955 +vn -0.5111 0.5136 -0.6892 +vn -0.4003 -0.7406 -0.5398 +vn -0.5386 0.4271 -0.7263 +vn -0.3551 -0.8029 -0.4788 +vn -0.5610 0.3365 -0.7564 +vn -0.3065 -0.8575 -0.4133 +vn -0.5779 0.2427 -0.7792 +vn -0.1251 0.9700 -0.2086 +vn -0.1251 -0.9700 -0.2086 +vn -0.5135 -0.0490 -0.8567 +vn -0.1734 0.9414 -0.2893 +vn -0.0755 -0.9892 -0.1260 +vn -0.5086 -0.1466 -0.8485 +vn -0.2200 0.9038 -0.3671 +vn -0.0253 -0.9988 -0.0421 +vn -0.4987 -0.2427 -0.8321 +vn -0.2645 0.8575 -0.4414 +vn -0.4841 -0.3365 -0.8077 +vn -0.3065 0.8029 -0.5113 +vn -0.4648 -0.4271 -0.7755 +vn -0.3455 0.7405 -0.5764 +vn -0.4411 -0.5136 -0.7359 +vn -0.3811 0.6711 -0.6359 +vn -0.4131 -0.5952 -0.6892 +vn -0.4131 0.5952 -0.6892 +vn -0.3811 -0.6711 -0.6359 +vn -0.4411 0.5136 -0.7359 +vn -0.3455 -0.7405 -0.5764 +vn -0.4648 0.4271 -0.7755 +vn -0.3065 -0.8029 -0.5113 +vn -0.4841 0.3365 -0.8077 +vn -0.2645 -0.8575 -0.4413 +vn -0.4987 0.2427 -0.8321 +vn -0.0253 0.9988 -0.0421 +vn -0.2200 -0.9038 -0.3671 +vn -0.5086 0.1465 -0.8485 +vn -0.0755 0.9892 -0.1260 +vn -0.1734 -0.9414 -0.2893 +vn -0.5135 0.0490 -0.8567 +vn -0.1830 0.9038 -0.3869 +vn -0.0210 -0.9988 -0.0444 +vn -0.4148 -0.2427 -0.8770 +vn -0.2200 0.8575 -0.4652 +vn -0.4026 -0.3365 -0.8513 +vn -0.2549 0.8029 -0.5389 +vn -0.3866 -0.4271 -0.8174 +vn -0.2873 0.7405 -0.6075 +vn -0.3668 -0.5136 -0.7756 +vn -0.3170 0.6711 -0.6702 +vn -0.3436 -0.5952 -0.7264 +vn -0.3436 0.5952 -0.7264 +vn -0.3170 -0.6711 -0.6702 +vn -0.3668 0.5136 -0.7756 +vn -0.2873 -0.7405 -0.6075 +vn -0.3866 0.4271 -0.8174 +vn -0.2549 -0.8029 -0.5389 +vn -0.4026 0.3365 -0.8513 +vn -0.2200 -0.8575 -0.4652 +vn -0.4148 0.2427 -0.8770 +vn -0.0210 0.9988 -0.0444 +vn -0.1830 -0.9038 -0.3869 +vn -0.4229 0.1465 -0.8942 +vn -0.0628 0.9892 -0.1328 +vn -0.1442 -0.9414 -0.3049 +vn -0.4270 0.0490 -0.9029 +vn -0.1040 0.9700 -0.2199 +vn -0.1040 -0.9700 -0.2199 +vn -0.4270 -0.0490 -0.9029 +vn -0.1442 0.9414 -0.3049 +vn -0.0628 -0.9892 -0.1328 +vn -0.4229 -0.1466 -0.8942 +vn -0.2008 0.8029 -0.5613 +vn -0.3046 -0.4271 -0.8513 +vn -0.2264 0.7405 -0.6327 +vn -0.2891 -0.5136 -0.8078 +vn -0.2498 0.6711 -0.6980 +vn -0.2707 -0.5952 -0.7566 +vn -0.2707 0.5952 -0.7566 +vn -0.2498 -0.6711 -0.6980 +vn -0.2891 0.5136 -0.8078 +vn -0.2264 -0.7405 -0.6327 +vn -0.3046 0.4271 -0.8513 +vn -0.2008 -0.8029 -0.5613 +vn -0.3172 0.3365 -0.8866 +vn -0.1733 -0.8575 -0.4845 +vn -0.3268 0.2427 -0.9134 +vn -0.0166 0.9988 -0.0463 +vn -0.1442 -0.9038 -0.4030 +vn -0.3333 0.1465 -0.9314 +vn -0.0495 0.9892 -0.1383 +vn -0.1136 -0.9414 -0.3175 +vn -0.3365 0.0490 -0.9404 +vn -0.0820 0.9700 -0.2290 +vn -0.0820 -0.9700 -0.2290 +vn -0.3365 -0.0490 -0.9404 +vn -0.1136 0.9414 -0.3175 +vn -0.0495 -0.9892 -0.1383 +vn -0.3333 -0.1466 -0.9314 +vn -0.1442 0.9038 -0.4030 +vn -0.0166 -0.9988 -0.0463 +vn -0.3268 -0.2427 -0.9134 +vn -0.1733 0.8575 -0.4845 +vn -0.3172 -0.3365 -0.8866 +vn -0.1801 0.6711 -0.7191 +vn -0.1952 -0.5952 -0.7795 +vn -0.1952 0.5952 -0.7795 +vn -0.1801 -0.6711 -0.7191 +vn -0.2085 0.5136 -0.8323 +vn -0.1633 -0.7405 -0.6519 +vn -0.2197 0.4271 -0.8771 +vn -0.1449 -0.8029 -0.5783 +vn -0.2288 0.3365 -0.9135 +vn -0.1250 -0.8575 -0.4991 +vn -0.2357 0.2427 -0.9410 +vn -0.0119 0.9988 -0.0477 +vn -0.1040 -0.9038 -0.4151 +vn -0.2404 0.1465 -0.9596 +vn -0.0357 0.9892 -0.1425 +vn -0.0819 -0.9414 -0.3271 +vn -0.2427 0.0490 -0.9689 +vn -0.0591 0.9700 -0.2360 +vn -0.0591 -0.9700 -0.2360 +vn -0.2427 -0.0490 -0.9689 +vn -0.0819 0.9414 -0.3271 +vn -0.0357 -0.9892 -0.1425 +vn -0.2404 -0.1465 -0.9596 +vn -0.1040 0.9038 -0.4151 +vn -0.0119 -0.9988 -0.0477 +vn -0.2357 -0.2427 -0.9410 +vn -0.1250 0.8575 -0.4991 +vn -0.2288 -0.3365 -0.9135 +vn -0.1449 0.8029 -0.5783 +vn -0.2197 -0.4271 -0.8771 +vn -0.1633 0.7405 -0.6519 +vn -0.2085 -0.5136 -0.8323 +vn -0.1259 0.5136 -0.8487 +vn -0.0986 -0.7405 -0.6647 +vn -0.1327 0.4271 -0.8944 +vn -0.0875 -0.8029 -0.5897 +vn -0.1382 0.3365 -0.9315 +vn -0.0755 -0.8575 -0.5090 +vn -0.1423 0.2427 -0.9596 +vn -0.0072 0.9988 -0.0486 +vn -0.0628 -0.9038 -0.4233 +vn -0.1451 0.1465 -0.9785 +vn -0.0216 0.9892 -0.1453 +vn -0.0495 -0.9414 -0.3336 +vn -0.1466 0.0490 -0.9880 +vn -0.0357 0.9700 -0.2406 +vn -0.0357 -0.9700 -0.2406 +vn -0.1466 -0.0490 -0.9880 +vn -0.0495 0.9414 -0.3336 +vn -0.0216 -0.9892 -0.1453 +vn -0.1451 -0.1465 -0.9785 +vn -0.0628 0.9038 -0.4233 +vn -0.0072 -0.9988 -0.0486 +vn -0.1423 -0.2427 -0.9596 +vn -0.0755 0.8575 -0.5090 +vn -0.1382 -0.3365 -0.9315 +vn -0.0875 0.8029 -0.5897 +vn -0.1327 -0.4271 -0.8944 +vn -0.0986 0.7406 -0.6647 +vn -0.1259 -0.5136 -0.8487 +vn -0.1088 0.6711 -0.7333 +vn -0.1179 -0.5952 -0.7949 +vn -0.1179 0.5952 -0.7949 +vn -0.1088 -0.6711 -0.7333 +vn -0.0462 0.3365 -0.9405 +vn -0.0253 -0.8575 -0.5139 +vn -0.0476 0.2427 -0.9689 +vn -0.0024 0.9988 -0.0491 +vn -0.0210 -0.9038 -0.4275 +vn -0.0485 0.1466 -0.9880 +vn -0.0072 0.9892 -0.1467 +vn -0.0165 -0.9414 -0.3368 +vn -0.0490 0.0490 -0.9976 +vn -0.0119 0.9700 -0.2430 +vn -0.0119 -0.9700 -0.2430 +vn -0.0490 -0.0490 -0.9976 +vn -0.0165 0.9414 -0.3368 +vn -0.0072 -0.9892 -0.1467 +vn -0.0485 -0.1465 -0.9880 +vn -0.0210 0.9038 -0.4275 +vn -0.0024 -0.9988 -0.0491 +vn -0.0476 -0.2427 -0.9689 +vn -0.0252 0.8575 -0.5139 +vn -0.0462 -0.3365 -0.9405 +vn -0.0293 0.8029 -0.5954 +vn -0.0444 -0.4271 -0.9031 +vn -0.0330 0.7405 -0.6712 +vn -0.0421 -0.5136 -0.8570 +vn -0.0364 0.6711 -0.7405 +vn -0.0394 -0.5952 -0.8026 +vn -0.0394 0.5952 -0.8026 +vn -0.0364 -0.6711 -0.7405 +vn -0.0421 0.5136 -0.8570 +vn -0.0330 -0.7405 -0.6712 +vn -0.0444 0.4271 -0.9031 +vn -0.0293 -0.8029 -0.5954 +vn 0.0819 0.9700 -0.2290 +vn 0.2645 -0.8575 -0.4414 +vn 0.1251 -0.9700 -0.2087 +vn 0.5386 0.4271 -0.7263 +vn 0.0987 -0.9892 -0.1089 +vn 0.6643 -0.1466 -0.7329 +vn 0.0987 0.9892 -0.1088 +vn 0.7329 0.1466 -0.6643 +vn 0.7330 -0.1466 -0.6643 +vn 0.1180 0.9891 -0.0875 +vn 0.4845 -0.8575 -0.1734 +vn 0.2290 -0.9700 -0.0820 +vn 0.4845 0.8575 -0.1733 +vn 0.4152 0.9038 -0.1040 +vn 0.4151 -0.9038 -0.1040 +vn 0.5139 0.8575 -0.0253 +vn 0.5954 -0.8029 -0.0293 +vn 0.3368 0.9414 -0.0165 +vn 0.4152 -0.9038 0.1040 +vn 0.2290 0.9700 0.0819 +vn 0.1328 0.9891 0.0628 +vn 0.0987 0.9892 0.1088 +vn 0.0987 -0.9892 0.1088 +vn 0.0820 0.9700 0.2290 +vn 0.2891 -0.5136 0.8078 +vn 0.1040 -0.9038 0.4152 +vn -0.0357 0.9891 0.1425 +vn -0.0820 0.9700 0.2290 +vn -0.0820 -0.9700 0.2290 +vn -0.1251 0.9700 0.2087 +vn -0.0875 -0.9891 0.1180 +vn -0.0987 0.9891 0.1089 +vn -0.1180 0.9891 0.0875 +vn -0.1180 -0.9892 0.0875 +vn -0.5764 0.7406 0.3455 +vn -0.2290 0.9700 0.0819 +vn -0.2290 -0.9700 0.0819 +vn -0.4845 0.8575 0.1734 +vn -0.4152 -0.9038 0.1040 +vn -0.1453 0.9892 0.0216 +vn -0.6647 0.7406 0.0986 +vn -0.3368 -0.9414 0.0165 +vn -0.3368 0.9414 0.0166 +vn -0.3368 0.9414 -0.0166 +vn -0.1453 0.9892 -0.0216 +vn -0.9596 0.1465 -0.2404 +vn -0.9596 -0.1466 -0.2404 +vn -0.2290 -0.9700 -0.0819 +vn -0.9314 -0.1466 -0.3333 +vn -0.4845 -0.8575 -0.1733 +vn -0.9314 0.1465 -0.3333 +vn -0.8942 -0.1466 -0.4229 +vn -0.8942 0.1465 -0.4229 +vn -0.5764 0.7405 -0.3455 +vn -0.4414 -0.8575 -0.2645 +vn -0.4413 0.8575 -0.2645 +vn -0.6643 0.1466 -0.7330 +vn -0.0987 0.9892 -0.1088 +vn -0.0987 -0.9892 -0.1088 +vn -0.6643 -0.1465 -0.7330 +vn -0.4513 0.7406 -0.4979 +vn -0.4513 -0.7405 -0.4979 +vn -0.0875 -0.9892 -0.1180 +vn -0.4003 -0.7405 -0.5398 +vn -0.5086 -0.1465 -0.8485 +vn -0.2645 0.8575 -0.4413 +vn -0.3455 -0.7406 -0.5764 +vn -0.5086 0.1466 -0.8485 +vn -0.4229 0.1466 -0.8942 +vn -0.4229 -0.1465 -0.8942 +vn -0.3333 0.1466 -0.9314 +vn -0.0819 0.9700 -0.2290 +vn -0.3333 -0.1465 -0.9314 +vn -0.1040 -0.9038 -0.4152 +vn -0.1040 0.9038 -0.4152 +vn -0.0986 0.7405 -0.6647 +vn -0.0252 -0.8575 -0.5139 +vn -0.0485 0.1465 -0.9880 +vn -0.0485 -0.1466 -0.9880 +vn -0.0253 0.8575 -0.5139 +vn -0.0330 0.7406 -0.6712 +usemtl None +s off +f 20/1/1 47/2/1 48/3/1 +f 9/4/2 35/5/2 10/6/2 +f 21/7/3 48/3/3 49/8/3 +f 1981/9/4 35/5/4 36/10/4 +f 22/11/5 49/8/5 50/12/5 +f 11/13/6 36/10/6 37/14/6 +f 23/15/7 50/12/7 51/16/7 +f 12/17/8 37/14/8 38/18/8 +f 24/19/9 51/16/9 52/20/9 +f 13/21/10 38/18/10 39/22/10 +f 1/23/11 1452/24/11 26/25/11 +f 24/19/12 53/26/12 1984/27/12 +f 14/28/13 39/22/13 40/29/13 +f 1/23/14 27/30/14 2/31/14 +f 1984/27/15 54/32/15 25/33/15 +f 14/28/16 41/34/16 15/35/16 +f 2/31/17 28/36/17 3/37/17 +f 25/33/18 55/38/18 1985/39/18 +f 15/35/19 42/40/19 16/41/19 +f 4/42/20 28/36/20 29/43/20 +f 1985/39/21 56/44/21 1986/45/21 +f 16/41/22 43/46/22 1982/47/22 +f 5/48/23 29/43/23 30/49/23 +f 1887/50/24 1986/45/24 56/44/24 +f 17/51/25 43/46/25 44/52/25 +f 5/48/26 31/53/26 6/54/26 +f 17/51/27 45/55/27 1983/56/27 +f 6/54/28 32/57/28 7/58/28 +f 1983/56/29 46/59/29 18/60/29 +f 7/58/30 33/61/30 8/62/30 +f 18/60/31 47/2/31 19/63/31 +f 8/62/32 34/64/32 9/4/32 +f 42/40/33 74/65/33 43/46/33 +f 29/43/34 61/66/34 30/49/34 +f 1887/67/35 56/44/35 87/68/35 +f 43/46/36 75/69/36 44/52/36 +f 30/49/37 62/70/37 31/53/37 +f 44/52/38 76/71/38 45/55/38 +f 31/53/39 63/72/39 32/57/39 +f 45/55/40 77/73/40 46/59/40 +f 32/57/41 64/74/41 33/61/41 +f 46/59/42 78/75/42 47/2/42 +f 34/64/43 64/74/43 65/76/43 +f 47/2/44 79/77/44 48/3/44 +f 34/64/45 66/78/45 35/5/45 +f 48/3/46 80/79/46 49/8/46 +f 36/10/47 66/78/47 67/80/47 +f 50/12/48 80/79/48 81/81/48 +f 36/10/49 68/82/49 37/14/49 +f 51/16/50 81/81/50 82/83/50 +f 38/18/51 68/82/51 69/84/51 +f 52/20/52 82/83/52 83/85/52 +f 38/18/53 70/86/53 39/22/53 +f 26/25/54 1452/87/54 57/88/54 +f 52/20/55 84/89/55 53/26/55 +f 39/22/56 71/90/56 40/29/56 +f 26/25/57 58/91/57 27/30/57 +f 53/26/58 85/92/58 54/32/58 +f 41/34/59 71/90/59 72/93/59 +f 28/36/60 58/91/60 59/94/60 +f 54/32/61 86/95/61 55/38/61 +f 41/34/62 73/96/62 42/40/62 +f 28/36/63 60/97/63 29/43/63 +f 55/38/64 87/68/64 56/44/64 +f 76/71/65 106/98/65 107/99/65 +f 62/70/66 94/100/66 63/72/66 +f 76/71/67 108/101/67 77/73/67 +f 63/72/68 95/102/68 64/74/68 +f 78/75/69 108/101/69 109/103/69 +f 64/74/70 96/104/70 65/76/70 +f 78/75/71 110/105/71 79/77/71 +f 66/78/72 96/104/72 97/106/72 +f 79/77/73 111/107/73 80/79/73 +f 67/80/74 97/106/74 98/108/74 +f 81/81/75 111/107/75 112/109/75 +f 67/80/76 99/110/76 68/82/76 +f 82/83/77 112/109/77 113/111/77 +f 68/82/78 100/112/78 69/84/78 +f 83/85/79 113/111/79 114/113/79 +f 69/84/80 101/114/80 70/86/80 +f 57/88/81 1452/115/81 88/116/81 +f 83/85/82 115/117/82 84/89/82 +f 71/90/83 101/114/83 102/118/83 +f 57/88/84 89/119/84 58/91/84 +f 85/92/85 115/117/85 116/120/85 +f 71/90/86 103/121/86 72/93/86 +f 58/91/87 90/122/87 59/94/87 +f 85/92/88 117/123/88 86/95/88 +f 72/93/89 104/124/89 73/96/89 +f 60/97/90 90/122/90 91/125/90 +f 86/95/91 118/126/91 87/68/91 +f 73/96/92 105/127/92 74/65/92 +f 61/66/93 91/125/93 92/128/93 +f 1887/129/94 87/68/94 118/126/94 +f 74/65/95 106/98/95 75/69/95 +f 61/66/96 93/130/96 62/70/96 +f 108/101/97 140/131/97 109/103/97 +f 95/102/98 127/132/98 96/104/98 +f 109/103/99 141/133/99 110/105/99 +f 97/106/100 127/132/100 128/134/100 +f 110/105/101 142/135/101 111/107/101 +f 98/108/102 128/134/102 129/136/102 +f 112/109/103 142/135/103 143/137/103 +f 98/108/104 130/138/104 99/110/104 +f 112/109/105 144/139/105 113/111/105 +f 99/110/106 131/140/106 100/112/106 +f 113/111/107 145/141/107 114/113/107 +f 100/112/108 132/142/108 101/114/108 +f 88/116/109 1452/143/109 119/144/109 +f 114/113/110 146/145/110 115/117/110 +f 102/118/111 132/142/111 133/146/111 +f 88/116/112 120/147/112 89/119/112 +f 115/117/113 147/148/113 116/120/113 +f 102/118/114 134/149/114 103/121/114 +f 90/122/115 120/147/115 121/150/115 +f 116/120/116 148/151/116 117/123/116 +f 103/121/117 135/152/117 104/124/117 +f 91/125/118 121/150/118 122/153/118 +f 118/126/119 148/151/119 149/154/119 +f 104/124/120 136/155/120 105/127/120 +f 92/128/121 122/153/121 123/156/121 +f 1887/157/122 118/126/122 149/154/122 +f 105/127/123 137/158/123 106/98/123 +f 93/130/124 123/156/124 124/159/124 +f 106/98/125 138/160/125 107/99/125 +f 94/100/126 124/159/126 125/161/126 +f 108/101/127 138/160/127 139/162/127 +f 94/100/128 126/163/128 95/102/128 +f 142/135/129 172/164/129 173/165/129 +f 129/136/130 159/166/130 160/167/130 +f 142/135/131 174/168/131 143/137/131 +f 129/136/132 161/169/132 130/138/132 +f 143/137/133 175/170/133 144/139/133 +f 130/138/134 162/171/134 131/140/134 +f 144/139/135 176/172/135 145/141/135 +f 131/140/136 163/173/136 132/142/136 +f 119/144/137 1452/174/137 150/175/137 +f 146/145/138 176/172/138 177/176/138 +f 133/146/139 163/173/139 164/177/139 +f 119/144/140 151/178/140 120/147/140 +f 146/145/141 178/179/141 147/148/141 +f 133/146/142 165/180/142 134/149/142 +f 120/147/143 152/181/143 121/150/143 +f 147/148/144 179/182/144 148/151/144 +f 134/149/145 166/183/145 135/152/145 +f 121/150/146 153/184/146 122/153/146 +f 149/154/147 179/182/147 180/185/147 +f 136/155/148 166/183/148 167/186/148 +f 122/153/149 154/187/149 123/156/149 +f 1887/188/150 149/154/150 180/185/150 +f 136/155/151 168/189/151 137/158/151 +f 123/156/152 155/190/152 124/159/152 +f 137/158/153 169/191/153 138/160/153 +f 125/161/154 155/190/154 156/192/154 +f 138/160/155 170/193/155 139/162/155 +f 125/161/156 157/194/156 126/163/156 +f 140/131/157 170/193/157 171/195/157 +f 126/163/158 158/196/158 127/132/158 +f 140/131/159 172/164/159 141/133/159 +f 128/134/160 158/196/160 159/166/160 +f 174/168/161 206/197/161 175/170/161 +f 161/169/162 193/198/162 162/171/162 +f 176/172/163 206/197/163 207/199/163 +f 162/171/164 194/200/164 163/173/164 +f 150/175/165 1452/201/165 181/202/165 +f 176/172/166 208/203/166 177/176/166 +f 164/177/167 194/200/167 195/204/167 +f 150/175/168 182/205/168 151/178/168 +f 177/176/169 209/206/169 178/179/169 +f 164/177/170 196/207/170 165/180/170 +f 152/181/171 182/205/171 183/208/171 +f 178/179/172 210/209/172 179/182/172 +f 166/183/173 196/207/173 197/210/173 +f 153/184/174 183/208/174 184/211/174 +f 179/182/175 211/212/175 180/185/175 +f 166/183/176 198/213/176 167/186/176 +f 153/184/177 185/214/177 154/187/177 +f 1887/215/178 180/185/178 211/212/178 +f 168/189/179 198/213/179 199/216/179 +f 154/187/180 186/217/180 155/190/180 +f 169/191/181 199/216/181 200/218/181 +f 156/192/182 186/217/182 187/219/182 +f 170/193/183 200/218/183 201/220/183 +f 156/192/184 188/221/184 157/194/184 +f 171/195/185 201/220/185 202/222/185 +f 158/196/186 188/221/186 189/223/186 +f 171/195/187 203/224/187 172/164/187 +f 159/166/188 189/223/188 190/225/188 +f 173/165/189 203/224/189 204/226/189 +f 160/167/190 190/225/190 191/227/190 +f 173/165/191 205/228/191 174/168/191 +f 160/167/192 192/229/192 161/169/192 +f 181/202/193 1452/230/193 212/231/193 +f 207/199/194 239/232/194 208/203/194 +f 195/204/195 225/233/195 226/234/195 +f 181/202/196 213/235/196 182/205/196 +f 208/203/197 240/236/197 209/206/197 +f 195/204/198 227/237/198 196/207/198 +f 182/205/199 214/238/199 183/208/199 +f 209/206/200 241/239/200 210/209/200 +f 197/210/201 227/237/201 228/240/201 +f 184/211/202 214/238/202 215/241/202 +f 210/209/203 242/242/203 211/212/203 +f 197/210/204 229/243/204 198/213/204 +f 184/211/205 216/244/205 185/214/205 +f 1887/245/206 211/212/206 242/242/206 +f 199/216/207 229/243/207 230/246/207 +f 186/217/208 216/244/208 217/247/208 +f 199/216/209 231/248/209 200/218/209 +f 187/219/210 217/247/210 218/249/210 +f 201/220/211 231/248/211 232/250/211 +f 188/221/212 218/249/212 219/251/212 +f 202/222/213 232/250/213 233/252/213 +f 188/221/214 220/253/214 189/223/214 +f 203/224/215 233/252/215 234/254/215 +f 189/223/216 221/255/216 190/225/216 +f 204/226/217 234/254/217 235/256/217 +f 191/227/218 221/255/218 222/257/218 +f 204/226/219 236/258/219 205/228/219 +f 191/227/220 223/259/220 192/229/220 +f 205/228/221 237/260/221 206/197/221 +f 193/198/222 223/259/222 224/261/222 +f 206/197/223 238/262/223 207/199/223 +f 193/198/224 225/233/224 194/200/224 +f 213/235/225 245/263/225 214/238/225 +f 240/236/226 272/264/226 241/239/226 +f 228/240/227 258/265/227 259/266/227 +f 215/241/228 245/263/228 246/267/228 +f 241/239/229 273/268/229 242/242/229 +f 228/240/230 260/269/230 229/243/230 +f 215/241/231 247/270/231 216/244/231 +f 1887/271/232 242/242/232 273/268/232 +f 230/246/233 260/269/233 261/272/233 +f 216/244/234 248/273/234 217/247/234 +f 230/246/235 262/274/235 231/248/235 +f 217/247/236 249/275/236 218/249/236 +f 232/250/237 262/274/237 263/276/237 +f 219/251/238 249/275/238 250/277/238 +f 233/252/239 263/276/239 264/278/239 +f 219/251/240 251/279/240 220/253/240 +f 234/254/241 264/278/241 265/280/241 +f 220/253/242 252/281/242 221/255/242 +f 235/256/243 265/280/243 266/282/243 +f 222/257/244 252/281/244 253/283/244 +f 235/256/245 267/284/245 236/258/245 +f 222/257/246 254/285/246 223/259/246 +f 236/258/247 268/286/247 237/260/247 +f 224/261/248 254/285/248 255/287/248 +f 237/260/249 269/288/249 238/262/249 +f 224/261/250 256/289/250 225/233/250 +f 212/231/251 1452/290/251 243/291/251 +f 238/262/252 270/292/252 239/232/252 +f 226/234/253 256/289/253 257/293/253 +f 212/231/254 244/294/254 213/235/254 +f 239/232/255 271/295/255 240/236/255 +f 226/234/256 258/265/256 227/237/256 +f 246/267/257 278/296/257 247/270/257 +f 1887/297/258 273/268/258 304/298/258 +f 261/272/259 291/299/259 292/300/259 +f 247/270/260 279/301/260 248/273/260 +f 261/272/261 293/302/261 262/274/261 +f 249/275/262 279/301/262 280/303/262 +f 263/276/263 293/302/263 294/304/263 +f 250/277/264 280/303/264 281/305/264 +f 264/278/265 294/304/265 295/306/265 +f 250/277/266 282/307/266 251/279/266 +f 264/278/267 296/308/267 265/280/267 +f 252/281/268 282/307/268 283/309/268 +f 266/282/269 296/308/269 297/310/269 +f 252/281/270 284/311/270 253/283/270 +f 266/282/271 298/312/271 267/284/271 +f 253/283/272 285/313/272 254/285/272 +f 268/286/273 298/312/273 299/314/273 +f 255/287/274 285/313/274 286/315/274 +f 269/288/275 299/314/275 300/316/275 +f 255/287/276 287/317/276 256/289/276 +f 243/291/277 1452/318/277 274/319/277 +f 269/288/278 301/320/278 270/292/278 +f 257/293/279 287/317/279 288/321/279 +f 243/291/280 275/322/280 244/294/280 +f 271/295/281 301/320/281 302/323/281 +f 257/293/282 289/324/282 258/265/282 +f 244/294/283 276/325/283 245/263/283 +f 271/295/284 303/326/284 272/264/284 +f 259/266/285 289/324/285 290/327/285 +f 246/267/286 276/325/286 277/328/286 +f 273/268/287 303/326/287 304/298/287 +f 259/266/288 291/299/288 260/269/288 +f 279/301/289 311/329/289 280/303/289 +f 294/304/290 324/330/290 325/331/290 +f 281/305/291 311/329/291 312/332/291 +f 295/306/292 325/331/292 326/333/292 +f 281/305/293 313/334/293 282/307/293 +f 295/306/294 327/335/294 296/308/294 +f 283/309/295 313/334/295 314/336/295 +f 296/308/296 328/337/296 297/310/296 +f 284/311/297 314/336/297 315/338/297 +f 297/310/298 329/339/298 298/312/298 +f 285/313/299 315/338/299 316/340/299 +f 299/314/300 329/339/300 330/341/300 +f 286/315/301 316/340/301 317/342/301 +f 300/316/302 330/341/302 331/343/302 +f 286/315/303 318/344/303 287/317/303 +f 274/319/304 1452/345/304 305/346/304 +f 300/316/305 332/347/305 301/320/305 +f 288/321/306 318/344/306 319/348/306 +f 274/319/307 306/349/307 275/322/307 +f 301/320/308 333/350/308 302/323/308 +f 288/321/309 320/351/309 289/324/309 +f 275/322/310 307/352/310 276/325/310 +f 302/323/311 334/353/311 303/326/311 +f 290/327/312 320/351/312 321/354/312 +f 277/328/313 307/352/313 308/355/313 +f 304/298/314 334/353/314 335/356/314 +f 290/327/315 322/357/315 291/299/315 +f 277/328/316 309/358/316 278/296/316 +f 1887/359/317 304/298/317 335/356/317 +f 292/300/318 322/357/318 323/360/318 +f 278/296/319 310/361/319 279/301/319 +f 292/300/320 324/330/320 293/302/320 +f 312/332/321 344/362/321 313/334/321 +f 327/335/322 357/363/322 358/364/322 +f 313/334/323 345/365/323 314/336/323 +f 328/337/324 358/364/324 359/366/324 +f 315/338/325 345/365/325 346/367/325 +f 329/339/326 359/366/326 360/368/326 +f 315/338/327 347/369/327 316/340/327 +f 330/341/328 360/368/328 361/370/328 +f 317/342/329 347/369/329 348/371/329 +f 330/341/330 362/372/330 331/343/330 +f 317/342/331 349/373/331 318/344/331 +f 305/346/332 1452/374/332 336/375/332 +f 331/343/333 363/376/333 332/347/333 +f 319/348/334 349/373/334 350/377/334 +f 305/346/335 337/378/335 306/349/335 +f 332/347/336 364/379/336 333/350/336 +f 319/348/337 351/380/337 320/351/337 +f 307/352/338 337/378/338 338/381/338 +f 333/350/339 365/382/339 334/353/339 +f 321/354/340 351/380/340 352/383/340 +f 308/355/341 338/381/341 339/384/341 +f 335/356/342 365/382/342 366/385/342 +f 321/354/343 353/386/343 322/357/343 +f 309/358/344 339/384/344 340/387/344 +f 1887/388/345 335/356/345 366/385/345 +f 323/360/346 353/386/346 354/389/346 +f 310/361/347 340/387/347 341/390/347 +f 323/360/348 355/391/348 324/330/348 +f 310/361/349 342/392/349 311/329/349 +f 325/331/350 355/391/350 356/393/350 +f 311/329/351 343/394/351 312/332/351 +f 326/333/352 356/393/352 357/363/352 +f 346/367/353 376/395/353 377/396/353 +f 360/368/354 390/397/354 391/398/354 +f 346/367/355 378/399/355 347/369/355 +f 361/370/356 391/398/356 392/400/356 +f 348/371/357 378/399/357 379/401/357 +f 362/372/358 392/400/358 393/402/358 +f 348/371/359 380/403/359 349/373/359 +f 336/375/360 1452/404/360 367/405/360 +f 362/372/361 394/406/361 363/376/361 +f 350/377/362 380/403/362 381/407/362 +f 336/375/363 368/408/363 337/378/363 +f 364/379/364 394/406/364 395/409/364 +f 350/377/365 382/410/365 351/380/365 +f 337/378/366 369/411/366 338/381/366 +f 364/379/367 396/412/367 365/382/367 +f 351/380/368 383/413/368 352/383/368 +f 339/384/369 369/411/369 370/414/369 +f 366/385/370 396/412/370 397/415/370 +f 352/383/371 384/416/371 353/386/371 +f 339/384/372 371/417/372 340/387/372 +f 1887/418/373 366/385/373 397/415/373 +f 354/389/374 384/416/374 385/419/374 +f 341/390/375 371/417/375 372/420/375 +f 354/389/376 386/421/376 355/391/376 +f 341/390/377 373/422/377 342/392/377 +f 356/393/378 386/421/378 387/423/378 +f 342/392/379 374/424/379 343/394/379 +f 357/363/380 387/423/380 388/425/380 +f 344/362/381 374/424/381 375/426/381 +f 358/364/382 388/425/382 389/427/382 +f 345/365/383 375/426/383 376/395/383 +f 359/366/384 389/427/384 390/397/384 +f 378/399/385 410/428/385 379/401/385 +f 393/402/386 423/429/386 424/430/386 +f 379/401/387 411/431/387 380/403/387 +f 367/405/388 1452/432/388 398/433/388 +f 393/402/389 425/434/389 394/406/389 +f 381/407/390 411/431/390 412/435/390 +f 367/405/391 399/436/391 368/408/391 +f 395/409/392 425/434/392 426/437/392 +f 381/407/393 413/438/393 382/410/393 +f 369/411/394 399/436/394 400/439/394 +f 395/409/395 427/440/395 396/412/395 +f 383/413/396 413/438/396 414/441/396 +f 370/414/397 400/439/397 401/442/397 +f 397/415/398 427/440/398 428/443/398 +f 383/413/399 415/444/399 384/416/399 +f 370/414/400 402/445/400 371/417/400 +f 1887/446/401 397/415/401 428/443/401 +f 385/419/402 415/444/402 416/447/402 +f 371/417/403 403/448/403 372/420/403 +f 385/419/404 417/449/404 386/421/404 +f 372/420/405 404/450/405 373/422/405 +f 387/423/406 417/449/406 418/451/406 +f 373/422/407 405/452/407 374/424/407 +f 388/425/408 418/451/408 419/453/408 +f 374/424/409 406/454/409 375/426/409 +f 389/427/410 419/453/410 420/455/410 +f 375/426/411 407/456/411 376/395/411 +f 389/427/412 421/457/412 390/397/412 +f 377/396/413 407/456/413 408/458/413 +f 391/398/414 421/457/414 422/459/414 +f 377/396/415 409/460/415 378/399/415 +f 392/400/416 422/459/416 423/429/416 +f 412/435/417 442/461/417 443/462/417 +f 398/433/418 430/463/418 399/436/418 +f 425/434/419 457/464/419 426/437/419 +f 412/435/420 444/465/420 413/438/420 +f 399/436/421 431/466/421 400/439/421 +f 426/437/422 458/467/422 427/440/422 +f 414/441/423 444/465/423 445/468/423 +f 401/442/424 431/466/424 432/469/424 +f 427/440/425 459/470/425 428/443/425 +f 414/441/426 446/471/426 415/444/426 +f 402/445/427 432/469/427 433/472/427 +f 1887/473/428 428/443/428 459/470/428 +f 416/447/429 446/471/429 447/474/429 +f 403/448/430 433/472/430 434/475/430 +f 416/447/431 448/476/431 417/449/431 +f 403/448/432 435/477/432 404/450/432 +f 418/451/433 448/476/433 449/478/433 +f 405/452/434 435/477/434 436/479/434 +f 419/453/435 449/478/435 450/480/435 +f 405/452/436 437/481/436 406/454/436 +f 420/455/437 450/480/437 451/482/437 +f 406/454/438 438/483/438 407/456/438 +f 420/455/439 452/484/439 421/457/439 +f 408/458/440 438/483/440 439/485/440 +f 422/459/441 452/484/441 453/486/441 +f 408/458/442 440/487/442 409/460/442 +f 423/429/443 453/486/443 454/488/443 +f 409/460/444 441/489/444 410/428/444 +f 423/429/445 455/490/445 424/430/445 +f 410/428/446 442/461/446 411/431/446 +f 398/433/447 1452/491/447 429/492/447 +f 424/430/448 456/493/448 425/434/448 +f 445/468/449 475/494/449 476/495/449 +f 432/469/450 462/496/450 463/497/450 +f 458/467/451 490/498/451 459/470/451 +f 445/468/452 477/499/452 446/471/452 +f 432/469/453 464/500/453 433/472/453 +f 1887/501/454 459/470/454 490/498/454 +f 447/474/455 477/499/455 478/502/455 +f 433/472/456 465/503/456 434/475/456 +f 447/474/457 479/504/457 448/476/457 +f 434/475/458 466/505/458 435/477/458 +f 449/478/459 479/504/459 480/506/459 +f 435/477/460 467/507/460 436/479/460 +f 450/480/461 480/506/461 481/508/461 +f 437/481/462 467/507/462 468/509/462 +f 450/480/463 482/510/463 451/482/463 +f 437/481/464 469/511/464 438/483/464 +f 451/482/465 483/512/465 452/484/465 +f 439/485/466 469/511/466 470/513/466 +f 453/486/467 483/512/467 484/514/467 +f 439/485/468 471/515/468 440/487/468 +f 453/486/469 485/516/469 454/488/469 +f 440/487/470 472/517/470 441/489/470 +f 455/490/471 485/516/471 486/518/471 +f 441/489/472 473/519/472 442/461/472 +f 429/492/473 1452/520/473 460/521/473 +f 455/490/474 487/522/474 456/493/474 +f 443/462/475 473/519/475 474/523/475 +f 429/492/476 461/524/476 430/463/476 +f 457/464/477 487/522/477 488/525/477 +f 443/462/478 475/494/478 444/465/478 +f 431/466/479 461/524/479 462/496/479 +f 457/464/480 489/526/480 458/467/480 +f 478/502/481 508/527/481 509/528/481 +f 464/500/482 496/529/482 465/503/482 +f 478/502/483 510/530/483 479/504/483 +f 465/503/484 497/531/484 466/505/484 +f 480/506/485 510/530/485 511/532/485 +f 466/505/486 498/533/486 467/507/486 +f 481/508/487 511/532/487 512/534/487 +f 467/507/488 499/535/488 468/509/488 +f 482/510/489 512/534/489 513/536/489 +f 468/509/490 500/537/490 469/511/490 +f 483/512/491 513/536/491 514/538/491 +f 470/513/492 500/537/492 501/539/492 +f 484/514/493 514/538/493 515/540/493 +f 470/513/494 502/541/494 471/515/494 +f 485/516/495 515/540/495 516/542/495 +f 471/515/496 503/543/496 472/517/496 +f 486/518/497 516/542/497 517/544/497 +f 472/517/498 504/545/498 473/519/498 +f 460/521/499 1452/546/499 491/547/499 +f 486/518/500 518/548/500 487/522/500 +f 474/523/501 504/545/501 505/549/501 +f 460/521/502 492/550/502 461/524/502 +f 488/525/503 518/548/503 519/551/503 +f 474/523/504 506/552/504 475/494/504 +f 461/524/505 493/553/505 462/496/505 +f 489/526/506 519/551/506 520/554/506 +f 476/495/507 506/552/507 507/555/507 +f 463/497/508 493/553/508 494/556/508 +f 490/498/509 520/554/509 521/557/509 +f 476/495/510 508/527/510 477/499/510 +f 463/497/511 495/558/511 464/500/511 +f 1887/559/512 490/498/512 521/557/512 +f 511/532/513 541/560/513 542/561/513 +f 497/531/514 529/562/514 498/533/514 +f 512/534/515 542/561/515 543/563/515 +f 498/533/516 530/564/516 499/535/516 +f 512/534/517 544/565/517 513/536/517 +f 499/535/518 531/566/518 500/537/518 +f 513/536/519 545/567/519 514/538/519 +f 501/539/520 531/566/520 532/568/520 +f 515/540/521 545/567/521 546/569/521 +f 501/539/522 533/570/522 502/541/522 +f 516/542/523 546/569/523 547/571/523 +f 502/541/524 534/572/524 503/543/524 +f 516/542/525 548/573/525 517/544/525 +f 503/543/526 535/574/526 504/545/526 +f 491/547/527 1452/575/527 522/576/527 +f 517/544/528 549/577/528 518/548/528 +f 505/549/529 535/574/529 536/578/529 +f 491/547/530 523/579/530 492/550/530 +f 519/551/531 549/577/531 550/580/531 +f 505/549/532 537/581/532 506/552/532 +f 492/550/533 524/582/533 493/553/533 +f 519/551/534 551/583/534 520/554/534 +f 507/555/535 537/581/535 538/584/535 +f 493/553/536 525/585/536 494/556/536 +f 520/554/537 552/586/537 521/557/537 +f 507/555/538 539/587/538 508/527/538 +f 494/556/539 526/588/539 495/558/539 +f 1887/589/540 521/557/540 552/586/540 +f 509/528/541 539/587/541 540/590/541 +f 495/558/542 527/591/542 496/529/542 +f 509/528/543 541/560/543 510/530/543 +f 496/529/544 528/592/544 497/531/544 +f 544/565/545 574/593/545 575/594/545 +f 530/564/546 562/595/546 531/566/546 +f 545/567/547 575/594/547 576/596/547 +f 532/568/548 562/595/548 563/597/548 +f 545/567/549 577/598/549 546/569/549 +f 532/568/550 564/599/550 533/570/550 +f 547/571/551 577/598/551 578/600/551 +f 533/570/552 565/601/552 534/572/552 +f 548/573/553 578/600/553 579/602/553 +f 534/572/554 566/603/554 535/574/554 +f 522/576/555 1452/604/555 553/605/555 +f 548/573/556 580/606/556 549/577/556 +f 536/578/557 566/603/557 567/607/557 +f 522/576/558 554/608/558 523/579/558 +f 550/580/559 580/606/559 581/609/559 +f 536/578/560 568/610/560 537/581/560 +f 523/579/561 555/611/561 524/582/561 +f 551/583/562 581/609/562 582/612/562 +f 538/584/563 568/610/563 569/613/563 +f 524/582/564 556/614/564 525/585/564 +f 552/586/565 582/612/565 583/615/565 +f 538/584/566 570/616/566 539/587/566 +f 525/585/567 557/617/567 526/588/567 +f 1887/618/568 552/586/568 583/615/568 +f 540/590/569 570/616/569 571/619/569 +f 526/588/570 558/620/570 527/591/570 +f 540/590/571 572/621/571 541/560/571 +f 527/591/572 559/622/572 528/592/572 +f 542/561/573 572/621/573 573/623/573 +f 528/592/574 560/624/574 529/562/574 +f 543/563/575 573/623/575 574/593/575 +f 529/562/576 561/625/576 530/564/576 +f 576/596/577 608/626/577 577/598/577 +f 563/597/578 595/627/578 564/599/578 +f 578/600/579 608/626/579 609/628/579 +f 564/599/580 596/629/580 565/601/580 +f 579/602/581 609/628/581 610/630/581 +f 565/601/582 597/631/582 566/603/582 +f 553/605/583 1452/632/583 584/633/583 +f 579/602/584 611/634/584 580/606/584 +f 567/607/585 597/631/585 598/635/585 +f 553/605/586 585/636/586 554/608/586 +f 580/606/587 612/637/587 581/609/587 +f 567/607/588 599/638/588 568/610/588 +f 554/608/589 586/639/589 555/611/589 +f 581/609/590 613/640/590 582/612/590 +f 569/613/591 599/638/591 600/641/591 +f 556/614/592 586/639/592 587/642/592 +f 582/612/593 614/643/593 583/615/593 +f 569/613/594 601/644/594 570/616/594 +f 556/614/595 588/645/595 557/617/595 +f 1887/646/596 583/615/596 614/643/596 +f 571/619/597 601/644/597 602/647/597 +f 558/620/598 588/645/598 589/648/598 +f 571/619/599 603/649/599 572/621/599 +f 558/620/600 590/650/600 559/622/600 +f 573/623/601 603/649/601 604/651/601 +f 559/622/602 591/652/602 560/624/602 +f 574/593/603 604/651/603 605/653/603 +f 561/625/604 591/652/604 592/654/604 +f 574/593/605 606/655/605 575/594/605 +f 561/625/606 593/656/606 562/595/606 +f 575/594/607 607/657/607 576/596/607 +f 563/597/608 593/656/608 594/658/608 +f 610/630/609 640/659/609 641/660/609 +f 596/629/610 628/661/610 597/631/610 +f 584/633/611 1452/662/611 615/663/611 +f 610/630/612 642/664/612 611/634/612 +f 598/635/613 628/661/613 629/665/613 +f 584/633/614 616/666/614 585/636/614 +f 611/634/615 643/667/615 612/637/615 +f 598/635/616 630/668/616 599/638/616 +f 585/636/617 617/669/617 586/639/617 +f 612/637/618 644/670/618 613/640/618 +f 600/641/619 630/668/619 631/671/619 +f 586/639/620 618/672/620 587/642/620 +f 614/643/621 644/670/621 645/673/621 +f 600/641/622 632/674/622 601/644/622 +f 587/642/623 619/675/623 588/645/623 +f 1887/676/624 614/643/624 645/673/624 +f 602/647/625 632/674/625 633/677/625 +f 589/648/626 619/675/626 620/678/626 +f 602/647/627 634/679/627 603/649/627 +f 589/648/628 621/680/628 590/650/628 +f 604/651/629 634/679/629 635/681/629 +f 590/650/630 622/682/630 591/652/630 +f 605/653/631 635/681/631 636/683/631 +f 591/652/632 623/684/632 592/654/632 +f 606/655/633 636/683/633 637/685/633 +f 592/654/634 624/686/634 593/656/634 +f 606/655/635 638/687/635 607/657/635 +f 594/658/636 624/686/636 625/688/636 +f 607/657/637 639/689/637 608/626/637 +f 594/658/638 626/690/638 595/627/638 +f 608/626/639 640/659/639 609/628/639 +f 595/627/640 627/691/640 596/629/640 +f 642/664/641 674/692/641 643/667/641 +f 629/665/642 661/693/642 630/668/642 +f 616/666/643 648/694/643 617/669/643 +f 643/667/644 675/695/644 644/670/644 +f 631/671/645 661/693/645 662/696/645 +f 618/672/646 648/694/646 649/697/646 +f 644/670/647 676/698/647 645/673/647 +f 631/671/648 663/699/648 632/674/648 +f 619/675/649 649/697/649 650/700/649 +f 1887/701/650 645/673/650 676/698/650 +f 633/677/651 663/699/651 664/702/651 +f 620/678/652 650/700/652 651/703/652 +f 633/677/653 665/704/653 634/679/653 +f 620/678/654 652/705/654 621/680/654 +f 635/681/655 665/704/655 666/706/655 +f 621/680/656 653/707/656 622/682/656 +f 636/683/657 666/706/657 667/708/657 +f 622/682/658 654/709/658 623/684/658 +f 636/683/659 668/710/659 637/685/659 +f 623/684/660 655/711/660 624/686/660 +f 638/687/661 668/710/661 669/712/661 +f 625/688/662 655/711/662 656/713/662 +f 639/689/663 669/712/663 670/714/663 +f 625/688/664 657/715/664 626/690/664 +f 640/659/665 670/714/665 671/716/665 +f 626/690/666 658/717/666 627/691/666 +f 640/659/667 672/718/667 641/660/667 +f 627/691/668 659/719/668 628/661/668 +f 615/663/669 1452/720/669 646/721/669 +f 641/660/670 673/722/670 642/664/670 +f 629/665/671 659/719/671 660/723/671 +f 616/666/672 646/721/672 647/724/672 +f 675/695/673 707/725/673 676/698/673 +f 662/696/674 694/726/674 663/699/674 +f 649/697/675 681/727/675 650/700/675 +f 1887/728/676 676/698/676 707/725/676 +f 664/702/677 694/726/677 695/729/677 +f 651/703/678 681/727/678 682/730/678 +f 664/702/679 696/731/679 665/704/679 +f 652/705/680 682/730/680 683/732/680 +f 666/706/681 696/731/681 697/733/681 +f 652/705/682 684/734/682 653/707/682 +f 667/708/683 697/733/683 698/735/683 +f 653/707/684 685/736/684 654/709/684 +f 667/708/685 699/737/685 668/710/685 +f 655/711/686 685/736/686 686/738/686 +f 668/710/687 700/739/687 669/712/687 +f 655/711/688 687/740/688 656/713/688 +f 669/712/689 701/741/689 670/714/689 +f 656/713/690 688/742/690 657/715/690 +f 671/716/691 701/741/691 702/743/691 +f 657/715/692 689/744/692 658/717/692 +f 671/716/693 703/745/693 672/718/693 +f 658/717/694 690/746/694 659/719/694 +f 646/721/695 1452/747/695 677/748/695 +f 672/718/696 704/749/696 673/722/696 +f 660/723/697 690/746/697 691/750/697 +f 646/721/698 678/751/698 647/724/698 +f 674/692/699 704/749/699 705/752/699 +f 660/723/700 692/753/700 661/693/700 +f 648/694/701 678/751/701 679/754/701 +f 674/692/702 706/755/702 675/695/702 +f 662/696/703 692/753/703 693/756/703 +f 648/694/704 680/757/704 649/697/704 +f 695/729/705 727/758/705 696/731/705 +f 682/730/706 714/759/706 683/732/706 +f 697/733/707 727/758/707 728/760/707 +f 683/732/708 715/761/708 684/734/708 +f 698/735/709 728/760/709 729/762/709 +f 684/734/710 716/763/710 685/736/710 +f 698/735/711 730/764/711 699/737/711 +f 686/738/712 716/763/712 717/765/712 +f 700/739/713 730/764/713 731/766/713 +f 687/740/714 717/765/714 718/767/714 +f 700/739/715 732/768/715 701/741/715 +f 687/740/716 719/769/716 688/742/716 +f 701/741/717 733/770/717 702/743/717 +f 689/744/718 719/769/718 720/771/718 +f 702/743/719 734/772/719 703/745/719 +f 689/744/720 721/773/720 690/746/720 +f 677/748/721 1452/774/721 708/775/721 +f 703/745/722 735/776/722 704/749/722 +f 691/750/723 721/773/723 722/777/723 +f 677/748/724 709/778/724 678/751/724 +f 705/752/725 735/776/725 736/779/725 +f 691/750/726 723/780/726 692/753/726 +f 678/751/727 710/781/727 679/754/727 +f 705/752/728 737/782/728 706/755/728 +f 693/756/729 723/780/729 724/783/729 +f 680/757/730 710/781/730 711/784/730 +f 706/755/731 738/785/731 707/725/731 +f 693/756/732 725/786/732 694/726/732 +f 680/757/733 712/787/733 681/727/733 +f 1887/788/734 707/725/734 738/785/734 +f 695/729/735 725/786/735 726/789/735 +f 682/730/736 712/787/736 713/790/736 +f 729/762/737 759/791/737 760/792/737 +f 715/761/738 747/793/738 716/763/738 +f 729/762/739 761/794/739 730/764/739 +f 716/763/740 748/795/740 717/765/740 +f 730/764/741 762/796/741 731/766/741 +f 718/767/742 748/795/742 749/797/742 +f 731/766/743 763/798/743 732/768/743 +f 718/767/744 750/799/744 719/769/744 +f 733/770/745 763/798/745 764/800/745 +f 720/771/746 750/799/746 751/801/746 +f 734/772/747 764/800/747 765/802/747 +f 720/771/748 752/803/748 721/773/748 +f 708/775/749 1452/804/749 739/805/749 +f 734/772/750 766/806/750 735/776/750 +f 722/777/751 752/803/751 753/807/751 +f 708/775/752 740/808/752 709/778/752 +f 736/779/753 766/806/753 767/809/753 +f 722/777/754 754/810/754 723/780/754 +f 709/778/755 741/811/755 710/781/755 +f 737/782/756 767/809/756 768/812/756 +f 724/783/757 754/810/757 755/813/757 +f 710/781/758 742/814/758 711/784/758 +f 737/782/759 769/815/759 738/785/759 +f 724/783/760 756/816/760 725/786/760 +f 711/784/761 743/817/761 712/787/761 +f 1887/818/762 738/785/762 769/815/762 +f 726/789/763 756/816/763 757/819/763 +f 713/790/764 743/817/764 744/820/764 +f 726/789/765 758/821/765 727/758/765 +f 713/790/766 745/822/766 714/759/766 +f 728/760/767 758/821/767 759/791/767 +f 715/761/768 745/822/768 746/823/768 +f 761/794/769 793/824/769 762/796/769 +f 748/795/770 780/825/770 749/797/770 +f 762/796/771 794/826/771 763/798/771 +f 749/797/772 781/827/772 750/799/772 +f 763/798/773 795/828/773 764/800/773 +f 751/801/774 781/827/774 782/829/774 +f 765/802/775 795/828/775 796/830/775 +f 751/801/776 783/831/776 752/803/776 +f 739/805/777 1452/832/777 770/833/777 +f 765/802/778 797/834/778 766/806/778 +f 753/807/779 783/831/779 784/835/779 +f 739/805/780 771/836/780 740/808/780 +f 767/809/781 797/834/781 798/837/781 +f 753/807/782 785/838/782 754/810/782 +f 740/808/783 772/839/783 741/811/783 +f 768/812/784 798/837/784 799/840/784 +f 754/810/785 786/841/785 755/813/785 +f 742/814/786 772/839/786 773/842/786 +f 768/812/787 800/843/787 769/815/787 +f 755/813/788 787/844/788 756/816/788 +f 742/814/789 774/845/789 743/817/789 +f 1887/846/790 769/815/790 800/843/790 +f 757/819/791 787/844/791 788/847/791 +f 743/817/792 775/848/792 744/820/792 +f 757/819/793 789/849/793 758/821/793 +f 744/820/794 776/850/794 745/822/794 +f 759/791/795 789/849/795 790/851/795 +f 746/823/796 776/850/796 777/852/796 +f 760/792/797 790/851/797 791/853/797 +f 746/823/798 778/854/798 747/793/798 +f 760/792/799 792/855/799 761/794/799 +f 748/795/800 778/854/800 779/856/800 +f 794/826/801 826/857/801 795/828/801 +f 782/829/802 812/858/802 813/859/802 +f 796/830/803 826/857/803 827/860/803 +f 782/829/804 814/861/804 783/831/804 +f 770/833/805 1452/862/805 801/863/805 +f 796/830/806 828/864/806 797/834/806 +f 784/835/807 814/861/807 815/865/807 +f 770/833/808 802/866/808 771/836/808 +f 798/837/809 828/864/809 829/867/809 +f 785/838/810 815/865/810 816/868/810 +f 771/836/811 803/869/811 772/839/811 +f 798/837/812 830/870/812 799/840/812 +f 785/838/813 817/871/813 786/841/813 +f 772/839/814 804/872/814 773/842/814 +f 799/840/815 831/873/815 800/843/815 +f 786/841/816 818/874/816 787/844/816 +f 773/842/817 805/875/817 774/845/817 +f 1887/876/818 800/843/818 831/873/818 +f 788/847/819 818/874/819 819/877/819 +f 774/845/820 806/878/820 775/848/820 +f 788/847/821 820/879/821 789/849/821 +f 776/850/822 806/878/822 807/880/822 +f 790/851/823 820/879/823 821/881/823 +f 777/852/824 807/880/824 808/882/824 +f 791/853/825 821/881/825 822/883/825 +f 777/852/826 809/884/826 778/854/826 +f 791/853/827 823/885/827 792/855/827 +f 779/856/828 809/884/828 810/886/828 +f 792/855/829 824/887/829 793/824/829 +f 780/825/830 810/886/830 811/888/830 +f 793/824/831 825/889/831 794/826/831 +f 780/825/832 812/858/832 781/827/832 +f 824/887/833 856/890/833 825/889/833 +f 811/888/834 843/891/834 812/858/834 +f 825/889/835 857/892/835 826/857/835 +f 813/859/836 843/891/836 844/893/836 +f 826/857/837 858/894/837 827/860/837 +f 813/859/838 845/895/838 814/861/838 +f 801/863/839 1452/896/839 832/897/839 +f 827/860/840 859/898/840 828/864/840 +f 815/865/841 845/895/841 846/899/841 +f 801/863/842 833/900/842 802/866/842 +f 829/867/843 859/898/843 860/901/843 +f 816/868/844 846/899/844 847/902/844 +f 802/866/845 834/903/845 803/869/845 +f 830/870/846 860/901/846 861/904/846 +f 816/868/847 848/905/847 817/871/847 +f 804/872/848 834/903/848 835/906/848 +f 831/873/849 861/904/849 862/907/849 +f 817/871/850 849/908/850 818/874/850 +f 805/875/851 835/906/851 836/909/851 +f 1887/910/852 831/873/852 862/907/852 +f 819/877/853 849/908/853 850/911/853 +f 805/875/854 837/912/854 806/878/854 +f 819/877/855 851/913/855 820/879/855 +f 806/878/856 838/914/856 807/880/856 +f 821/881/857 851/913/857 852/915/857 +f 807/880/858 839/916/858 808/882/858 +f 822/883/859 852/915/859 853/917/859 +f 808/882/860 840/918/860 809/884/860 +f 822/883/861 854/919/861 823/885/861 +f 809/884/862 841/920/862 810/886/862 +f 823/885/863 855/921/863 824/887/863 +f 811/888/864 841/920/864 842/922/864 +f 858/894/865 888/923/865 889/924/865 +f 844/893/866 876/925/866 845/895/866 +f 832/897/867 1452/926/867 863/927/867 +f 858/894/868 890/928/868 859/898/868 +f 846/899/869 876/925/869 877/929/869 +f 832/897/870 864/930/870 833/900/870 +f 860/901/871 890/928/871 891/931/871 +f 847/902/872 877/929/872 878/932/872 +f 833/900/873 865/933/873 834/903/873 +f 860/901/874 892/934/874 861/904/874 +f 847/902/875 879/935/875 848/905/875 +f 835/906/876 865/933/876 866/936/876 +f 861/904/877 893/937/877 862/907/877 +f 848/905/878 880/938/878 849/908/878 +f 835/906/879 867/939/879 836/909/879 +f 1887/940/880 862/907/880 893/937/880 +f 850/911/881 880/938/881 881/941/881 +f 837/912/882 867/939/882 868/942/882 +f 850/911/883 882/943/883 851/913/883 +f 837/912/884 869/944/884 838/914/884 +f 852/915/885 882/943/885 883/945/885 +f 838/914/886 870/946/886 839/916/886 +f 853/917/887 883/945/887 884/947/887 +f 840/918/888 870/946/888 871/948/888 +f 853/917/889 885/949/889 854/919/889 +f 840/918/890 872/950/890 841/920/890 +f 854/919/891 886/951/891 855/921/891 +f 842/922/892 872/950/892 873/952/892 +f 855/921/893 887/953/893 856/890/893 +f 842/922/894 874/954/894 843/891/894 +f 857/892/895 887/953/895 888/923/895 +f 844/893/896 874/954/896 875/955/896 +f 863/927/897 895/956/897 864/930/897 +f 890/928/898 922/957/898 891/931/898 +f 878/932/899 908/958/899 909/959/899 +f 864/930/900 896/960/900 865/933/900 +f 891/931/901 923/961/901 892/934/901 +f 878/932/902 910/962/902 879/935/902 +f 866/936/903 896/960/903 897/963/903 +f 892/934/904 924/964/904 893/937/904 +f 879/935/905 911/965/905 880/938/905 +f 866/936/906 898/966/906 867/939/906 +f 1887/967/907 893/937/907 924/964/907 +f 881/941/908 911/965/908 912/968/908 +f 867/939/909 899/969/909 868/942/909 +f 881/941/910 913/970/910 882/943/910 +f 868/942/911 900/971/911 869/944/911 +f 883/945/912 913/970/912 914/972/912 +f 869/944/913 901/973/913 870/946/913 +f 884/947/914 914/972/914 915/974/914 +f 870/946/915 902/975/915 871/948/915 +f 884/947/916 916/976/916 885/949/916 +f 871/948/917 903/977/917 872/950/917 +f 886/951/918 916/976/918 917/978/918 +f 873/952/919 903/977/919 904/979/919 +f 886/951/920 918/980/920 887/953/920 +f 873/952/921 905/981/921 874/954/921 +f 888/923/922 918/980/922 919/982/922 +f 875/955/923 905/981/923 906/983/923 +f 889/924/924 919/982/924 920/984/924 +f 875/955/925 907/985/925 876/925/925 +f 863/927/926 1452/986/926 894/987/926 +f 890/928/927 920/984/927 921/988/927 +f 877/929/928 907/985/928 908/958/928 +f 897/963/929 927/989/929 928/990/929 +f 923/961/930 955/991/930 924/964/930 +f 910/962/931 942/992/931 911/965/931 +f 897/963/932 929/993/932 898/966/932 +f 1887/994/933 924/964/933 955/991/933 +f 912/968/934 942/992/934 943/995/934 +f 898/966/935 930/996/935 899/969/935 +f 912/968/936 944/997/936 913/970/936 +f 899/969/937 931/998/937 900/971/937 +f 914/972/938 944/997/938 945/999/938 +f 901/973/939 931/998/939 932/1000/939 +f 915/974/940 945/999/940 946/1001/940 +f 902/975/941 932/1000/941 933/1002/941 +f 916/976/942 946/1001/942 947/1003/942 +f 902/975/943 934/1004/943 903/977/943 +f 916/976/944 948/1005/944 917/978/944 +f 904/979/945 934/1004/945 935/1006/945 +f 917/978/946 949/1007/946 918/980/946 +f 904/979/947 936/1008/947 905/981/947 +f 919/982/948 949/1007/948 950/1009/948 +f 906/983/949 936/1008/949 937/1010/949 +f 920/984/950 950/1009/950 951/1011/950 +f 906/983/951 938/1012/951 907/985/951 +f 894/987/952 1452/1013/952 925/1014/952 +f 920/984/953 952/1015/953 921/988/953 +f 908/958/954 938/1012/954 939/1016/954 +f 895/956/955 925/1014/955 926/1017/955 +f 921/988/956 953/1018/956 922/957/956 +f 909/959/957 939/1016/957 940/1019/957 +f 895/956/958 927/989/958 896/960/958 +f 923/961/959 953/1018/959 954/1020/959 +f 909/959/960 941/1021/960 910/962/960 +f 929/993/961 961/1022/961 930/996/961 +f 943/995/962 975/1023/962 944/997/962 +f 931/998/963 961/1022/963 962/1024/963 +f 945/999/964 975/1023/964 976/1025/964 +f 932/1000/965 962/1024/965 963/1026/965 +f 946/1001/966 976/1025/966 977/1027/966 +f 932/1000/967 964/1028/967 933/1002/967 +f 947/1003/968 977/1027/968 978/1029/968 +f 933/1002/969 965/1030/969 934/1004/969 +f 947/1003/970 979/1031/970 948/1005/970 +f 935/1006/971 965/1030/971 966/1032/971 +f 948/1005/972 980/1033/972 949/1007/972 +f 935/1006/973 967/1034/973 936/1008/973 +f 950/1009/974 980/1033/974 981/1035/974 +f 937/1010/975 967/1034/975 968/1036/975 +f 951/1011/976 981/1035/976 982/1037/976 +f 937/1010/977 969/1038/977 938/1012/977 +f 925/1014/978 1452/1039/978 956/1040/978 +f 951/1011/979 983/1041/979 952/1015/979 +f 939/1016/980 969/1038/980 970/1042/980 +f 925/1014/981 957/1043/981 926/1017/981 +f 952/1015/982 984/1044/982 953/1018/982 +f 940/1019/983 970/1042/983 971/1045/983 +f 926/1017/984 958/1046/984 927/989/984 +f 953/1018/985 985/1047/985 954/1020/985 +f 940/1019/986 972/1048/986 941/1021/986 +f 928/990/987 958/1046/987 959/1049/987 +f 954/1020/988 986/1050/988 955/991/988 +f 941/1021/989 973/1051/989 942/992/989 +f 928/990/990 960/1052/990 929/993/990 +f 1887/1053/991 955/991/991 986/1050/991 +f 943/995/992 973/1051/992 974/1054/992 +f 962/1024/993 994/1055/993 963/1026/993 +f 977/1027/994 1007/1056/994 1008/1057/994 +f 963/1026/995 995/1058/995 964/1028/995 +f 978/1029/996 1008/1057/996 1009/1059/996 +f 964/1028/997 996/1060/997 965/1030/997 +f 979/1031/998 1009/1059/998 1010/1061/998 +f 966/1032/999 996/1060/999 997/1062/999 +f 979/1031/1000 1011/1063/1000 980/1033/1000 +f 966/1032/1001 998/1064/1001 967/1034/1001 +f 981/1035/1002 1011/1063/1002 1012/1065/1002 +f 968/1036/1003 998/1064/1003 999/1066/1003 +f 981/1035/1004 1013/1067/1004 982/1037/1004 +f 968/1036/1005 1000/1068/1005 969/1038/1005 +f 956/1040/1006 1452/1069/1006 987/1070/1006 +f 982/1037/1007 1014/1071/1007 983/1041/1007 +f 970/1042/1008 1000/1068/1008 1001/1072/1008 +f 956/1040/1009 988/1073/1009 957/1043/1009 +f 983/1041/1010 1015/1074/1010 984/1044/1010 +f 971/1045/1011 1001/1072/1011 1002/1075/1011 +f 957/1043/1012 989/1076/1012 958/1046/1012 +f 985/1047/1013 1015/1074/1013 1016/1077/1013 +f 971/1045/1014 1003/1078/1014 972/1048/1014 +f 959/1049/1015 989/1076/1015 990/1079/1015 +f 985/1047/1016 1017/1080/1016 986/1050/1016 +f 972/1048/1017 1004/1081/1017 973/1051/1017 +f 959/1049/1018 991/1082/1018 960/1052/1018 +f 1887/1083/1019 986/1050/1019 1017/1080/1019 +f 974/1054/1020 1004/1081/1020 1005/1084/1020 +f 960/1052/1021 992/1085/1021 961/1022/1021 +f 974/1054/1022 1006/1086/1022 975/1023/1022 +f 962/1024/1023 992/1085/1023 993/1087/1023 +f 976/1025/1024 1006/1086/1024 1007/1056/1024 +f 995/1058/1025 1027/1088/1025 996/1060/1025 +f 1009/1059/1026 1041/1089/1026 1010/1061/1026 +f 997/1062/1027 1027/1088/1027 1028/1090/1027 +f 1010/1061/1028 1042/1091/1028 1011/1063/1028 +f 997/1062/1029 1029/1092/1029 998/1064/1029 +f 1012/1065/1030 1042/1091/1030 1043/1093/1030 +f 999/1066/1031 1029/1092/1031 1030/1094/1031 +f 1013/1067/1032 1043/1093/1032 1044/1095/1032 +f 999/1066/1033 1031/1096/1033 1000/1068/1033 +f 987/1070/1034 1452/1097/1034 1018/1098/1034 +f 1013/1067/1035 1045/1099/1035 1014/1071/1035 +f 1001/1072/1036 1031/1096/1036 1032/1100/1036 +f 987/1070/1037 1019/1101/1037 988/1073/1037 +f 1015/1074/1038 1045/1099/1038 1046/1102/1038 +f 1002/1075/1039 1032/1100/1039 1033/1103/1039 +f 988/1073/1040 1020/1104/1040 989/1076/1040 +f 1016/1077/1041 1046/1102/1041 1047/1105/1041 +f 1002/1075/1042 1034/1106/1042 1003/1078/1042 +f 989/1076/1043 1021/1107/1043 990/1079/1043 +f 1016/1077/1044 1048/1108/1044 1017/1080/1044 +f 1003/1078/1045 1035/1109/1045 1004/1081/1045 +f 990/1079/1046 1022/1110/1046 991/1082/1046 +f 1887/1111/1047 1017/1080/1047 1048/1108/1047 +f 1005/1084/1048 1035/1109/1048 1036/1112/1048 +f 991/1082/1049 1023/1113/1049 992/1085/1049 +f 1005/1084/1050 1037/1114/1050 1006/1086/1050 +f 993/1087/1051 1023/1113/1051 1024/1115/1051 +f 1007/1056/1052 1037/1114/1052 1038/1116/1052 +f 993/1087/1053 1025/1117/1053 994/1055/1053 +f 1008/1057/1054 1038/1116/1054 1039/1118/1054 +f 994/1055/1055 1026/1119/1055 995/1058/1055 +f 1009/1059/1056 1039/1118/1056 1040/1120/1056 +f 1028/1090/1057 1060/1121/1057 1029/1092/1057 +f 1043/1093/1058 1073/1122/1058 1074/1123/1058 +f 1030/1094/1059 1060/1121/1059 1061/1124/1059 +f 1043/1093/1060 1075/1125/1060 1044/1095/1060 +f 1030/1094/1061 1062/1126/1061 1031/1096/1061 +f 1018/1098/1062 1452/1127/1062 1049/1128/1062 +f 1044/1095/1063 1076/1129/1063 1045/1099/1063 +f 1032/1100/1064 1062/1126/1064 1063/1130/1064 +f 1018/1098/1065 1050/1131/1065 1019/1101/1065 +f 1046/1102/1066 1076/1129/1066 1077/1132/1066 +f 1033/1103/1067 1063/1130/1067 1064/1133/1067 +f 1019/1101/1068 1051/1134/1068 1020/1104/1068 +f 1046/1102/1069 1078/1135/1069 1047/1105/1069 +f 1033/1103/1070 1065/1136/1070 1034/1106/1070 +f 1021/1107/1071 1051/1134/1071 1052/1137/1071 +f 1048/1108/1072 1078/1135/1072 1079/1138/1072 +f 1034/1106/1073 1066/1139/1073 1035/1109/1073 +f 1021/1107/1074 1053/1140/1074 1022/1110/1074 +f 1887/1141/1075 1048/1108/1075 1079/1138/1075 +f 1036/1112/1076 1066/1139/1076 1067/1142/1076 +f 1022/1110/1077 1054/1143/1077 1023/1113/1077 +f 1036/1112/1078 1068/1144/1078 1037/1114/1078 +f 1024/1115/1079 1054/1143/1079 1055/1145/1079 +f 1038/1116/1080 1068/1144/1080 1069/1146/1080 +f 1024/1115/1081 1056/1147/1081 1025/1117/1081 +f 1039/1118/1082 1069/1146/1082 1070/1148/1082 +f 1025/1117/1083 1057/1149/1083 1026/1119/1083 +f 1040/1120/1084 1070/1148/1084 1071/1150/1084 +f 1026/1119/1085 1058/1151/1085 1027/1088/1085 +f 1040/1120/1086 1072/1152/1086 1041/1089/1086 +f 1028/1090/1087 1058/1151/1087 1059/1153/1087 +f 1041/1089/1088 1073/1122/1088 1042/1091/1088 +f 1061/1124/1089 1093/1154/1089 1062/1126/1089 +f 1049/1128/1090 1452/1155/1090 1080/1156/1090 +f 1075/1125/1091 1107/1157/1091 1076/1129/1091 +f 1063/1130/1092 1093/1154/1092 1094/1158/1092 +f 1049/1128/1093 1081/1159/1093 1050/1131/1093 +f 1077/1132/1094 1107/1157/1094 1108/1160/1094 +f 1064/1133/1095 1094/1158/1095 1095/1161/1095 +f 1050/1131/1096 1082/1162/1096 1051/1134/1096 +f 1078/1135/1097 1108/1160/1097 1109/1163/1097 +f 1064/1133/1098 1096/1164/1098 1065/1136/1098 +f 1052/1137/1099 1082/1162/1099 1083/1165/1099 +f 1078/1135/1100 1110/1166/1100 1079/1138/1100 +f 1065/1136/1101 1097/1167/1101 1066/1139/1101 +f 1052/1137/1102 1084/1168/1102 1053/1140/1102 +f 1887/1169/1103 1079/1138/1103 1110/1166/1103 +f 1067/1142/1104 1097/1167/1104 1098/1170/1104 +f 1053/1140/1105 1085/1171/1105 1054/1143/1105 +f 1067/1142/1106 1099/1172/1106 1068/1144/1106 +f 1055/1145/1107 1085/1171/1107 1086/1173/1107 +f 1069/1146/1108 1099/1172/1108 1100/1174/1108 +f 1056/1147/1109 1086/1173/1109 1087/1175/1109 +f 1070/1148/1110 1100/1174/1110 1101/1176/1110 +f 1056/1147/1111 1088/1177/1111 1057/1149/1111 +f 1070/1148/1112 1102/1178/1112 1071/1150/1112 +f 1057/1149/1113 1089/1179/1113 1058/1151/1113 +f 1071/1150/1114 1103/1180/1114 1072/1152/1114 +f 1059/1153/1115 1089/1179/1115 1090/1181/1115 +f 1072/1152/1116 1104/1182/1116 1073/1122/1116 +f 1059/1153/1117 1091/1183/1117 1060/1121/1117 +f 1074/1123/1118 1104/1182/1118 1105/1184/1118 +f 1061/1124/1119 1091/1183/1119 1092/1185/1119 +f 1075/1125/1120 1105/1184/1120 1106/1186/1120 +f 1095/1161/1121 1125/1187/1121 1126/1188/1121 +f 1081/1159/1122 1113/1189/1122 1082/1162/1122 +f 1109/1163/1123 1139/1190/1123 1140/1191/1123 +f 1095/1161/1124 1127/1192/1124 1096/1164/1124 +f 1083/1165/1125 1113/1189/1125 1114/1193/1125 +f 1109/1163/1126 1141/1194/1126 1110/1166/1126 +f 1096/1164/1127 1128/1195/1127 1097/1167/1127 +f 1083/1165/1128 1115/1196/1128 1084/1168/1128 +f 1887/1197/1129 1110/1166/1129 1141/1194/1129 +f 1098/1170/1130 1128/1195/1130 1129/1198/1130 +f 1084/1168/1131 1116/1199/1131 1085/1171/1131 +f 1098/1170/1132 1130/1200/1132 1099/1172/1132 +f 1086/1173/1133 1116/1199/1133 1117/1201/1133 +f 1100/1174/1134 1130/1200/1134 1131/1202/1134 +f 1086/1173/1135 1118/1203/1135 1087/1175/1135 +f 1101/1176/1136 1131/1202/1136 1132/1204/1136 +f 1087/1175/1137 1119/1205/1137 1088/1177/1137 +f 1102/1178/1138 1132/1204/1138 1133/1206/1138 +f 1088/1177/1139 1120/1207/1139 1089/1179/1139 +f 1102/1178/1140 1134/1208/1140 1103/1180/1140 +f 1090/1181/1141 1120/1207/1141 1121/1209/1141 +f 1103/1180/1142 1135/1210/1142 1104/1182/1142 +f 1090/1181/1143 1122/1211/1143 1091/1183/1143 +f 1105/1184/1144 1135/1210/1144 1136/1212/1144 +f 1092/1185/1145 1122/1211/1145 1123/1213/1145 +f 1105/1184/1146 1137/1214/1146 1106/1186/1146 +f 1092/1185/1147 1124/1215/1147 1093/1154/1147 +f 1080/1156/1148 1452/1216/1148 1111/1217/1148 +f 1106/1186/1149 1138/1218/1149 1107/1157/1149 +f 1094/1158/1150 1124/1215/1150 1125/1187/1150 +f 1080/1156/1151 1112/1219/1151 1081/1159/1151 +f 1108/1160/1152 1138/1218/1152 1139/1190/1152 +f 1127/1192/1153 1159/1220/1153 1128/1195/1153 +f 1114/1193/1154 1146/1221/1154 1115/1196/1154 +f 1887/1222/1155 1141/1194/1155 1172/1223/1155 +f 1129/1198/1156 1159/1220/1156 1160/1224/1156 +f 1115/1196/1157 1147/1225/1157 1116/1199/1157 +f 1129/1198/1158 1161/1226/1158 1130/1200/1158 +f 1116/1199/1159 1148/1227/1159 1117/1201/1159 +f 1131/1202/1160 1161/1226/1160 1162/1228/1160 +f 1117/1201/1161 1149/1229/1161 1118/1203/1161 +f 1132/1204/1162 1162/1228/1162 1163/1230/1162 +f 1118/1203/1163 1150/1231/1163 1119/1205/1163 +f 1133/1206/1164 1163/1230/1164 1164/1232/1164 +f 1119/1205/1165 1151/1233/1165 1120/1207/1165 +f 1134/1208/1166 1164/1232/1166 1165/1234/1166 +f 1121/1209/1167 1151/1233/1167 1152/1235/1167 +f 1134/1208/1168 1166/1236/1168 1135/1210/1168 +f 1121/1209/1169 1153/1237/1169 1122/1211/1169 +f 1136/1212/1170 1166/1236/1170 1167/1238/1170 +f 1123/1213/1171 1153/1237/1171 1154/1239/1171 +f 1137/1214/1172 1167/1238/1172 1168/1240/1172 +f 1123/1213/1173 1155/1241/1173 1124/1215/1173 +f 1111/1217/1174 1452/1242/1174 1142/1243/1174 +f 1137/1214/1175 1169/1244/1175 1138/1218/1175 +f 1125/1187/1176 1155/1241/1176 1156/1245/1176 +f 1111/1217/1177 1143/1246/1177 1112/1219/1177 +f 1139/1190/1178 1169/1244/1178 1170/1247/1178 +f 1126/1188/1179 1156/1245/1179 1157/1248/1179 +f 1112/1219/1180 1144/1249/1180 1113/1189/1180 +f 1140/1191/1181 1170/1247/1181 1171/1250/1181 +f 1126/1188/1182 1158/1251/1182 1127/1192/1182 +f 1114/1193/1183 1144/1249/1183 1145/1252/1183 +f 1141/1194/1184 1171/1250/1184 1172/1223/1184 +f 1160/1224/1185 1192/1253/1185 1161/1226/1185 +f 1148/1227/1186 1178/1254/1186 1179/1255/1186 +f 1162/1228/1187 1192/1253/1187 1193/1256/1187 +f 1148/1227/1188 1180/1257/1188 1149/1229/1188 +f 1163/1230/1189 1193/1256/1189 1194/1258/1189 +f 1149/1229/1190 1181/1259/1190 1150/1231/1190 +f 1163/1230/1191 1195/1260/1191 1164/1232/1191 +f 1150/1231/1192 1182/1261/1192 1151/1233/1192 +f 1165/1234/1193 1195/1260/1193 1196/1262/1193 +f 1152/1235/1194 1182/1261/1194 1183/1263/1194 +f 1165/1234/1195 1197/1264/1195 1166/1236/1195 +f 1152/1235/1196 1184/1265/1196 1153/1237/1196 +f 1167/1238/1197 1197/1264/1197 1198/1266/1197 +f 1154/1239/1198 1184/1265/1198 1185/1267/1198 +f 1168/1240/1199 1198/1266/1199 1199/1268/1199 +f 1154/1239/1200 1186/1269/1200 1155/1241/1200 +f 1142/1243/1201 1452/1270/1201 1173/1271/1201 +f 1168/1240/1202 1200/1272/1202 1169/1244/1202 +f 1156/1245/1203 1186/1269/1203 1187/1273/1203 +f 1142/1243/1204 1174/1274/1204 1143/1246/1204 +f 1170/1247/1205 1200/1272/1205 1201/1275/1205 +f 1157/1248/1206 1187/1273/1206 1188/1276/1206 +f 1143/1246/1207 1175/1277/1207 1144/1249/1207 +f 1170/1247/1208 1202/1278/1208 1171/1250/1208 +f 1157/1248/1209 1189/1279/1209 1158/1251/1209 +f 1145/1252/1210 1175/1277/1210 1176/1280/1210 +f 1171/1250/1211 1203/1281/1211 1172/1223/1211 +f 1158/1251/1212 1190/1282/1212 1159/1220/1212 +f 1145/1252/1213 1177/1283/1213 1146/1221/1213 +f 1887/1284/1214 1172/1223/1214 1203/1281/1214 +f 1160/1224/1215 1190/1282/1215 1191/1285/1215 +f 1146/1221/1216 1178/1254/1216 1147/1225/1216 +f 1194/1258/1217 1224/1286/1217 1225/1287/1217 +f 1180/1257/1218 1212/1288/1218 1181/1259/1218 +f 1194/1258/1219 1226/1289/1219 1195/1260/1219 +f 1182/1261/1220 1212/1288/1220 1213/1290/1220 +f 1196/1262/1221 1226/1289/1221 1227/1291/1221 +f 1183/1263/1222 1213/1290/1222 1214/1292/1222 +f 1196/1262/1223 1228/1293/1223 1197/1264/1223 +f 1183/1263/1224 1215/1294/1224 1184/1265/1224 +f 1198/1266/1225 1228/1293/1225 1229/1295/1225 +f 1185/1267/1226 1215/1294/1226 1216/1296/1226 +f 1198/1266/1227 1230/1297/1227 1199/1268/1227 +f 1185/1267/1228 1217/1298/1228 1186/1269/1228 +f 1173/1271/1229 1452/1299/1229 1204/1300/1229 +f 1199/1268/1230 1231/1301/1230 1200/1272/1230 +f 1187/1273/1231 1217/1298/1231 1218/1302/1231 +f 1173/1271/1232 1205/1303/1232 1174/1274/1232 +f 1201/1275/1233 1231/1301/1233 1232/1304/1233 +f 1188/1276/1234 1218/1302/1234 1219/1305/1234 +f 1174/1274/1235 1206/1306/1235 1175/1277/1235 +f 1201/1275/1236 1233/1307/1236 1202/1278/1236 +f 1188/1276/1237 1220/1308/1237 1189/1279/1237 +f 1176/1280/1238 1206/1306/1238 1207/1309/1238 +f 1203/1281/1239 1233/1307/1239 1234/1310/1239 +f 1189/1279/1240 1221/1311/1240 1190/1282/1240 +f 1177/1283/1241 1207/1309/1241 1208/1312/1241 +f 1887/1313/1242 1203/1281/1242 1234/1310/1242 +f 1191/1285/1243 1221/1311/1243 1222/1314/1243 +f 1177/1283/1244 1209/1315/1244 1178/1254/1244 +f 1191/1285/1245 1223/1316/1245 1192/1253/1245 +f 1178/1254/1246 1210/1317/1246 1179/1255/1246 +f 1193/1256/1247 1223/1316/1247 1224/1286/1247 +f 1179/1255/1248 1211/1318/1248 1180/1257/1248 +f 1226/1289/1249 1258/1319/1249 1227/1291/1249 +f 1213/1290/1250 1245/1320/1250 1214/1292/1250 +f 1227/1291/1251 1259/1321/1251 1228/1293/1251 +f 1214/1292/1252 1246/1322/1252 1215/1294/1252 +f 1229/1295/1253 1259/1321/1253 1260/1323/1253 +f 1216/1296/1254 1246/1322/1254 1247/1324/1254 +f 1230/1297/1255 1260/1323/1255 1261/1325/1255 +f 1216/1296/1256 1248/1326/1256 1217/1298/1256 +f 1204/1300/1257 1452/1327/1257 1235/1328/1257 +f 1231/1301/1258 1261/1325/1258 1262/1329/1258 +f 1218/1302/1259 1248/1326/1259 1249/1330/1259 +f 1204/1300/1260 1236/1331/1260 1205/1303/1260 +f 1232/1304/1261 1262/1329/1261 1263/1332/1261 +f 1219/1305/1262 1249/1330/1262 1250/1333/1262 +f 1205/1303/1263 1237/1334/1263 1206/1306/1263 +f 1233/1307/1264 1263/1332/1264 1264/1335/1264 +f 1220/1308/1265 1250/1333/1265 1251/1336/1265 +f 1206/1306/1266 1238/1337/1266 1207/1309/1266 +f 1234/1310/1267 1264/1335/1267 1265/1338/1267 +f 1220/1308/1268 1252/1339/1268 1221/1311/1268 +f 1207/1309/1269 1239/1340/1269 1208/1312/1269 +f 1887/1341/1270 1234/1310/1270 1265/1338/1270 +f 1222/1314/1271 1252/1339/1271 1253/1342/1271 +f 1208/1312/1272 1240/1343/1272 1209/1315/1272 +f 1222/1314/1273 1254/1344/1273 1223/1316/1273 +f 1210/1317/1274 1240/1343/1274 1241/1345/1274 +f 1224/1286/1275 1254/1344/1275 1255/1346/1275 +f 1210/1317/1276 1242/1347/1276 1211/1318/1276 +f 1225/1287/1277 1255/1346/1277 1256/1348/1277 +f 1211/1318/1278 1243/1349/1278 1212/1288/1278 +f 1225/1287/1279 1257/1350/1279 1226/1289/1279 +f 1213/1290/1280 1243/1349/1280 1244/1351/1280 +f 1260/1323/1281 1290/1352/1281 1291/1353/1281 +f 1247/1324/1282 1277/1354/1282 1278/1355/1282 +f 1261/1325/1283 1291/1353/1283 1292/1356/1283 +f 1247/1324/1284 1279/1357/1284 1248/1326/1284 +f 1235/1328/1285 1452/1358/1285 1266/1359/1285 +f 1262/1329/1286 1292/1356/1286 1293/1360/1286 +f 1249/1330/1287 1279/1357/1287 1280/1361/1287 +f 1236/1331/1288 1266/1359/1288 1267/1362/1288 +f 1263/1332/1289 1293/1360/1289 1294/1363/1289 +f 1249/1330/1290 1281/1364/1290 1250/1333/1290 +f 1236/1331/1291 1268/1365/1291 1237/1334/1291 +f 1263/1332/1292 1295/1366/1292 1264/1335/1292 +f 1251/1336/1293 1281/1364/1293 1282/1367/1293 +f 1237/1334/1294 1269/1368/1294 1238/1337/1294 +f 1264/1335/1295 1296/1369/1295 1265/1338/1295 +f 1251/1336/1296 1283/1370/1296 1252/1339/1296 +f 1238/1337/1297 1270/1371/1297 1239/1340/1297 +f 1887/1372/1298 1265/1338/1298 1296/1369/1298 +f 1253/1342/1299 1283/1370/1299 1284/1373/1299 +f 1240/1343/1300 1270/1371/1300 1271/1374/1300 +f 1253/1342/1301 1285/1375/1301 1254/1344/1301 +f 1240/1343/1302 1272/1376/1302 1241/1345/1302 +f 1255/1346/1303 1285/1375/1303 1286/1377/1303 +f 1241/1345/1304 1273/1378/1304 1242/1347/1304 +f 1256/1348/1305 1286/1377/1305 1287/1379/1305 +f 1243/1349/1306 1273/1378/1306 1274/1380/1306 +f 1256/1348/1307 1288/1381/1307 1257/1350/1307 +f 1244/1351/1308 1274/1380/1308 1275/1382/1308 +f 1257/1350/1309 1289/1383/1309 1258/1319/1309 +f 1244/1351/1310 1276/1384/1310 1245/1320/1310 +f 1258/1319/1311 1290/1352/1311 1259/1321/1311 +f 1245/1320/1312 1277/1354/1312 1246/1322/1312 +f 1266/1359/1313 1452/1385/1313 1297/1386/1313 +f 1293/1360/1314 1323/1387/1314 1324/1388/1314 +f 1280/1361/1315 1310/1389/1315 1311/1390/1315 +f 1266/1359/1316 1298/1391/1316 1267/1362/1316 +f 1294/1363/1317 1324/1388/1317 1325/1392/1317 +f 1280/1361/1318 1312/1393/1318 1281/1364/1318 +f 1267/1362/1319 1299/1394/1319 1268/1365/1319 +f 1294/1363/1320 1326/1395/1320 1295/1366/1320 +f 1282/1367/1321 1312/1393/1321 1313/1396/1321 +f 1268/1365/1322 1300/1397/1322 1269/1368/1322 +f 1295/1366/1323 1327/1398/1323 1296/1369/1323 +f 1282/1367/1324 1314/1399/1324 1283/1370/1324 +f 1269/1368/1325 1301/1400/1325 1270/1371/1325 +f 1887/1401/1326 1296/1369/1326 1327/1398/1326 +f 1284/1373/1327 1314/1399/1327 1315/1402/1327 +f 1270/1371/1328 1302/1403/1328 1271/1374/1328 +f 1284/1373/1329 1316/1404/1329 1285/1375/1329 +f 1271/1374/1330 1303/1405/1330 1272/1376/1330 +f 1286/1377/1331 1316/1404/1331 1317/1406/1331 +f 1273/1378/1332 1303/1405/1332 1304/1407/1332 +f 1287/1379/1333 1317/1406/1333 1318/1408/1333 +f 1273/1378/1334 1305/1409/1334 1274/1380/1334 +f 1287/1379/1335 1319/1410/1335 1288/1381/1335 +f 1275/1382/1336 1305/1409/1336 1306/1411/1336 +f 1288/1381/1337 1320/1412/1337 1289/1383/1337 +f 1275/1382/1338 1307/1413/1338 1276/1384/1338 +f 1289/1383/1339 1321/1414/1339 1290/1352/1339 +f 1276/1384/1340 1308/1415/1340 1277/1354/1340 +f 1290/1352/1341 1322/1416/1341 1291/1353/1341 +f 1278/1355/1342 1308/1415/1342 1309/1417/1342 +f 1292/1356/1343 1322/1416/1343 1323/1387/1343 +f 1278/1355/1344 1310/1389/1344 1279/1357/1344 +f 1298/1391/1345 1330/1418/1345 1299/1394/1345 +f 1325/1392/1346 1357/1419/1346 1326/1395/1346 +f 1313/1396/1347 1343/1420/1347 1344/1421/1347 +f 1299/1394/1348 1331/1422/1348 1300/1397/1348 +f 1326/1395/1349 1358/1423/1349 1327/1398/1349 +f 1313/1396/1350 1345/1424/1350 1314/1399/1350 +f 1300/1397/1351 1332/1425/1351 1301/1400/1351 +f 1887/1426/1352 1327/1398/1352 1358/1423/1352 +f 1315/1402/1353 1345/1424/1353 1346/1427/1353 +f 1301/1400/1354 1333/1428/1354 1302/1403/1354 +f 1315/1402/1355 1347/1429/1355 1316/1404/1355 +f 1303/1405/1356 1333/1428/1356 1334/1430/1356 +f 1317/1406/1357 1347/1429/1357 1348/1431/1357 +f 1304/1407/1358 1334/1430/1358 1335/1432/1358 +f 1318/1408/1359 1348/1431/1359 1349/1433/1359 +f 1304/1407/1360 1336/1434/1360 1305/1409/1360 +f 1319/1410/1361 1349/1433/1361 1350/1435/1361 +f 1306/1411/1362 1336/1434/1362 1337/1436/1362 +f 1319/1410/1363 1351/1437/1363 1320/1412/1363 +f 1306/1411/1364 1338/1438/1364 1307/1413/1364 +f 1320/1412/1365 1352/1439/1365 1321/1414/1365 +f 1308/1415/1366 1338/1438/1366 1339/1440/1366 +f 1322/1416/1367 1352/1439/1367 1353/1441/1367 +f 1309/1417/1368 1339/1440/1368 1340/1442/1368 +f 1322/1416/1369 1354/1443/1369 1323/1387/1369 +f 1309/1417/1370 1341/1444/1370 1310/1389/1370 +f 1297/1386/1371 1452/1445/1371 1328/1446/1371 +f 1323/1387/1372 1355/1447/1372 1324/1388/1372 +f 1311/1390/1373 1341/1444/1373 1342/1448/1373 +f 1297/1386/1374 1329/1449/1374 1298/1391/1374 +f 1325/1392/1375 1355/1447/1375 1356/1450/1375 +f 1311/1390/1376 1343/1420/1376 1312/1393/1376 +f 1331/1422/1377 1363/1451/1377 1332/1425/1377 +f 1887/1452/1378 1358/1423/1378 1389/1453/1378 +f 1346/1427/1379 1376/1454/1379 1377/1455/1379 +f 1332/1425/1380 1364/1456/1380 1333/1428/1380 +f 1346/1427/1381 1378/1457/1381 1347/1429/1381 +f 1334/1430/1382 1364/1456/1382 1365/1458/1382 +f 1348/1431/1383 1378/1457/1383 1379/1459/1383 +f 1334/1430/1384 1366/1460/1384 1335/1432/1384 +f 1349/1433/1385 1379/1459/1385 1380/1461/1385 +f 1335/1432/1386 1367/1462/1386 1336/1434/1386 +f 1349/1433/1387 1381/1463/1387 1350/1435/1387 +f 1337/1436/1388 1367/1462/1388 1368/1464/1388 +f 1350/1435/1389 1382/1465/1389 1351/1437/1389 +f 1337/1436/1390 1369/1466/1390 1338/1438/1390 +f 1351/1437/1391 1383/1467/1391 1352/1439/1391 +f 1338/1438/1392 1370/1468/1392 1339/1440/1392 +f 1352/1439/1393 1384/1469/1393 1353/1441/1393 +f 1340/1442/1394 1370/1468/1394 1371/1470/1394 +f 1354/1443/1395 1384/1469/1395 1385/1471/1395 +f 1340/1442/1396 1372/1472/1396 1341/1444/1396 +f 1328/1446/1397 1452/1473/1397 1359/1474/1397 +f 1354/1443/1398 1386/1475/1398 1355/1447/1398 +f 1342/1448/1399 1372/1472/1399 1373/1476/1399 +f 1328/1446/1400 1360/1477/1400 1329/1449/1400 +f 1356/1450/1401 1386/1475/1401 1387/1478/1401 +f 1342/1448/1402 1374/1479/1402 1343/1420/1402 +f 1329/1449/1403 1361/1480/1403 1330/1418/1403 +f 1356/1450/1404 1388/1481/1404 1357/1419/1404 +f 1344/1421/1405 1374/1479/1405 1375/1482/1405 +f 1330/1418/1406 1362/1483/1406 1331/1422/1406 +f 1357/1419/1407 1389/1453/1407 1358/1423/1407 +f 1344/1421/1408 1376/1454/1408 1345/1424/1408 +f 1365/1458/1409 1395/1484/1409 1396/1485/1409 +f 1379/1459/1410 1409/1486/1410 1410/1487/1410 +f 1366/1460/1411 1396/1485/1411 1397/1488/1411 +f 1380/1461/1412 1410/1487/1412 1411/1489/1412 +f 1366/1460/1413 1398/1490/1413 1367/1462/1413 +f 1381/1463/1414 1411/1489/1414 1412/1491/1414 +f 1367/1462/1415 1399/1492/1415 1368/1464/1415 +f 1381/1463/1416 1413/1493/1416 1382/1465/1416 +f 1368/1464/1417 1400/1494/1417 1369/1466/1417 +f 1382/1465/1418 1414/1495/1418 1383/1467/1418 +f 1369/1466/1419 1401/1496/1419 1370/1468/1419 +f 1383/1467/1420 1415/1497/1420 1384/1469/1420 +f 1371/1470/1421 1401/1496/1421 1402/1498/1421 +f 1385/1471/1422 1415/1497/1422 1416/1499/1422 +f 1371/1470/1423 1403/1500/1423 1372/1472/1423 +f 1359/1474/1424 1452/1501/1424 1390/1502/1424 +f 1385/1471/1425 1417/1503/1425 1386/1475/1425 +f 1373/1476/1426 1403/1500/1426 1404/1504/1426 +f 1359/1474/1427 1391/1505/1427 1360/1477/1427 +f 1387/1478/1428 1417/1503/1428 1418/1506/1428 +f 1373/1476/1429 1405/1507/1429 1374/1479/1429 +f 1361/1480/1430 1391/1505/1430 1392/1508/1430 +f 1387/1478/1431 1419/1509/1431 1388/1481/1431 +f 1375/1482/1432 1405/1507/1432 1406/1510/1432 +f 1361/1480/1433 1393/1511/1433 1362/1483/1433 +f 1389/1453/1434 1419/1509/1434 1420/1512/1434 +f 1375/1482/1435 1407/1513/1435 1376/1454/1435 +f 1362/1483/1436 1394/1514/1436 1363/1451/1436 +f 1887/1515/1437 1389/1453/1437 1420/1512/1437 +f 1377/1455/1438 1407/1513/1438 1408/1516/1438 +f 1364/1456/1439 1394/1514/1439 1395/1484/1439 +f 1377/1455/1440 1409/1486/1440 1378/1457/1440 +f 1397/1488/1441 1429/1517/1441 1398/1490/1441 +f 1412/1491/1442 1442/1518/1442 1443/1519/1442 +f 1399/1492/1443 1429/1517/1443 1430/1520/1443 +f 1412/1491/1444 1444/1521/1444 1413/1493/1444 +f 1399/1492/1445 1431/1522/1445 1400/1494/1445 +f 1413/1493/1446 1445/1523/1446 1414/1495/1446 +f 1400/1494/1447 1432/1524/1447 1401/1496/1447 +f 1414/1495/1448 1446/1525/1448 1415/1497/1448 +f 1402/1498/1449 1432/1524/1449 1433/1526/1449 +f 1415/1497/1450 1447/1527/1450 1416/1499/1450 +f 1402/1498/1451 1434/1528/1451 1403/1500/1451 +f 1390/1502/1452 1452/1529/1452 1421/1530/1452 +f 1417/1503/1453 1447/1527/1453 1448/1531/1453 +f 1404/1504/1454 1434/1528/1454 1435/1532/1454 +f 1390/1502/1455 1422/1533/1455 1391/1505/1455 +f 1418/1506/1456 1448/1531/1456 1449/1534/1456 +f 1404/1504/1457 1436/1535/1457 1405/1507/1457 +f 1391/1505/1458 1423/1536/1458 1392/1508/1458 +f 1418/1506/1459 1450/1537/1459 1419/1509/1459 +f 1406/1510/1460 1436/1535/1460 1437/1538/1460 +f 1392/1508/1461 1424/1539/1461 1393/1511/1461 +f 1419/1509/1462 1451/1540/1462 1420/1512/1462 +f 1406/1510/1463 1438/1541/1463 1407/1513/1463 +f 1394/1514/1464 1424/1539/1464 1425/1542/1464 +f 1887/1543/1465 1420/1512/1465 1451/1540/1465 +f 1408/1516/1466 1438/1541/1466 1439/1544/1466 +f 1395/1484/1467 1425/1542/1467 1426/1545/1467 +f 1408/1516/1468 1440/1546/1468 1409/1486/1468 +f 1396/1485/1469 1426/1545/1469 1427/1547/1469 +f 1410/1487/1470 1440/1546/1470 1441/1548/1470 +f 1397/1488/1471 1427/1547/1471 1428/1549/1471 +f 1411/1489/1472 1441/1548/1472 1442/1518/1472 +f 1430/1520/1473 1463/1550/1473 1431/1522/1473 +f 1444/1521/1474 1477/1551/1474 1445/1523/1474 +f 1431/1522/1475 1464/1552/1475 1432/1524/1475 +f 1445/1523/1476 1478/1553/1476 1446/1525/1476 +f 1433/1526/1477 1464/1552/1477 1465/1554/1477 +f 1446/1525/1478 1479/1555/1478 1447/1527/1478 +f 1433/1526/1479 1466/1556/1479 1434/1528/1479 +f 1421/1530/1480 1452/1557/1480 1453/1558/1480 +f 1447/1527/1481 1480/1559/1481 1448/1531/1481 +f 1435/1532/1482 1466/1556/1482 1467/1560/1482 +f 1421/1530/1483 1454/1561/1483 1422/1533/1483 +f 1449/1534/1484 1480/1559/1484 1481/1562/1484 +f 1435/1532/1485 1468/1563/1485 1436/1535/1485 +f 1422/1533/1486 1455/1564/1486 1423/1536/1486 +f 1449/1534/1487 1482/1565/1487 1450/1537/1487 +f 1437/1538/1488 1468/1563/1488 1469/1566/1488 +f 1423/1536/1489 1456/1567/1489 1424/1539/1489 +f 1450/1537/1490 1483/1568/1490 1451/1540/1490 +f 1437/1538/1491 1470/1569/1491 1438/1541/1491 +f 1424/1539/1492 1457/1570/1492 1425/1542/1492 +f 1887/1571/1493 1451/1540/1493 1483/1568/1493 +f 1439/1544/1494 1470/1569/1494 1471/1572/1494 +f 1425/1542/1495 1458/1573/1495 1426/1545/1495 +f 1439/1544/1496 1472/1574/1496 1440/1546/1496 +f 1427/1547/1497 1458/1573/1497 1459/1575/1497 +f 1441/1548/1498 1472/1574/1498 1473/1576/1498 +f 1428/1549/1499 1459/1575/1499 1460/1577/1499 +f 1442/1518/1500 1473/1576/1500 1474/1578/1500 +f 1428/1549/1501 1461/1579/1501 1429/1517/1501 +f 1442/1518/1502 1475/1580/1502 1443/1519/1502 +f 1430/1520/1503 1461/1579/1503 1462/1581/1503 +f 1443/1519/1504 1476/1582/1504 1444/1521/1504 +f 1465/1554/1505 1495/1583/1505 1496/1584/1505 +f 1478/1553/1506 1510/1585/1506 1479/1555/1506 +f 1465/1554/1507 1497/1586/1507 1466/1556/1507 +f 1453/1558/1508 1452/1587/1508 1484/1588/1508 +f 1479/1555/1509 1511/1589/1509 1480/1559/1509 +f 1467/1560/1510 1497/1586/1510 1498/1590/1510 +f 1453/1558/1511 1485/1591/1511 1454/1561/1511 +f 1481/1562/1512 1511/1589/1512 1512/1592/1512 +f 1467/1560/1513 1499/1593/1513 1468/1563/1513 +f 1454/1561/1514 1486/1594/1514 1455/1564/1514 +f 1481/1562/1515 1513/1595/1515 1482/1565/1515 +f 1469/1566/1516 1499/1593/1516 1500/1596/1516 +f 1455/1564/1517 1487/1597/1517 1456/1567/1517 +f 1482/1565/1518 1514/1598/1518 1483/1568/1518 +f 1469/1566/1519 1501/1599/1519 1470/1569/1519 +f 1456/1567/1520 1488/1600/1520 1457/1570/1520 +f 1887/1601/1521 1483/1568/1521 1514/1598/1521 +f 1471/1572/1522 1501/1599/1522 1502/1602/1522 +f 1457/1570/1523 1489/1603/1523 1458/1573/1523 +f 1471/1572/1524 1503/1604/1524 1472/1574/1524 +f 1459/1575/1525 1489/1603/1525 1490/1605/1525 +f 1473/1576/1526 1503/1604/1526 1504/1606/1526 +f 1460/1577/1527 1490/1605/1527 1491/1607/1527 +f 1474/1578/1528 1504/1606/1528 1505/1608/1528 +f 1460/1577/1529 1492/1609/1529 1461/1579/1529 +f 1474/1578/1530 1506/1610/1530 1475/1580/1530 +f 1462/1581/1531 1492/1609/1531 1493/1611/1531 +f 1475/1580/1532 1507/1612/1532 1476/1582/1532 +f 1462/1581/1533 1494/1613/1533 1463/1550/1533 +f 1476/1582/1534 1508/1614/1534 1477/1551/1534 +f 1463/1550/1535 1495/1583/1535 1464/1552/1535 +f 1477/1551/1536 1509/1615/1536 1478/1553/1536 +f 1498/1616/1537 1528/1617/1537 1529/1618/1537 +f 1484/1619/1538 1516/1620/1538 1485/1621/1538 +f 1512/1622/1539 1542/1623/1539 1543/1624/1539 +f 1498/1616/1540 1530/1625/1540 1499/1626/1540 +f 1485/1621/1541 1517/1627/1541 1486/1628/1541 +f 1512/1622/1542 1544/1629/1542 1513/1630/1542 +f 1500/1631/1543 1530/1625/1543 1531/1632/1543 +f 1486/1628/1544 1518/1633/1544 1487/1634/1544 +f 1513/1630/1545 1545/1635/1545 1514/1636/1545 +f 1500/1631/1546 1532/1637/1546 1501/1638/1546 +f 1487/1634/1547 1519/1639/1547 1488/1640/1547 +f 1887/1641/1548 1514/1636/1548 1545/1635/1548 +f 1502/1642/1549 1532/1637/1549 1533/1643/1549 +f 1489/1644/1550 1519/1639/1550 1520/1645/1550 +f 1502/1642/1551 1534/1646/1551 1503/1647/1551 +f 1489/1644/1552 1521/1648/1552 1490/1649/1552 +f 1504/1650/1553 1534/1646/1553 1535/1651/1553 +f 1490/1649/1554 1522/1652/1554 1491/1653/1554 +f 1505/1654/1555 1535/1651/1555 1536/1655/1555 +f 1491/1653/1556 1523/1656/1556 1492/1657/1556 +f 1505/1654/1557 1537/1658/1557 1506/1659/1557 +f 1493/1660/1558 1523/1656/1558 1524/1661/1558 +f 1506/1659/1559 1538/1662/1559 1507/1663/1559 +f 1493/1660/1560 1525/1664/1560 1494/1665/1560 +f 1507/1663/1561 1539/1666/1561 1508/1667/1561 +f 1494/1665/1562 1526/1668/1562 1495/1669/1562 +f 1508/1667/1563 1540/1670/1563 1509/1671/1563 +f 1496/1672/1564 1526/1668/1564 1527/1673/1564 +f 1509/1671/1565 1541/1674/1565 1510/1675/1565 +f 1496/1672/1566 1528/1617/1566 1497/1676/1566 +f 1484/1619/1567 1452/1677/1567 1515/1678/1567 +f 1510/1675/1568 1542/1623/1568 1511/1679/1568 +f 1531/1632/1569 1561/1680/1569 1562/1681/1569 +f 1517/1627/1570 1549/1682/1570 1518/1633/1570 +f 1544/1629/1571 1576/1683/1571 1545/1635/1571 +f 1531/1632/1572 1563/1684/1572 1532/1637/1572 +f 1518/1633/1573 1550/1685/1573 1519/1639/1573 +f 1887/1686/1574 1545/1635/1574 1576/1683/1574 +f 1533/1643/1575 1563/1684/1575 1564/1687/1575 +f 1520/1645/1576 1550/1685/1576 1551/1688/1576 +f 1533/1643/1577 1565/1689/1577 1534/1646/1577 +f 1521/1648/1578 1551/1688/1578 1552/1690/1578 +f 1535/1651/1579 1565/1689/1579 1566/1691/1579 +f 1522/1652/1580 1552/1690/1580 1553/1692/1580 +f 1536/1655/1581 1566/1691/1581 1567/1693/1581 +f 1522/1652/1582 1554/1694/1582 1523/1656/1582 +f 1536/1655/1583 1568/1695/1583 1537/1658/1583 +f 1524/1661/1584 1554/1694/1584 1555/1696/1584 +f 1537/1658/1585 1569/1697/1585 1538/1662/1585 +f 1524/1661/1586 1556/1698/1586 1525/1664/1586 +f 1538/1662/1587 1570/1699/1587 1539/1666/1587 +f 1526/1668/1588 1556/1698/1588 1557/1700/1588 +f 1539/1666/1589 1571/1701/1589 1540/1670/1589 +f 1527/1673/1590 1557/1700/1590 1558/1702/1590 +f 1540/1670/1591 1572/1703/1591 1541/1674/1591 +f 1527/1673/1592 1559/1704/1592 1528/1617/1592 +f 1515/1678/1593 1452/1705/1593 1546/1706/1593 +f 1541/1674/1594 1573/1707/1594 1542/1623/1594 +f 1529/1618/1595 1559/1704/1595 1560/1708/1595 +f 1515/1678/1596 1547/1709/1596 1516/1620/1596 +f 1543/1624/1597 1573/1707/1597 1574/1710/1597 +f 1529/1618/1598 1561/1680/1598 1530/1625/1598 +f 1516/1620/1599 1548/1711/1599 1517/1627/1599 +f 1543/1624/1600 1575/1712/1600 1544/1629/1600 +f 1564/1687/1601 1594/1713/1601 1595/1714/1601 +f 1551/1688/1602 1581/1715/1602 1582/1716/1602 +f 1564/1687/1603 1596/1717/1603 1565/1689/1603 +f 1552/1690/1604 1582/1716/1604 1583/1718/1604 +f 1566/1691/1605 1596/1717/1605 1597/1719/1605 +f 1553/1692/1606 1583/1718/1606 1584/1720/1606 +f 1567/1693/1607 1597/1719/1607 1598/1721/1607 +f 1553/1692/1608 1585/1722/1608 1554/1694/1608 +f 1567/1693/1609 1599/1723/1609 1568/1695/1609 +f 1555/1696/1610 1585/1722/1610 1586/1724/1610 +f 1568/1695/1611 1600/1725/1611 1569/1697/1611 +f 1555/1696/1612 1587/1726/1612 1556/1698/1612 +f 1569/1697/1613 1601/1727/1613 1570/1699/1613 +f 1556/1698/1614 1588/1728/1614 1557/1700/1614 +f 1570/1699/1615 1602/1729/1615 1571/1701/1615 +f 1558/1702/1616 1588/1728/1616 1589/1730/1616 +f 1571/1701/1617 1603/1731/1617 1572/1703/1617 +f 1558/1702/1618 1590/1732/1618 1559/1704/1618 +f 1546/1706/1619 1452/1733/1619 1577/1734/1619 +f 1572/1703/1620 1604/1735/1620 1573/1707/1620 +f 1560/1708/1621 1590/1732/1621 1591/1736/1621 +f 1546/1706/1622 1578/1737/1622 1547/1709/1622 +f 1574/1710/1623 1604/1735/1623 1605/1738/1623 +f 1560/1708/1624 1592/1739/1624 1561/1680/1624 +f 1547/1709/1625 1579/1740/1625 1548/1711/1625 +f 1574/1710/1626 1606/1741/1626 1575/1712/1626 +f 1562/1681/1627 1592/1739/1627 1593/1742/1627 +f 1548/1711/1628 1580/1743/1628 1549/1682/1628 +f 1575/1712/1629 1607/1744/1629 1576/1683/1629 +f 1562/1681/1630 1594/1713/1630 1563/1684/1630 +f 1549/1682/1631 1581/1715/1631 1550/1685/1631 +f 1887/1745/1632 1576/1683/1632 1607/1744/1632 +f 1591/1736/1633 1623/1746/1633 1592/1739/1633 +f 1578/1737/1634 1610/1747/1634 1579/1740/1634 +f 1605/1738/1635 1637/1748/1635 1606/1741/1635 +f 1593/1742/1636 1623/1746/1636 1624/1749/1636 +f 1579/1740/1637 1611/1750/1637 1580/1743/1637 +f 1606/1741/1638 1638/1751/1638 1607/1744/1638 +f 1593/1742/1639 1625/1752/1639 1594/1713/1639 +f 1581/1715/1640 1611/1750/1640 1612/1753/1640 +f 1887/1754/1641 1607/1744/1641 1638/1751/1641 +f 1595/1714/1642 1625/1752/1642 1626/1755/1642 +f 1581/1715/1643 1613/1756/1643 1582/1716/1643 +f 1595/1714/1644 1627/1757/1644 1596/1717/1644 +f 1583/1718/1645 1613/1756/1645 1614/1758/1645 +f 1597/1719/1646 1627/1757/1646 1628/1759/1646 +f 1584/1720/1647 1614/1758/1647 1615/1760/1647 +f 1598/1721/1648 1628/1759/1648 1629/1761/1648 +f 1584/1720/1649 1616/1762/1649 1585/1722/1649 +f 1598/1721/1650 1630/1763/1650 1599/1723/1650 +f 1585/1722/1651 1617/1764/1651 1586/1724/1651 +f 1599/1723/1652 1631/1765/1652 1600/1725/1652 +f 1586/1724/1653 1618/1766/1653 1587/1726/1653 +f 1600/1725/1654 1632/1767/1654 1601/1727/1654 +f 1587/1726/1655 1619/1768/1655 1588/1728/1655 +f 1601/1727/1656 1633/1769/1656 1602/1729/1656 +f 1589/1730/1657 1619/1768/1657 1620/1770/1657 +f 1603/1731/1658 1633/1769/1658 1634/1771/1658 +f 1589/1730/1659 1621/1772/1659 1590/1732/1659 +f 1577/1734/1660 1452/1773/1660 1608/1774/1660 +f 1603/1731/1661 1635/1775/1661 1604/1735/1661 +f 1591/1736/1662 1621/1772/1662 1622/1776/1662 +f 1577/1734/1663 1609/1777/1663 1578/1737/1663 +f 1605/1738/1664 1635/1775/1664 1636/1778/1664 +f 1624/1749/1665 1656/1779/1665 1625/1752/1665 +f 1611/1750/1666 1643/1780/1666 1612/1753/1666 +f 1887/1781/1667 1638/1751/1667 1669/1782/1667 +f 1626/1755/1668 1656/1779/1668 1657/1783/1668 +f 1612/1753/1669 1644/1784/1669 1613/1756/1669 +f 1626/1755/1670 1658/1785/1670 1627/1757/1670 +f 1614/1758/1671 1644/1784/1671 1645/1786/1671 +f 1628/1759/1672 1658/1785/1672 1659/1787/1672 +f 1614/1758/1673 1646/1788/1673 1615/1760/1673 +f 1629/1761/1674 1659/1787/1674 1660/1789/1674 +f 1615/1760/1675 1647/1790/1675 1616/1762/1675 +f 1629/1761/1676 1661/1791/1676 1630/1763/1676 +f 1617/1764/1677 1647/1790/1677 1648/1792/1677 +f 1630/1763/1678 1662/1793/1678 1631/1765/1678 +f 1617/1764/1679 1649/1794/1679 1618/1766/1679 +f 1631/1765/1680 1663/1795/1680 1632/1767/1680 +f 1618/1766/1681 1650/1796/1681 1619/1768/1681 +f 1632/1767/1682 1664/1797/1682 1633/1769/1682 +f 1620/1770/1683 1650/1796/1683 1651/1798/1683 +f 1634/1771/1684 1664/1797/1684 1665/1799/1684 +f 1620/1770/1685 1652/1800/1685 1621/1772/1685 +f 1608/1774/1686 1452/1801/1686 1639/1802/1686 +f 1634/1771/1687 1666/1803/1687 1635/1775/1687 +f 1622/1776/1688 1652/1800/1688 1653/1804/1688 +f 1608/1774/1689 1640/1805/1689 1609/1777/1689 +f 1636/1778/1690 1666/1803/1690 1667/1806/1690 +f 1622/1776/1691 1654/1807/1691 1623/1746/1691 +f 1609/1777/1692 1641/1808/1692 1610/1747/1692 +f 1636/1778/1693 1668/1809/1693 1637/1748/1693 +f 1624/1749/1694 1654/1807/1694 1655/1810/1694 +f 1610/1747/1695 1642/1811/1695 1611/1750/1695 +f 1637/1748/1696 1669/1782/1696 1638/1751/1696 +f 1657/1783/1697 1689/1812/1697 1658/1785/1697 +f 1645/1786/1698 1675/1813/1698 1676/1814/1698 +f 1659/1787/1699 1689/1812/1699 1690/1815/1699 +f 1645/1786/1700 1677/1816/1700 1646/1788/1700 +f 1660/1789/1701 1690/1815/1701 1691/1817/1701 +f 1646/1788/1702 1678/1818/1702 1647/1790/1702 +f 1660/1789/1703 1692/1819/1703 1661/1791/1703 +f 1648/1792/1704 1678/1818/1704 1679/1820/1704 +f 1661/1791/1705 1693/1821/1705 1662/1793/1705 +f 1648/1792/1706 1680/1822/1706 1649/1794/1706 +f 1662/1793/1707 1694/1823/1707 1663/1795/1707 +f 1649/1794/1708 1681/1824/1708 1650/1796/1708 +f 1663/1795/1709 1695/1825/1709 1664/1797/1709 +f 1651/1798/1710 1681/1824/1710 1682/1826/1710 +f 1665/1799/1711 1695/1825/1711 1696/1827/1711 +f 1651/1798/1712 1683/1828/1712 1652/1800/1712 +f 1639/1802/1713 1452/1829/1713 1670/1830/1713 +f 1665/1799/1714 1697/1831/1714 1666/1803/1714 +f 1653/1804/1715 1683/1828/1715 1684/1832/1715 +f 1640/1805/1716 1670/1830/1716 1671/1833/1716 +f 1667/1806/1717 1697/1831/1717 1698/1834/1717 +f 1653/1804/1718 1685/1835/1718 1654/1807/1718 +f 1641/1808/1719 1671/1833/1719 1672/1836/1719 +f 1667/1806/1720 1699/1837/1720 1668/1809/1720 +f 1655/1810/1721 1685/1835/1721 1686/1838/1721 +f 1641/1808/1722 1673/1839/1722 1642/1811/1722 +f 1668/1809/1723 1700/1840/1723 1669/1782/1723 +f 1655/1810/1724 1687/1841/1724 1656/1779/1724 +f 1642/1811/1725 1674/1842/1725 1643/1780/1725 +f 1887/1843/1726 1669/1782/1726 1700/1840/1726 +f 1657/1783/1727 1687/1841/1727 1688/1844/1727 +f 1643/1780/1728 1675/1813/1728 1644/1784/1728 +f 1691/1817/1729 1721/1845/1729 1722/1846/1729 +f 1677/1816/1730 1709/1847/1730 1678/1818/1730 +f 1691/1817/1731 1723/1848/1731 1692/1819/1731 +f 1678/1818/1732 1710/1849/1732 1679/1820/1732 +f 1692/1819/1733 1724/1850/1733 1693/1821/1733 +f 1679/1820/1734 1711/1851/1734 1680/1822/1734 +f 1693/1821/1735 1725/1852/1735 1694/1823/1735 +f 1680/1822/1736 1712/1853/1736 1681/1824/1736 +f 1695/1825/1737 1725/1852/1737 1726/1854/1737 +f 1682/1826/1738 1712/1853/1738 1713/1855/1738 +f 1696/1827/1739 1726/1854/1739 1727/1856/1739 +f 1682/1826/1740 1714/1857/1740 1683/1828/1740 +f 1670/1830/1741 1452/1858/1741 1701/1859/1741 +f 1696/1827/1742 1728/1860/1742 1697/1831/1742 +f 1684/1832/1743 1714/1857/1743 1715/1861/1743 +f 1670/1830/1744 1702/1862/1744 1671/1833/1744 +f 1698/1834/1745 1728/1860/1745 1729/1863/1745 +f 1684/1832/1746 1716/1864/1746 1685/1835/1746 +f 1671/1833/1747 1703/1865/1747 1672/1836/1747 +f 1699/1837/1748 1729/1863/1748 1730/1866/1748 +f 1686/1838/1749 1716/1864/1749 1717/1867/1749 +f 1672/1836/1750 1704/1868/1750 1673/1839/1750 +f 1700/1840/1751 1730/1866/1751 1731/1869/1751 +f 1686/1838/1752 1718/1870/1752 1687/1841/1752 +f 1674/1842/1753 1704/1868/1753 1705/1871/1753 +f 1887/1872/1754 1700/1840/1754 1731/1869/1754 +f 1688/1844/1755 1718/1870/1755 1719/1873/1755 +f 1674/1842/1756 1706/1874/1756 1675/1813/1756 +f 1688/1844/1757 1720/1875/1757 1689/1812/1757 +f 1676/1814/1758 1706/1874/1758 1707/1876/1758 +f 1690/1815/1759 1720/1875/1759 1721/1845/1759 +f 1676/1814/1760 1708/1877/1760 1677/1816/1760 +f 1723/1848/1761 1755/1878/1761 1724/1850/1761 +f 1710/1849/1762 1742/1879/1762 1711/1851/1762 +f 1724/1850/1763 1756/1880/1763 1725/1852/1763 +f 1712/1853/1764 1742/1879/1764 1743/1881/1764 +f 1725/1852/1765 1757/1882/1765 1726/1854/1765 +f 1713/1855/1766 1743/1881/1766 1744/1883/1766 +f 1727/1856/1767 1757/1882/1767 1758/1884/1767 +f 1713/1855/1768 1745/1885/1768 1714/1857/1768 +f 1701/1859/1769 1452/1886/1769 1732/1887/1769 +f 1727/1856/1770 1759/1888/1770 1728/1860/1770 +f 1715/1861/1771 1745/1885/1771 1746/1889/1771 +f 1701/1859/1772 1733/1890/1772 1702/1862/1772 +f 1728/1860/1773 1760/1891/1773 1729/1863/1773 +f 1715/1861/1774 1747/1892/1774 1716/1864/1774 +f 1703/1865/1775 1733/1890/1775 1734/1893/1775 +f 1729/1863/1776 1761/1894/1776 1730/1866/1776 +f 1717/1867/1777 1747/1892/1777 1748/1895/1777 +f 1703/1865/1778 1735/1896/1778 1704/1868/1778 +f 1730/1866/1779 1762/1897/1779 1731/1869/1779 +f 1717/1867/1780 1749/1898/1780 1718/1870/1780 +f 1704/1868/1781 1736/1899/1781 1705/1871/1781 +f 1887/1900/1782 1731/1869/1782 1762/1897/1782 +f 1719/1873/1783 1749/1898/1783 1750/1901/1783 +f 1705/1871/1784 1737/1902/1784 1706/1874/1784 +f 1719/1873/1785 1751/1903/1785 1720/1875/1785 +f 1706/1874/1786 1738/1904/1786 1707/1876/1786 +f 1721/1845/1787 1751/1903/1787 1752/1905/1787 +f 1708/1877/1788 1738/1904/1788 1739/1906/1788 +f 1722/1846/1789 1752/1905/1789 1753/1907/1789 +f 1709/1847/1790 1739/1906/1790 1740/1908/1790 +f 1723/1848/1791 1753/1907/1791 1754/1909/1791 +f 1710/1849/1792 1740/1908/1792 1741/1910/1792 +f 1756/1880/1793 1788/1911/1793 1757/1882/1793 +f 1744/1883/1794 1774/1912/1794 1775/1913/1794 +f 1758/1884/1795 1788/1911/1795 1789/1914/1795 +f 1744/1883/1796 1776/1915/1796 1745/1885/1796 +f 1732/1887/1797 1452/1916/1797 1763/1917/1797 +f 1758/1884/1798 1790/1918/1798 1759/1888/1798 +f 1746/1889/1799 1776/1915/1799 1777/1919/1799 +f 1732/1887/1800 1764/1920/1800 1733/1890/1800 +f 1759/1888/1801 1791/1921/1801 1760/1891/1801 +f 1746/1889/1802 1778/1922/1802 1747/1892/1802 +f 1734/1893/1803 1764/1920/1803 1765/1923/1803 +f 1760/1891/1804 1792/1924/1804 1761/1894/1804 +f 1748/1895/1805 1778/1922/1805 1779/1925/1805 +f 1734/1893/1806 1766/1926/1806 1735/1896/1806 +f 1762/1897/1807 1792/1924/1807 1793/1927/1807 +f 1748/1895/1808 1780/1928/1808 1749/1898/1808 +f 1736/1899/1809 1766/1926/1809 1767/1929/1809 +f 1887/1930/1810 1762/1897/1810 1793/1927/1810 +f 1750/1901/1811 1780/1928/1811 1781/1931/1811 +f 1736/1899/1812 1768/1932/1812 1737/1902/1812 +f 1750/1901/1813 1782/1933/1813 1751/1903/1813 +f 1738/1904/1814 1768/1932/1814 1769/1934/1814 +f 1752/1905/1815 1782/1933/1815 1783/1935/1815 +f 1739/1906/1816 1769/1934/1816 1770/1936/1816 +f 1753/1907/1817 1783/1935/1817 1784/1937/1817 +f 1740/1908/1818 1770/1936/1818 1771/1938/1818 +f 1754/1909/1819 1784/1937/1819 1785/1939/1819 +f 1740/1908/1820 1772/1940/1820 1741/1910/1820 +f 1754/1909/1821 1786/1941/1821 1755/1878/1821 +f 1741/1910/1822 1773/1942/1822 1742/1879/1822 +f 1755/1878/1823 1787/1943/1823 1756/1880/1823 +f 1742/1879/1824 1774/1912/1824 1743/1881/1824 +f 1763/1917/1825 1452/1944/1825 1794/1945/1825 +f 1789/1914/1826 1821/1946/1826 1790/1918/1826 +f 1777/1919/1827 1807/1947/1827 1808/1948/1827 +f 1763/1917/1828 1795/1949/1828 1764/1920/1828 +f 1790/1918/1829 1822/1950/1829 1791/1921/1829 +f 1777/1919/1830 1809/1951/1830 1778/1922/1830 +f 1764/1920/1831 1796/1952/1831 1765/1923/1831 +f 1792/1924/1832 1822/1950/1832 1823/1953/1832 +f 1779/1925/1833 1809/1951/1833 1810/1954/1833 +f 1766/1926/1834 1796/1952/1834 1797/1955/1834 +f 1792/1924/1835 1824/1956/1835 1793/1927/1835 +f 1779/1925/1836 1811/1957/1836 1780/1928/1836 +f 1767/1929/1837 1797/1955/1837 1798/1958/1837 +f 1887/1959/1838 1793/1927/1838 1824/1956/1838 +f 1781/1931/1839 1811/1957/1839 1812/1960/1839 +f 1767/1929/1840 1799/1961/1840 1768/1932/1840 +f 1781/1931/1841 1813/1962/1841 1782/1933/1841 +f 1768/1932/1842 1800/1963/1842 1769/1934/1842 +f 1783/1935/1843 1813/1962/1843 1814/1964/1843 +f 1770/1936/1844 1800/1963/1844 1801/1965/1844 +f 1784/1937/1845 1814/1964/1845 1815/1966/1845 +f 1770/1936/1846 1802/1967/1846 1771/1938/1846 +f 1785/1939/1847 1815/1966/1847 1816/1968/1847 +f 1771/1938/1848 1803/1969/1848 1772/1940/1848 +f 1785/1939/1849 1817/1970/1849 1786/1941/1849 +f 1772/1940/1850 1804/1971/1850 1773/1942/1850 +f 1786/1941/1851 1818/1972/1851 1787/1943/1851 +f 1774/1912/1852 1804/1971/1852 1805/1973/1852 +f 1787/1943/1853 1819/1974/1853 1788/1911/1853 +f 1775/1913/1854 1805/1973/1854 1806/1975/1854 +f 1789/1914/1855 1819/1974/1855 1820/1976/1855 +f 1775/1913/1856 1807/1947/1856 1776/1915/1856 +f 1795/1949/1857 1827/1977/1857 1796/1952/1857 +f 1822/1950/1858 1854/1978/1858 1823/1953/1858 +f 1810/1954/1859 1840/1979/1859 1841/1980/1859 +f 1796/1952/1860 1828/1981/1860 1797/1955/1860 +f 1824/1956/1861 1854/1978/1861 1855/1982/1861 +f 1810/1954/1862 1842/1983/1862 1811/1957/1862 +f 1798/1958/1863 1828/1981/1863 1829/1984/1863 +f 1887/1985/1864 1824/1956/1864 1855/1982/1864 +f 1812/1960/1865 1842/1983/1865 1843/1986/1865 +f 1798/1958/1866 1830/1987/1866 1799/1961/1866 +f 1812/1960/1867 1844/1988/1867 1813/1962/1867 +f 1800/1963/1868 1830/1987/1868 1831/1989/1868 +f 1814/1964/1869 1844/1988/1869 1845/1990/1869 +f 1800/1963/1870 1832/1991/1870 1801/1965/1870 +f 1814/1964/1871 1846/1992/1871 1815/1966/1871 +f 1801/1965/1872 1833/1993/1872 1802/1967/1872 +f 1816/1968/1873 1846/1992/1873 1847/1994/1873 +f 1802/1967/1874 1834/1995/1874 1803/1969/1874 +f 1816/1968/1875 1848/1996/1875 1817/1970/1875 +f 1803/1969/1876 1835/1997/1876 1804/1971/1876 +f 1817/1970/1877 1849/1998/1877 1818/1972/1877 +f 1805/1973/1878 1835/1997/1878 1836/1999/1878 +f 1818/1972/1879 1850/2000/1879 1819/1974/1879 +f 1806/1975/1880 1836/1999/1880 1837/2001/1880 +f 1820/1976/1881 1850/2000/1881 1851/2002/1881 +f 1806/1975/1882 1838/2003/1882 1807/1947/1882 +f 1794/1945/1883 1452/2004/1883 1825/2005/1883 +f 1820/1976/1884 1852/2006/1884 1821/1946/1884 +f 1808/1948/1885 1838/2003/1885 1839/2007/1885 +f 1794/1945/1886 1826/2008/1886 1795/1949/1886 +f 1821/1946/1887 1853/2009/1887 1822/1950/1887 +f 1808/1948/1888 1840/1979/1888 1809/1951/1888 +f 1828/1981/1889 1860/2010/1889 1829/1984/1889 +f 1887/2011/1890 1855/1982/1890 1886/2012/1890 +f 1843/1986/1891 1873/2013/1891 1874/2014/1891 +f 1829/1984/1892 1861/2015/1892 1830/1987/1892 +f 1843/1986/1893 1875/2016/1893 1844/1988/1893 +f 1831/1989/1894 1861/2015/1894 1862/2017/1894 +f 1845/1990/1895 1875/2016/1895 1876/2018/1895 +f 1832/1991/1896 1862/2017/1896 1863/2019/1896 +f 1845/1990/1897 1877/2020/1897 1846/1992/1897 +f 1832/1991/1898 1864/2021/1898 1833/1993/1898 +f 1847/1994/1899 1877/2020/1899 1878/2022/1899 +f 1833/1993/1900 1865/2023/1900 1834/1995/1900 +f 1847/1994/1901 1879/2024/1901 1848/1996/1901 +f 1834/1995/1902 1866/2025/1902 1835/1997/1902 +f 1848/1996/1903 1880/2026/1903 1849/1998/1903 +f 1836/1999/1904 1866/2025/1904 1867/2027/1904 +f 1849/1998/1905 1881/2028/1905 1850/2000/1905 +f 1837/2001/1906 1867/2027/1906 1868/2029/1906 +f 1851/2002/1907 1881/2028/1907 1882/2030/1907 +f 1837/2001/1908 1869/2031/1908 1838/2003/1908 +f 1825/2005/1909 1452/2032/1909 1856/2033/1909 +f 1852/2006/1910 1882/2030/1910 1883/2034/1910 +f 1839/2007/1911 1869/2031/1911 1870/2035/1911 +f 1825/2005/1912 1857/2036/1912 1826/2008/1912 +f 1852/2006/1913 1884/2037/1913 1853/2009/1913 +f 1839/2007/1914 1871/2038/1914 1840/1979/1914 +f 1826/2008/1915 1858/2039/1915 1827/1977/1915 +f 1853/2009/1916 1885/2040/1916 1854/1978/1916 +f 1841/1980/1917 1871/2038/1917 1872/2041/1917 +f 1827/1977/1918 1859/2042/1918 1828/1981/1918 +f 1855/1982/1919 1885/2040/1919 1886/2012/1919 +f 1841/1980/1920 1873/2013/1920 1842/1983/1920 +f 1862/2017/1921 1893/2043/1921 1894/2044/1921 +f 1876/2018/1922 1907/2045/1922 1908/2046/1922 +f 1862/2017/1923 1895/2047/1923 1863/2019/1923 +f 1877/2020/1924 1908/2046/1924 1909/2048/1924 +f 1863/2019/1925 1896/2049/1925 1864/2021/1925 +f 1878/2022/1926 1909/2048/1926 1910/2050/1926 +f 1864/2021/1927 1897/2051/1927 1865/2023/1927 +f 1878/2022/1928 1911/2052/1928 1879/2024/1928 +f 1865/2023/1929 1898/2053/1929 1866/2025/1929 +f 1879/2024/1930 1912/2054/1930 1880/2026/1930 +f 1867/2027/1931 1898/2053/1931 1899/2055/1931 +f 1881/2028/1932 1912/2054/1932 1913/2056/1932 +f 1868/2029/1933 1899/2055/1933 1900/2057/1933 +f 1882/2030/1934 1913/2056/1934 1914/2058/1934 +f 1868/2029/1935 1901/2059/1935 1869/2031/1935 +f 1856/2033/1936 1452/2060/1936 1888/2061/1936 +f 1883/2034/1937 1914/2058/1937 1915/2062/1937 +f 1870/2035/1938 1901/2059/1938 1902/2063/1938 +f 1856/2033/1939 1889/2064/1939 1857/2036/1939 +f 1883/2034/1940 1916/2065/1940 1884/2037/1940 +f 1870/2035/1941 1903/2066/1941 1871/2038/1941 +f 1857/2036/1942 1890/2067/1942 1858/2039/1942 +f 1884/2037/1943 1917/2068/1943 1885/2040/1943 +f 1872/2041/1944 1903/2066/1944 1904/2069/1944 +f 1859/2042/1945 1890/2067/1945 1891/2070/1945 +f 1885/2040/1946 1918/2071/1946 1886/2012/1946 +f 1872/2041/1947 1905/2072/1947 1873/2013/1947 +f 1859/2042/1948 1892/2073/1948 1860/2010/1948 +f 1887/2074/1949 1886/2012/1949 1918/2071/1949 +f 1874/2014/1950 1905/2072/1950 1906/2075/1950 +f 1860/2010/1951 1893/2043/1951 1861/2015/1951 +f 1874/2014/1952 1907/2045/1952 1875/2016/1952 +f 1895/2047/1953 1927/2076/1953 1896/2049/1953 +f 1910/2050/1954 1940/2077/1954 1941/2078/1954 +f 1896/2049/1955 1928/2079/1955 1897/2051/1955 +f 1910/2050/1956 1942/2080/1956 1911/2052/1956 +f 1897/2051/1957 1929/2081/1957 1898/2053/1957 +f 1911/2052/1958 1943/2082/1958 1912/2054/1958 +f 1899/2055/1959 1929/2081/1959 1930/2083/1959 +f 1913/2056/1960 1943/2082/1960 1944/2084/1960 +f 1900/2057/1961 1930/2083/1961 1931/2085/1961 +f 1914/2058/1962 1944/2084/1962 1945/2086/1962 +f 1900/2057/1963 1932/2087/1963 1901/2059/1963 +f 1888/2061/1964 1452/2088/1964 1919/2089/1964 +f 1915/2062/1965 1945/2086/1965 1946/2090/1965 +f 1902/2063/1966 1932/2087/1966 1933/2091/1966 +f 1888/2061/1967 1920/2092/1967 1889/2064/1967 +f 1915/2062/1968 1947/2093/1968 1916/2065/1968 +f 1902/2063/1969 1934/2094/1969 1903/2066/1969 +f 1890/2067/1970 1920/2092/1970 1921/2095/1970 +f 1916/2065/1971 1948/2096/1971 1917/2068/1971 +f 1904/2069/1972 1934/2094/1972 1935/2097/1972 +f 1891/2070/1973 1921/2095/1973 1922/2098/1973 +f 1917/2068/1974 1949/2099/1974 1918/2071/1974 +f 1904/2069/1975 1936/2100/1975 1905/2072/1975 +f 1892/2073/1976 1922/2098/1976 1923/2101/1976 +f 1887/2102/1977 1918/2071/1977 1949/2099/1977 +f 1906/2075/1978 1936/2100/1978 1937/2103/1978 +f 1893/2043/1979 1923/2101/1979 1924/2104/1979 +f 1906/2075/1980 1938/2105/1980 1907/2045/1980 +f 1894/2044/1981 1924/2104/1981 1925/2106/1981 +f 1908/2046/1982 1938/2105/1982 1939/2107/1982 +f 1895/2047/1983 1925/2106/1983 1926/2108/1983 +f 1909/2048/1984 1939/2107/1984 1940/2077/1984 +f 1928/2079/1985 1960/2109/1985 1929/2081/1985 +f 1942/2080/1986 1974/2110/1986 1943/2082/1986 +f 1930/2083/1987 1960/2109/1987 1961/2111/1987 +f 1943/2082/1988 1975/2112/1988 1944/2084/1988 +f 1931/2085/1989 1961/2111/1989 1962/2113/1989 +f 1944/2084/1990 1976/2114/1990 1945/2086/1990 +f 1931/2085/1991 1963/2115/1991 1932/2087/1991 +f 1919/2089/1992 1452/2116/1992 1950/2117/1992 +f 1945/2086/1993 1977/2118/1993 1946/2090/1993 +f 1933/2091/1994 1963/2115/1994 1964/2119/1994 +f 1919/2089/1995 1951/2120/1995 1920/2092/1995 +f 1946/2090/1996 1978/2121/1996 1947/2093/1996 +f 1933/2091/1997 1965/2122/1997 1934/2094/1997 +f 1920/2092/1998 1952/2123/1998 1921/2095/1998 +f 1947/2093/1999 1979/2124/1999 1948/2096/1999 +f 1935/2097/2000 1965/2122/2000 1966/2125/2000 +f 1922/2098/2001 1952/2123/2001 1953/2126/2001 +f 1949/2099/2002 1979/2124/2002 1980/2127/2002 +f 1935/2097/2003 1967/2128/2003 1936/2100/2003 +f 1922/2098/2004 1954/2129/2004 1923/2101/2004 +f 1887/2130/2005 1949/2099/2005 1980/2127/2005 +f 1937/2103/2006 1967/2128/2006 1968/2131/2006 +f 1924/2104/2007 1954/2129/2007 1955/2132/2007 +f 1937/2103/2008 1969/2133/2008 1938/2105/2008 +f 1924/2104/2009 1956/2134/2009 1925/2106/2009 +f 1939/2107/2010 1969/2133/2010 1970/2135/2010 +f 1926/2108/2011 1956/2134/2011 1957/2136/2011 +f 1940/2077/2012 1970/2135/2012 1971/2137/2012 +f 1926/2108/2013 1958/2138/2013 1927/2076/2013 +f 1941/2078/2014 1971/2137/2014 1972/2139/2014 +f 1927/2076/2015 1959/2140/2015 1928/2079/2015 +f 1941/2078/2016 1973/2141/2016 1942/2080/2016 +f 1962/2113/2017 11/13/2017 12/17/2017 +f 1975/2112/2018 24/19/2018 1976/2114/2018 +f 1962/2113/2019 13/21/2019 1963/2115/2019 +f 1950/2117/2020 1452/2142/2020 1/23/2020 +f 1976/2114/2021 1984/27/2021 1977/2118/2021 +f 1964/2119/2022 13/21/2022 14/28/2022 +f 1951/2120/2023 1/23/2023 2/31/2023 +f 1977/2118/2024 25/33/2024 1978/2121/2024 +f 1964/2119/2025 15/35/2025 1965/2122/2025 +f 1951/2120/2026 3/37/2026 1952/2123/2026 +f 1979/2124/2027 25/33/2027 1985/39/2027 +f 1966/2125/2028 15/35/2028 16/41/2028 +f 1953/2126/2029 3/37/2029 4/42/2029 +f 1979/2124/2030 1986/45/2030 1980/2127/2030 +f 1966/2125/2031 1982/47/2031 1967/2128/2031 +f 1954/2129/2032 4/42/2032 5/48/2032 +f 1887/2143/2033 1980/2127/2033 1986/45/2033 +f 1968/2131/2034 1982/47/2034 17/51/2034 +f 1955/2132/2035 5/48/2035 6/54/2035 +f 1968/2131/2036 1983/56/2036 1969/2133/2036 +f 1956/2134/2037 6/54/2037 7/58/2037 +f 1970/2135/2038 1983/56/2038 18/60/2038 +f 1957/2136/2039 7/58/2039 8/62/2039 +f 1970/2135/2040 19/63/2040 1971/2137/2040 +f 1958/2138/2041 8/62/2041 9/4/2041 +f 1971/2137/2042 20/1/2042 1972/2139/2042 +f 1959/2140/2043 9/4/2043 10/6/2043 +f 1972/2139/2044 21/7/2044 1973/2141/2044 +f 1960/2109/2045 10/6/2045 1981/9/2045 +f 1973/2141/2046 22/11/2046 1974/2110/2046 +f 1961/2111/2047 1981/9/2047 11/13/2047 +f 1974/2110/2048 23/15/2048 1975/2112/2048 +f 20/1/1 19/63/1 47/2/1 +f 9/4/2 34/64/2 35/5/2 +f 21/7/3 20/1/3 48/3/3 +f 1981/9/4 10/6/4 35/5/4 +f 22/11/5 21/7/5 49/8/5 +f 11/13/6 1981/9/6 36/10/6 +f 23/15/7 22/11/7 50/12/7 +f 12/17/8 11/13/8 37/14/8 +f 24/19/9 23/15/9 51/16/9 +f 13/21/10 12/17/10 38/18/10 +f 24/19/12 52/20/12 53/26/12 +f 14/28/13 13/21/13 39/22/13 +f 1/23/14 26/25/14 27/30/14 +f 1984/27/15 53/26/15 54/32/15 +f 14/28/16 40/29/16 41/34/16 +f 2/31/17 27/30/17 28/36/17 +f 25/33/18 54/32/18 55/38/18 +f 15/35/19 41/34/19 42/40/19 +f 4/42/20 3/37/20 28/36/20 +f 1985/39/21 55/38/21 56/44/21 +f 16/41/22 42/40/22 43/46/22 +f 5/48/23 4/42/23 29/43/23 +f 17/51/25 1982/47/25 43/46/25 +f 5/48/26 30/49/26 31/53/26 +f 17/51/27 44/52/27 45/55/27 +f 6/54/28 31/53/28 32/57/28 +f 1983/56/29 45/55/29 46/59/29 +f 7/58/30 32/57/30 33/61/30 +f 18/60/31 46/59/31 47/2/31 +f 8/62/32 33/61/32 34/64/32 +f 42/40/33 73/96/33 74/65/33 +f 29/43/34 60/97/34 61/66/34 +f 43/46/36 74/65/36 75/69/36 +f 30/49/37 61/66/37 62/70/37 +f 44/52/38 75/69/38 76/71/38 +f 31/53/39 62/70/39 63/72/39 +f 45/55/40 76/71/40 77/73/40 +f 32/57/41 63/72/41 64/74/41 +f 46/59/42 77/73/42 78/75/42 +f 34/64/43 33/61/43 64/74/43 +f 47/2/44 78/75/44 79/77/44 +f 34/64/45 65/76/45 66/78/45 +f 48/3/46 79/77/46 80/79/46 +f 36/10/47 35/5/47 66/78/47 +f 50/12/48 49/8/48 80/79/48 +f 36/10/49 67/80/49 68/82/49 +f 51/16/50 50/12/50 81/81/50 +f 38/18/51 37/14/51 68/82/51 +f 52/20/52 51/16/52 82/83/52 +f 38/18/53 69/84/53 70/86/53 +f 52/20/55 83/85/55 84/89/55 +f 39/22/56 70/86/56 71/90/56 +f 26/25/57 57/88/57 58/91/57 +f 53/26/58 84/89/58 85/92/58 +f 41/34/59 40/29/59 71/90/59 +f 28/36/60 27/30/60 58/91/60 +f 54/32/61 85/92/61 86/95/61 +f 41/34/62 72/93/62 73/96/62 +f 28/36/63 59/94/63 60/97/63 +f 55/38/64 86/95/64 87/68/64 +f 76/71/65 75/69/65 106/98/65 +f 62/70/66 93/130/66 94/100/66 +f 76/71/67 107/99/67 108/101/67 +f 63/72/68 94/100/68 95/102/68 +f 78/75/69 77/73/69 108/101/69 +f 64/74/70 95/102/70 96/104/70 +f 78/75/71 109/103/71 110/105/71 +f 66/78/72 65/76/72 96/104/72 +f 79/77/73 110/105/73 111/107/73 +f 67/80/74 66/78/74 97/106/74 +f 81/81/75 80/79/75 111/107/75 +f 67/80/76 98/108/76 99/110/76 +f 82/83/77 81/81/77 112/109/77 +f 68/82/78 99/110/78 100/112/78 +f 83/85/79 82/83/79 113/111/79 +f 69/84/80 100/112/80 101/114/80 +f 83/85/82 114/113/82 115/117/82 +f 71/90/83 70/86/83 101/114/83 +f 57/88/84 88/116/84 89/119/84 +f 85/92/85 84/89/85 115/117/85 +f 71/90/86 102/118/86 103/121/86 +f 58/91/87 89/119/87 90/122/87 +f 85/92/88 116/120/88 117/123/88 +f 72/93/89 103/121/89 104/124/89 +f 60/97/90 59/94/90 90/122/90 +f 86/95/91 117/123/91 118/126/91 +f 73/96/92 104/124/92 105/127/92 +f 61/66/93 60/97/93 91/125/93 +f 74/65/95 105/127/95 106/98/95 +f 61/66/96 92/128/96 93/130/96 +f 108/101/97 139/162/97 140/131/97 +f 95/102/98 126/163/98 127/132/98 +f 109/103/99 140/131/99 141/133/99 +f 97/106/100 96/104/100 127/132/100 +f 110/105/101 141/133/101 142/135/101 +f 98/108/102 97/106/102 128/134/102 +f 112/109/103 111/107/103 142/135/103 +f 98/108/104 129/136/104 130/138/104 +f 112/109/105 143/137/105 144/139/105 +f 99/110/106 130/138/106 131/140/106 +f 113/111/107 144/139/107 145/141/107 +f 100/112/108 131/140/108 132/142/108 +f 114/113/110 145/141/110 146/145/110 +f 102/118/111 101/114/111 132/142/111 +f 88/116/112 119/144/112 120/147/112 +f 115/117/113 146/145/113 147/148/113 +f 102/118/114 133/146/114 134/149/114 +f 90/122/2049 89/119/2049 120/147/2049 +f 116/120/116 147/148/116 148/151/116 +f 103/121/117 134/149/117 135/152/117 +f 91/125/118 90/122/118 121/150/118 +f 118/126/119 117/123/119 148/151/119 +f 104/124/120 135/152/120 136/155/120 +f 92/128/121 91/125/121 122/153/121 +f 105/127/123 136/155/123 137/158/123 +f 93/130/124 92/128/124 123/156/124 +f 106/98/125 137/158/125 138/160/125 +f 94/100/126 93/130/126 124/159/126 +f 108/101/127 107/99/127 138/160/127 +f 94/100/128 125/161/128 126/163/128 +f 142/135/129 141/133/129 172/164/129 +f 129/136/130 128/134/130 159/166/130 +f 142/135/131 173/165/131 174/168/131 +f 129/136/132 160/167/132 161/169/132 +f 143/137/133 174/168/133 175/170/133 +f 130/138/134 161/169/134 162/171/134 +f 144/139/135 175/170/135 176/172/135 +f 131/140/136 162/171/136 163/173/136 +f 146/145/138 145/141/138 176/172/138 +f 133/146/139 132/142/139 163/173/139 +f 119/144/140 150/175/140 151/178/140 +f 146/145/141 177/176/141 178/179/141 +f 133/146/142 164/177/142 165/180/142 +f 120/147/143 151/178/143 152/181/143 +f 147/148/144 178/179/144 179/182/144 +f 134/149/145 165/180/145 166/183/145 +f 121/150/146 152/181/146 153/184/146 +f 149/154/147 148/151/147 179/182/147 +f 136/155/148 135/152/148 166/183/148 +f 122/153/149 153/184/149 154/187/149 +f 136/155/151 167/186/151 168/189/151 +f 123/156/152 154/187/152 155/190/152 +f 137/158/153 168/189/153 169/191/153 +f 125/161/154 124/159/154 155/190/154 +f 138/160/155 169/191/155 170/193/155 +f 125/161/156 156/192/156 157/194/156 +f 140/131/157 139/162/157 170/193/157 +f 126/163/158 157/194/158 158/196/158 +f 140/131/159 171/195/159 172/164/159 +f 128/134/160 127/132/160 158/196/160 +f 174/168/161 205/228/161 206/197/161 +f 161/169/162 192/229/162 193/198/162 +f 176/172/2050 175/170/2050 206/197/2050 +f 162/171/164 193/198/164 194/200/164 +f 176/172/166 207/199/166 208/203/166 +f 164/177/167 163/173/167 194/200/167 +f 150/175/168 181/202/168 182/205/168 +f 177/176/169 208/203/169 209/206/169 +f 164/177/170 195/204/170 196/207/170 +f 152/181/171 151/178/171 182/205/171 +f 178/179/2051 209/206/2051 210/209/2051 +f 166/183/173 165/180/173 196/207/173 +f 153/184/174 152/181/174 183/208/174 +f 179/182/175 210/209/175 211/212/175 +f 166/183/176 197/210/176 198/213/176 +f 153/184/177 184/211/177 185/214/177 +f 168/189/179 167/186/179 198/213/179 +f 154/187/180 185/214/180 186/217/180 +f 169/191/181 168/189/181 199/216/181 +f 156/192/182 155/190/182 186/217/182 +f 170/193/183 169/191/183 200/218/183 +f 156/192/184 187/219/184 188/221/184 +f 171/195/185 170/193/185 201/220/185 +f 158/196/186 157/194/186 188/221/186 +f 171/195/187 202/222/187 203/224/187 +f 159/166/188 158/196/188 189/223/188 +f 173/165/189 172/164/189 203/224/189 +f 160/167/190 159/166/190 190/225/190 +f 173/165/191 204/226/191 205/228/191 +f 160/167/192 191/227/192 192/229/192 +f 207/199/194 238/262/194 239/232/194 +f 195/204/195 194/200/195 225/233/195 +f 181/202/196 212/231/196 213/235/196 +f 208/203/197 239/232/197 240/236/197 +f 195/204/198 226/234/198 227/237/198 +f 182/205/199 213/235/199 214/238/199 +f 209/206/200 240/236/200 241/239/200 +f 197/210/201 196/207/201 227/237/201 +f 184/211/202 183/208/202 214/238/202 +f 210/209/203 241/239/203 242/242/203 +f 197/210/204 228/240/204 229/243/204 +f 184/211/205 215/241/205 216/244/205 +f 199/216/207 198/213/207 229/243/207 +f 186/217/208 185/214/208 216/244/208 +f 199/216/209 230/246/209 231/248/209 +f 187/219/210 186/217/210 217/247/210 +f 201/220/211 200/218/211 231/248/211 +f 188/221/212 187/219/212 218/249/212 +f 202/222/213 201/220/213 232/250/213 +f 188/221/214 219/251/214 220/253/214 +f 203/224/215 202/222/215 233/252/215 +f 189/223/216 220/253/216 221/255/216 +f 204/226/217 203/224/217 234/254/217 +f 191/227/218 190/225/218 221/255/218 +f 204/226/219 235/256/219 236/258/219 +f 191/227/2052 222/257/2052 223/259/2052 +f 205/228/221 236/258/221 237/260/221 +f 193/198/222 192/229/222 223/259/222 +f 206/197/223 237/260/223 238/262/223 +f 193/198/224 224/261/224 225/233/224 +f 213/235/225 244/294/225 245/263/225 +f 240/236/226 271/295/226 272/264/226 +f 228/240/227 227/237/227 258/265/227 +f 215/241/228 214/238/228 245/263/228 +f 241/239/2053 272/264/2053 273/268/2053 +f 228/240/2054 259/266/2054 260/269/2054 +f 215/241/231 246/267/231 247/270/231 +f 230/246/233 229/243/233 260/269/233 +f 216/244/234 247/270/234 248/273/234 +f 230/246/235 261/272/235 262/274/235 +f 217/247/236 248/273/236 249/275/236 +f 232/250/237 231/248/237 262/274/237 +f 219/251/238 218/249/238 249/275/238 +f 233/252/239 232/250/239 263/276/239 +f 219/251/240 250/277/240 251/279/240 +f 234/254/241 233/252/241 264/278/241 +f 220/253/242 251/279/242 252/281/242 +f 235/256/243 234/254/243 265/280/243 +f 222/257/244 221/255/244 252/281/244 +f 235/256/245 266/282/245 267/284/245 +f 222/257/246 253/283/246 254/285/246 +f 236/258/247 267/284/247 268/286/247 +f 224/261/248 223/259/248 254/285/248 +f 237/260/249 268/286/249 269/288/249 +f 224/261/250 255/287/250 256/289/250 +f 238/262/252 269/288/252 270/292/252 +f 226/234/253 225/233/253 256/289/253 +f 212/231/2055 243/291/2055 244/294/2055 +f 239/232/255 270/292/255 271/295/255 +f 226/234/256 257/293/256 258/265/256 +f 246/267/257 277/328/257 278/296/257 +f 261/272/259 260/269/259 291/299/259 +f 247/270/260 278/296/260 279/301/260 +f 261/272/261 292/300/261 293/302/261 +f 249/275/262 248/273/262 279/301/262 +f 263/276/263 262/274/263 293/302/263 +f 250/277/264 249/275/264 280/303/264 +f 264/278/265 263/276/265 294/304/265 +f 250/277/266 281/305/266 282/307/266 +f 264/278/267 295/306/267 296/308/267 +f 252/281/268 251/279/268 282/307/268 +f 266/282/269 265/280/269 296/308/269 +f 252/281/270 283/309/270 284/311/270 +f 266/282/271 297/310/271 298/312/271 +f 253/283/272 284/311/272 285/313/272 +f 268/286/273 267/284/273 298/312/273 +f 255/287/274 254/285/274 285/313/274 +f 269/288/275 268/286/275 299/314/275 +f 255/287/276 286/315/276 287/317/276 +f 269/288/278 300/316/278 301/320/278 +f 257/293/2056 256/289/2056 287/317/2056 +f 243/291/280 274/319/280 275/322/280 +f 271/295/281 270/292/281 301/320/281 +f 257/293/282 288/321/282 289/324/282 +f 244/294/283 275/322/283 276/325/283 +f 271/295/284 302/323/284 303/326/284 +f 259/266/285 258/265/285 289/324/285 +f 246/267/286 245/263/286 276/325/286 +f 273/268/287 272/264/287 303/326/287 +f 259/266/2057 290/327/2057 291/299/2057 +f 279/301/289 310/361/289 311/329/289 +f 294/304/290 293/302/290 324/330/290 +f 281/305/291 280/303/291 311/329/291 +f 295/306/292 294/304/292 325/331/292 +f 281/305/293 312/332/293 313/334/293 +f 295/306/294 326/333/294 327/335/294 +f 283/309/295 282/307/295 313/334/295 +f 296/308/296 327/335/296 328/337/296 +f 284/311/297 283/309/297 314/336/297 +f 297/310/298 328/337/298 329/339/298 +f 285/313/299 284/311/299 315/338/299 +f 299/314/300 298/312/300 329/339/300 +f 286/315/301 285/313/301 316/340/301 +f 300/316/302 299/314/302 330/341/302 +f 286/315/303 317/342/303 318/344/303 +f 300/316/305 331/343/305 332/347/305 +f 288/321/306 287/317/306 318/344/306 +f 274/319/2058 305/346/2058 306/349/2058 +f 301/320/308 332/347/308 333/350/308 +f 288/321/309 319/348/309 320/351/309 +f 275/322/310 306/349/310 307/352/310 +f 302/323/311 333/350/311 334/353/311 +f 290/327/312 289/324/312 320/351/312 +f 277/328/313 276/325/313 307/352/313 +f 304/298/314 303/326/314 334/353/314 +f 290/327/315 321/354/315 322/357/315 +f 277/328/316 308/355/316 309/358/316 +f 292/300/318 291/299/318 322/357/318 +f 278/296/319 309/358/319 310/361/319 +f 292/300/320 323/360/320 324/330/320 +f 312/332/321 343/394/321 344/362/321 +f 327/335/322 326/333/322 357/363/322 +f 313/334/323 344/362/323 345/365/323 +f 328/337/324 327/335/324 358/364/324 +f 315/338/325 314/336/325 345/365/325 +f 329/339/326 328/337/326 359/366/326 +f 315/338/327 346/367/327 347/369/327 +f 330/341/328 329/339/328 360/368/328 +f 317/342/329 316/340/329 347/369/329 +f 330/341/330 361/370/330 362/372/330 +f 317/342/331 348/371/331 349/373/331 +f 331/343/333 362/372/333 363/376/333 +f 319/348/334 318/344/334 349/373/334 +f 305/346/335 336/375/335 337/378/335 +f 332/347/336 363/376/336 364/379/336 +f 319/348/337 350/377/337 351/380/337 +f 307/352/338 306/349/338 337/378/338 +f 333/350/339 364/379/339 365/382/339 +f 321/354/340 320/351/340 351/380/340 +f 308/355/341 307/352/341 338/381/341 +f 335/356/342 334/353/342 365/382/342 +f 321/354/343 352/383/343 353/386/343 +f 309/358/344 308/355/344 339/384/344 +f 323/360/346 322/357/346 353/386/346 +f 310/361/347 309/358/347 340/387/347 +f 323/360/348 354/389/348 355/391/348 +f 310/361/349 341/390/349 342/392/349 +f 325/331/350 324/330/350 355/391/350 +f 311/329/351 342/392/351 343/394/351 +f 326/333/352 325/331/352 356/393/352 +f 346/367/353 345/365/353 376/395/353 +f 360/368/354 359/366/354 390/397/354 +f 346/367/355 377/396/355 378/399/355 +f 361/370/356 360/368/356 391/398/356 +f 348/371/357 347/369/357 378/399/357 +f 362/372/358 361/370/358 392/400/358 +f 348/371/359 379/401/359 380/403/359 +f 362/372/361 393/402/361 394/406/361 +f 350/377/362 349/373/362 380/403/362 +f 336/375/363 367/405/363 368/408/363 +f 364/379/364 363/376/364 394/406/364 +f 350/377/365 381/407/365 382/410/365 +f 337/378/366 368/408/366 369/411/366 +f 364/379/367 395/409/367 396/412/367 +f 351/380/368 382/410/368 383/413/368 +f 339/384/369 338/381/369 369/411/369 +f 366/385/370 365/382/370 396/412/370 +f 352/383/371 383/413/371 384/416/371 +f 339/384/372 370/414/372 371/417/372 +f 354/389/374 353/386/374 384/416/374 +f 341/390/375 340/387/375 371/417/375 +f 354/389/376 385/419/376 386/421/376 +f 341/390/377 372/420/377 373/422/377 +f 356/393/378 355/391/378 386/421/378 +f 342/392/379 373/422/379 374/424/379 +f 357/363/380 356/393/380 387/423/380 +f 344/362/381 343/394/381 374/424/381 +f 358/364/382 357/363/382 388/425/382 +f 345/365/383 344/362/383 375/426/383 +f 359/366/384 358/364/384 389/427/384 +f 378/399/385 409/460/385 410/428/385 +f 393/402/2059 392/400/2059 423/429/2059 +f 379/401/387 410/428/387 411/431/387 +f 393/402/389 424/430/389 425/434/389 +f 381/407/390 380/403/390 411/431/390 +f 367/405/391 398/433/391 399/436/391 +f 395/409/392 394/406/392 425/434/392 +f 381/407/393 412/435/393 413/438/393 +f 369/411/394 368/408/394 399/436/394 +f 395/409/2060 426/437/2060 427/440/2060 +f 383/413/396 382/410/396 413/438/396 +f 370/414/397 369/411/397 400/439/397 +f 397/415/398 396/412/398 427/440/398 +f 383/413/399 414/441/399 415/444/399 +f 370/414/400 401/442/400 402/445/400 +f 385/419/402 384/416/402 415/444/402 +f 371/417/2061 402/445/2061 403/448/2061 +f 385/419/404 416/447/404 417/449/404 +f 372/420/405 403/448/405 404/450/405 +f 387/423/406 386/421/406 417/449/406 +f 373/422/407 404/450/407 405/452/407 +f 388/425/408 387/423/408 418/451/408 +f 374/424/409 405/452/409 406/454/409 +f 389/427/410 388/425/410 419/453/410 +f 375/426/411 406/454/411 407/456/411 +f 389/427/412 420/455/412 421/457/412 +f 377/396/413 376/395/413 407/456/413 +f 391/398/414 390/397/414 421/457/414 +f 377/396/415 408/458/415 409/460/415 +f 392/400/416 391/398/416 422/459/416 +f 412/435/417 411/431/417 442/461/417 +f 398/433/418 429/492/418 430/463/418 +f 425/434/419 456/493/419 457/464/419 +f 412/435/420 443/462/420 444/465/420 +f 399/436/421 430/463/421 431/466/421 +f 426/437/422 457/464/422 458/467/422 +f 414/441/423 413/438/423 444/465/423 +f 401/442/424 400/439/424 431/466/424 +f 427/440/425 458/467/425 459/470/425 +f 414/441/426 445/468/426 446/471/426 +f 402/445/2062 401/442/2062 432/469/2062 +f 416/447/429 415/444/429 446/471/429 +f 403/448/430 402/445/430 433/472/430 +f 416/447/431 447/474/431 448/476/431 +f 403/448/432 434/475/432 435/477/432 +f 418/451/433 417/449/433 448/476/433 +f 405/452/434 404/450/434 435/477/434 +f 419/453/435 418/451/435 449/478/435 +f 405/452/436 436/479/436 437/481/436 +f 420/455/437 419/453/437 450/480/437 +f 406/454/438 437/481/438 438/483/438 +f 420/455/439 451/482/439 452/484/439 +f 408/458/440 407/456/440 438/483/440 +f 422/459/441 421/457/441 452/484/441 +f 408/458/442 439/485/442 440/487/442 +f 423/429/443 422/459/443 453/486/443 +f 409/460/444 440/487/444 441/489/444 +f 423/429/445 454/488/445 455/490/445 +f 410/428/446 441/489/446 442/461/446 +f 424/430/2063 455/490/2063 456/493/2063 +f 445/468/449 444/465/449 475/494/449 +f 432/469/450 431/466/450 462/496/450 +f 458/467/451 489/526/451 490/498/451 +f 445/468/452 476/495/452 477/499/452 +f 432/469/453 463/497/453 464/500/453 +f 447/474/455 446/471/455 477/499/455 +f 433/472/456 464/500/456 465/503/456 +f 447/474/457 478/502/457 479/504/457 +f 434/475/458 465/503/458 466/505/458 +f 449/478/459 448/476/459 479/504/459 +f 435/477/460 466/505/460 467/507/460 +f 450/480/461 449/478/461 480/506/461 +f 437/481/462 436/479/462 467/507/462 +f 450/480/463 481/508/463 482/510/463 +f 437/481/464 468/509/464 469/511/464 +f 451/482/465 482/510/465 483/512/465 +f 439/485/466 438/483/466 469/511/466 +f 453/486/467 452/484/467 483/512/467 +f 439/485/468 470/513/468 471/515/468 +f 453/486/469 484/514/469 485/516/469 +f 440/487/470 471/515/470 472/517/470 +f 455/490/471 454/488/471 485/516/471 +f 441/489/472 472/517/472 473/519/472 +f 455/490/474 486/518/474 487/522/474 +f 443/462/475 442/461/475 473/519/475 +f 429/492/476 460/521/476 461/524/476 +f 457/464/477 456/493/477 487/522/477 +f 443/462/478 474/523/478 475/494/478 +f 431/466/479 430/463/479 461/524/479 +f 457/464/480 488/525/480 489/526/480 +f 478/502/481 477/499/481 508/527/481 +f 464/500/2064 495/558/2064 496/529/2064 +f 478/502/483 509/528/483 510/530/483 +f 465/503/484 496/529/484 497/531/484 +f 480/506/485 479/504/485 510/530/485 +f 466/505/486 497/531/486 498/533/486 +f 481/508/487 480/506/487 511/532/487 +f 467/507/488 498/533/488 499/535/488 +f 482/510/489 481/508/489 512/534/489 +f 468/509/490 499/535/490 500/537/490 +f 483/512/491 482/510/491 513/536/491 +f 470/513/492 469/511/492 500/537/492 +f 484/514/493 483/512/493 514/538/493 +f 470/513/494 501/539/494 502/541/494 +f 485/516/2065 484/514/2065 515/540/2065 +f 471/515/496 502/541/496 503/543/496 +f 486/518/497 485/516/497 516/542/497 +f 472/517/498 503/543/498 504/545/498 +f 486/518/500 517/544/500 518/548/500 +f 474/523/501 473/519/501 504/545/501 +f 460/521/502 491/547/502 492/550/502 +f 488/525/503 487/522/503 518/548/503 +f 474/523/504 505/549/504 506/552/504 +f 461/524/505 492/550/505 493/553/505 +f 489/526/506 488/525/506 519/551/506 +f 476/495/507 475/494/507 506/552/507 +f 463/497/2066 462/496/2066 493/553/2066 +f 490/498/509 489/526/509 520/554/509 +f 476/495/510 507/555/510 508/527/510 +f 463/497/511 494/556/511 495/558/511 +f 511/532/513 510/530/513 541/560/513 +f 497/531/514 528/592/514 529/562/514 +f 512/534/515 511/532/515 542/561/515 +f 498/533/516 529/562/516 530/564/516 +f 512/534/517 543/563/517 544/565/517 +f 499/535/518 530/564/518 531/566/518 +f 513/536/519 544/565/519 545/567/519 +f 501/539/520 500/537/520 531/566/520 +f 515/540/521 514/538/521 545/567/521 +f 501/539/522 532/568/522 533/570/522 +f 516/542/523 515/540/523 546/569/523 +f 502/541/524 533/570/524 534/572/524 +f 516/542/525 547/571/525 548/573/525 +f 503/543/526 534/572/526 535/574/526 +f 517/544/528 548/573/528 549/577/528 +f 505/549/529 504/545/529 535/574/529 +f 491/547/530 522/576/530 523/579/530 +f 519/551/531 518/548/531 549/577/531 +f 505/549/532 536/578/532 537/581/532 +f 492/550/533 523/579/533 524/582/533 +f 519/551/534 550/580/534 551/583/534 +f 507/555/535 506/552/535 537/581/535 +f 493/553/536 524/582/536 525/585/536 +f 520/554/537 551/583/537 552/586/537 +f 507/555/538 538/584/538 539/587/538 +f 494/556/539 525/585/539 526/588/539 +f 509/528/541 508/527/541 539/587/541 +f 495/558/542 526/588/542 527/591/542 +f 509/528/543 540/590/543 541/560/543 +f 496/529/544 527/591/544 528/592/544 +f 544/565/545 543/563/545 574/593/545 +f 530/564/546 561/625/546 562/595/546 +f 545/567/547 544/565/547 575/594/547 +f 532/568/548 531/566/548 562/595/548 +f 545/567/549 576/596/549 577/598/549 +f 532/568/550 563/597/550 564/599/550 +f 547/571/551 546/569/551 577/598/551 +f 533/570/552 564/599/552 565/601/552 +f 548/573/553 547/571/553 578/600/553 +f 534/572/554 565/601/554 566/603/554 +f 548/573/556 579/602/556 580/606/556 +f 536/578/557 535/574/557 566/603/557 +f 522/576/558 553/605/558 554/608/558 +f 550/580/559 549/577/559 580/606/559 +f 536/578/560 567/607/560 568/610/560 +f 523/579/561 554/608/561 555/611/561 +f 551/583/562 550/580/562 581/609/562 +f 538/584/563 537/581/563 568/610/563 +f 524/582/564 555/611/564 556/614/564 +f 552/586/565 551/583/565 582/612/565 +f 538/584/566 569/613/566 570/616/566 +f 525/585/567 556/614/567 557/617/567 +f 540/590/569 539/587/569 570/616/569 +f 526/588/570 557/617/570 558/620/570 +f 540/590/571 571/619/571 572/621/571 +f 527/591/572 558/620/572 559/622/572 +f 542/561/573 541/560/573 572/621/573 +f 528/592/574 559/622/574 560/624/574 +f 543/563/575 542/561/575 573/623/575 +f 529/562/576 560/624/576 561/625/576 +f 576/596/577 607/657/577 608/626/577 +f 563/597/578 594/658/578 595/627/578 +f 578/600/579 577/598/579 608/626/579 +f 564/599/580 595/627/580 596/629/580 +f 579/602/581 578/600/581 609/628/581 +f 565/601/582 596/629/582 597/631/582 +f 579/602/2067 610/630/2067 611/634/2067 +f 567/607/585 566/603/585 597/631/585 +f 553/605/586 584/633/586 585/636/586 +f 580/606/587 611/634/587 612/637/587 +f 567/607/588 598/635/588 599/638/588 +f 554/608/589 585/636/589 586/639/589 +f 581/609/590 612/637/590 613/640/590 +f 569/613/591 568/610/591 599/638/591 +f 556/614/592 555/611/592 586/639/592 +f 582/612/593 613/640/593 614/643/593 +f 569/613/594 600/641/594 601/644/594 +f 556/614/595 587/642/595 588/645/595 +f 571/619/597 570/616/597 601/644/597 +f 558/620/598 557/617/598 588/645/598 +f 571/619/599 602/647/599 603/649/599 +f 558/620/600 589/648/600 590/650/600 +f 573/623/601 572/621/601 603/649/601 +f 559/622/602 590/650/602 591/652/602 +f 574/593/603 573/623/603 604/651/603 +f 561/625/604 560/624/604 591/652/604 +f 574/593/605 605/653/605 606/655/605 +f 561/625/606 592/654/606 593/656/606 +f 575/594/607 606/655/607 607/657/607 +f 563/597/608 562/595/608 593/656/608 +f 610/630/609 609/628/609 640/659/609 +f 596/629/610 627/691/610 628/661/610 +f 610/630/612 641/660/612 642/664/612 +f 598/635/613 597/631/613 628/661/613 +f 584/633/614 615/663/614 616/666/614 +f 611/634/615 642/664/615 643/667/615 +f 598/635/616 629/665/616 630/668/616 +f 585/636/2068 616/666/2068 617/669/2068 +f 612/637/618 643/667/618 644/670/618 +f 600/641/619 599/638/619 630/668/619 +f 586/639/620 617/669/620 618/672/620 +f 614/643/621 613/640/621 644/670/621 +f 600/641/622 631/671/622 632/674/622 +f 587/642/623 618/672/623 619/675/623 +f 602/647/625 601/644/625 632/674/625 +f 589/648/626 588/645/626 619/675/626 +f 602/647/627 633/677/627 634/679/627 +f 589/648/628 620/678/628 621/680/628 +f 604/651/629 603/649/629 634/679/629 +f 590/650/630 621/680/630 622/682/630 +f 605/653/631 604/651/631 635/681/631 +f 591/652/632 622/682/632 623/684/632 +f 606/655/633 605/653/633 636/683/633 +f 592/654/634 623/684/634 624/686/634 +f 606/655/635 637/685/635 638/687/635 +f 594/658/636 593/656/636 624/686/636 +f 607/657/637 638/687/637 639/689/637 +f 594/658/638 625/688/638 626/690/638 +f 608/626/639 639/689/639 640/659/639 +f 595/627/640 626/690/640 627/691/640 +f 642/664/641 673/722/641 674/692/641 +f 629/665/642 660/723/642 661/693/642 +f 616/666/643 647/724/643 648/694/643 +f 643/667/644 674/692/644 675/695/644 +f 631/671/645 630/668/645 661/693/645 +f 618/672/646 617/669/646 648/694/646 +f 644/670/647 675/695/647 676/698/647 +f 631/671/648 662/696/648 663/699/648 +f 619/675/649 618/672/649 649/697/649 +f 633/677/651 632/674/651 663/699/651 +f 620/678/652 619/675/652 650/700/652 +f 633/677/653 664/702/653 665/704/653 +f 620/678/654 651/703/654 652/705/654 +f 635/681/655 634/679/655 665/704/655 +f 621/680/656 652/705/656 653/707/656 +f 636/683/657 635/681/657 666/706/657 +f 622/682/658 653/707/658 654/709/658 +f 636/683/659 667/708/659 668/710/659 +f 623/684/660 654/709/660 655/711/660 +f 638/687/661 637/685/661 668/710/661 +f 625/688/662 624/686/662 655/711/662 +f 639/689/663 638/687/663 669/712/663 +f 625/688/664 656/713/664 657/715/664 +f 640/659/665 639/689/665 670/714/665 +f 626/690/666 657/715/666 658/717/666 +f 640/659/667 671/716/667 672/718/667 +f 627/691/668 658/717/668 659/719/668 +f 641/660/670 672/718/670 673/722/670 +f 629/665/671 628/661/671 659/719/671 +f 616/666/2069 615/663/2069 646/721/2069 +f 675/695/673 706/755/673 707/725/673 +f 662/696/674 693/756/674 694/726/674 +f 649/697/675 680/757/675 681/727/675 +f 664/702/677 663/699/677 694/726/677 +f 651/703/678 650/700/678 681/727/678 +f 664/702/679 695/729/679 696/731/679 +f 652/705/680 651/703/680 682/730/680 +f 666/706/681 665/704/681 696/731/681 +f 652/705/682 683/732/682 684/734/682 +f 667/708/683 666/706/683 697/733/683 +f 653/707/684 684/734/684 685/736/684 +f 667/708/685 698/735/685 699/737/685 +f 655/711/686 654/709/686 685/736/686 +f 668/710/687 699/737/687 700/739/687 +f 655/711/688 686/738/688 687/740/688 +f 669/712/689 700/739/689 701/741/689 +f 656/713/690 687/740/690 688/742/690 +f 671/716/691 670/714/691 701/741/691 +f 657/715/692 688/742/692 689/744/692 +f 671/716/693 702/743/693 703/745/693 +f 658/717/694 689/744/694 690/746/694 +f 672/718/696 703/745/696 704/749/696 +f 660/723/697 659/719/697 690/746/697 +f 646/721/698 677/748/698 678/751/698 +f 674/692/699 673/722/699 704/749/699 +f 660/723/700 691/750/700 692/753/700 +f 648/694/701 647/724/701 678/751/701 +f 674/692/702 705/752/702 706/755/702 +f 662/696/703 661/693/703 692/753/703 +f 648/694/704 679/754/704 680/757/704 +f 695/729/705 726/789/705 727/758/705 +f 682/730/706 713/790/706 714/759/706 +f 697/733/707 696/731/707 727/758/707 +f 683/732/708 714/759/708 715/761/708 +f 698/735/709 697/733/709 728/760/709 +f 684/734/710 715/761/710 716/763/710 +f 698/735/711 729/762/711 730/764/711 +f 686/738/712 685/736/712 716/763/712 +f 700/739/713 699/737/713 730/764/713 +f 687/740/714 686/738/714 717/765/714 +f 700/739/715 731/766/715 732/768/715 +f 687/740/716 718/767/716 719/769/716 +f 701/741/717 732/768/717 733/770/717 +f 689/744/718 688/742/718 719/769/718 +f 702/743/719 733/770/719 734/772/719 +f 689/744/720 720/771/720 721/773/720 +f 703/745/722 734/772/722 735/776/722 +f 691/750/723 690/746/723 721/773/723 +f 677/748/724 708/775/724 709/778/724 +f 705/752/725 704/749/725 735/776/725 +f 691/750/726 722/777/726 723/780/726 +f 678/751/727 709/778/727 710/781/727 +f 705/752/728 736/779/728 737/782/728 +f 693/756/729 692/753/729 723/780/729 +f 680/757/730 679/754/730 710/781/730 +f 706/755/731 737/782/731 738/785/731 +f 693/756/732 724/783/732 725/786/732 +f 680/757/733 711/784/733 712/787/733 +f 695/729/735 694/726/735 725/786/735 +f 682/730/736 681/727/736 712/787/736 +f 729/762/737 728/760/737 759/791/737 +f 715/761/738 746/823/738 747/793/738 +f 729/762/739 760/792/739 761/794/739 +f 716/763/740 747/793/740 748/795/740 +f 730/764/741 761/794/741 762/796/741 +f 718/767/742 717/765/742 748/795/742 +f 731/766/743 762/796/743 763/798/743 +f 718/767/744 749/797/744 750/799/744 +f 733/770/745 732/768/745 763/798/745 +f 720/771/746 719/769/746 750/799/746 +f 734/772/747 733/770/747 764/800/747 +f 720/771/748 751/801/748 752/803/748 +f 734/772/750 765/802/750 766/806/750 +f 722/777/751 721/773/751 752/803/751 +f 708/775/752 739/805/752 740/808/752 +f 736/779/753 735/776/753 766/806/753 +f 722/777/754 753/807/754 754/810/754 +f 709/778/755 740/808/755 741/811/755 +f 737/782/756 736/779/756 767/809/756 +f 724/783/757 723/780/757 754/810/757 +f 710/781/758 741/811/758 742/814/758 +f 737/782/759 768/812/759 769/815/759 +f 724/783/760 755/813/760 756/816/760 +f 711/784/761 742/814/761 743/817/761 +f 726/789/763 725/786/763 756/816/763 +f 713/790/764 712/787/764 743/817/764 +f 726/789/765 757/819/765 758/821/765 +f 713/790/766 744/820/766 745/822/766 +f 728/760/767 727/758/767 758/821/767 +f 715/761/768 714/759/768 745/822/768 +f 761/794/769 792/855/769 793/824/769 +f 748/795/770 779/856/770 780/825/770 +f 762/796/771 793/824/771 794/826/771 +f 749/797/772 780/825/772 781/827/772 +f 763/798/773 794/826/773 795/828/773 +f 751/801/774 750/799/774 781/827/774 +f 765/802/775 764/800/775 795/828/775 +f 751/801/776 782/829/776 783/831/776 +f 765/802/778 796/830/778 797/834/778 +f 753/807/779 752/803/779 783/831/779 +f 739/805/2070 770/833/2070 771/836/2070 +f 767/809/781 766/806/781 797/834/781 +f 753/807/782 784/835/782 785/838/782 +f 740/808/783 771/836/783 772/839/783 +f 768/812/784 767/809/784 798/837/784 +f 754/810/785 785/838/785 786/841/785 +f 742/814/786 741/811/786 772/839/786 +f 768/812/2071 799/840/2071 800/843/2071 +f 755/813/788 786/841/788 787/844/788 +f 742/814/789 773/842/789 774/845/789 +f 757/819/791 756/816/791 787/844/791 +f 743/817/792 774/845/792 775/848/792 +f 757/819/793 788/847/793 789/849/793 +f 744/820/794 775/848/794 776/850/794 +f 759/791/795 758/821/795 789/849/795 +f 746/823/796 745/822/796 776/850/796 +f 760/792/797 759/791/797 790/851/797 +f 746/823/798 777/852/798 778/854/798 +f 760/792/799 791/853/799 792/855/799 +f 748/795/800 747/793/800 778/854/800 +f 794/826/801 825/889/801 826/857/801 +f 782/829/802 781/827/802 812/858/802 +f 796/830/803 795/828/803 826/857/803 +f 782/829/804 813/859/804 814/861/804 +f 796/830/806 827/860/806 828/864/806 +f 784/835/807 783/831/807 814/861/807 +f 770/833/808 801/863/808 802/866/808 +f 798/837/809 797/834/809 828/864/809 +f 785/838/810 784/835/810 815/865/810 +f 771/836/811 802/866/811 803/869/811 +f 798/837/812 829/867/812 830/870/812 +f 785/838/813 816/868/813 817/871/813 +f 772/839/814 803/869/814 804/872/814 +f 799/840/815 830/870/815 831/873/815 +f 786/841/816 817/871/816 818/874/816 +f 773/842/817 804/872/817 805/875/817 +f 788/847/819 787/844/819 818/874/819 +f 774/845/820 805/875/820 806/878/820 +f 788/847/821 819/877/821 820/879/821 +f 776/850/822 775/848/822 806/878/822 +f 790/851/823 789/849/823 820/879/823 +f 777/852/824 776/850/824 807/880/824 +f 791/853/825 790/851/825 821/881/825 +f 777/852/826 808/882/826 809/884/826 +f 791/853/827 822/883/827 823/885/827 +f 779/856/828 778/854/828 809/884/828 +f 792/855/829 823/885/829 824/887/829 +f 780/825/830 779/856/830 810/886/830 +f 793/824/831 824/887/831 825/889/831 +f 780/825/832 811/888/832 812/858/832 +f 824/887/833 855/921/833 856/890/833 +f 811/888/834 842/922/834 843/891/834 +f 825/889/835 856/890/835 857/892/835 +f 813/859/836 812/858/836 843/891/836 +f 826/857/837 857/892/837 858/894/837 +f 813/859/838 844/893/838 845/895/838 +f 827/860/840 858/894/840 859/898/840 +f 815/865/841 814/861/841 845/895/841 +f 801/863/842 832/897/842 833/900/842 +f 829/867/843 828/864/843 859/898/843 +f 816/868/844 815/865/844 846/899/844 +f 802/866/845 833/900/845 834/903/845 +f 830/870/846 829/867/846 860/901/846 +f 816/868/847 847/902/847 848/905/847 +f 804/872/848 803/869/848 834/903/848 +f 831/873/849 830/870/849 861/904/849 +f 817/871/850 848/905/850 849/908/850 +f 805/875/851 804/872/851 835/906/851 +f 819/877/853 818/874/853 849/908/853 +f 805/875/854 836/909/854 837/912/854 +f 819/877/855 850/911/855 851/913/855 +f 806/878/856 837/912/856 838/914/856 +f 821/881/857 820/879/857 851/913/857 +f 807/880/858 838/914/858 839/916/858 +f 822/883/859 821/881/859 852/915/859 +f 808/882/860 839/916/860 840/918/860 +f 822/883/861 853/917/861 854/919/861 +f 809/884/862 840/918/862 841/920/862 +f 823/885/863 854/919/863 855/921/863 +f 811/888/864 810/886/864 841/920/864 +f 858/894/865 857/892/865 888/923/865 +f 844/893/866 875/955/866 876/925/866 +f 858/894/868 889/924/868 890/928/868 +f 846/899/869 845/895/869 876/925/869 +f 832/897/870 863/927/870 864/930/870 +f 860/901/871 859/898/871 890/928/871 +f 847/902/872 846/899/872 877/929/872 +f 833/900/873 864/930/873 865/933/873 +f 860/901/874 891/931/874 892/934/874 +f 847/902/875 878/932/875 879/935/875 +f 835/906/876 834/903/876 865/933/876 +f 861/904/877 892/934/877 893/937/877 +f 848/905/878 879/935/878 880/938/878 +f 835/906/879 866/936/879 867/939/879 +f 850/911/881 849/908/881 880/938/881 +f 837/912/882 836/909/882 867/939/882 +f 850/911/883 881/941/883 882/943/883 +f 837/912/884 868/942/884 869/944/884 +f 852/915/885 851/913/885 882/943/885 +f 838/914/886 869/944/886 870/946/886 +f 853/917/887 852/915/887 883/945/887 +f 840/918/888 839/916/888 870/946/888 +f 853/917/889 884/947/889 885/949/889 +f 840/918/890 871/948/890 872/950/890 +f 854/919/891 885/949/891 886/951/891 +f 842/922/892 841/920/892 872/950/892 +f 855/921/893 886/951/893 887/953/893 +f 842/922/894 873/952/894 874/954/894 +f 857/892/895 856/890/895 887/953/895 +f 844/893/896 843/891/896 874/954/896 +f 863/927/897 894/987/897 895/956/897 +f 890/928/898 921/988/898 922/957/898 +f 878/932/899 877/929/899 908/958/899 +f 864/930/2072 895/956/2072 896/960/2072 +f 891/931/901 922/957/901 923/961/901 +f 878/932/902 909/959/902 910/962/902 +f 866/936/903 865/933/903 896/960/903 +f 892/934/904 923/961/904 924/964/904 +f 879/935/905 910/962/905 911/965/905 +f 866/936/906 897/963/906 898/966/906 +f 881/941/908 880/938/908 911/965/908 +f 867/939/909 898/966/909 899/969/909 +f 881/941/910 912/968/910 913/970/910 +f 868/942/911 899/969/911 900/971/911 +f 883/945/912 882/943/912 913/970/912 +f 869/944/913 900/971/913 901/973/913 +f 884/947/2073 883/945/2073 914/972/2073 +f 870/946/915 901/973/915 902/975/915 +f 884/947/916 915/974/916 916/976/916 +f 871/948/917 902/975/917 903/977/917 +f 886/951/918 885/949/918 916/976/918 +f 873/952/919 872/950/919 903/977/919 +f 886/951/920 917/978/920 918/980/920 +f 873/952/921 904/979/921 905/981/921 +f 888/923/922 887/953/922 918/980/922 +f 875/955/923 874/954/923 905/981/923 +f 889/924/924 888/923/924 919/982/924 +f 875/955/925 906/983/925 907/985/925 +f 890/928/927 889/924/927 920/984/927 +f 877/929/928 876/925/928 907/985/928 +f 897/963/929 896/960/929 927/989/929 +f 923/961/930 954/1020/930 955/991/930 +f 910/962/931 941/1021/931 942/992/931 +f 897/963/932 928/990/932 929/993/932 +f 912/968/934 911/965/934 942/992/934 +f 898/966/935 929/993/935 930/996/935 +f 912/968/936 943/995/936 944/997/936 +f 899/969/937 930/996/937 931/998/937 +f 914/972/938 913/970/938 944/997/938 +f 901/973/939 900/971/939 931/998/939 +f 915/974/940 914/972/940 945/999/940 +f 902/975/941 901/973/941 932/1000/941 +f 916/976/942 915/974/942 946/1001/942 +f 902/975/943 933/1002/943 934/1004/943 +f 916/976/944 947/1003/944 948/1005/944 +f 904/979/945 903/977/945 934/1004/945 +f 917/978/946 948/1005/946 949/1007/946 +f 904/979/947 935/1006/947 936/1008/947 +f 919/982/948 918/980/948 949/1007/948 +f 906/983/949 905/981/949 936/1008/949 +f 920/984/950 919/982/950 950/1009/950 +f 906/983/951 937/1010/951 938/1012/951 +f 920/984/2074 951/1011/2074 952/1015/2074 +f 908/958/954 907/985/954 938/1012/954 +f 895/956/955 894/987/955 925/1014/955 +f 921/988/956 952/1015/956 953/1018/956 +f 909/959/957 908/958/957 939/1016/957 +f 895/956/958 926/1017/958 927/989/958 +f 923/961/959 922/957/959 953/1018/959 +f 909/959/960 940/1019/960 941/1021/960 +f 929/993/961 960/1052/961 961/1022/961 +f 943/995/962 974/1054/962 975/1023/962 +f 931/998/963 930/996/963 961/1022/963 +f 945/999/964 944/997/964 975/1023/964 +f 932/1000/965 931/998/965 962/1024/965 +f 946/1001/966 945/999/966 976/1025/966 +f 932/1000/967 963/1026/967 964/1028/967 +f 947/1003/968 946/1001/968 977/1027/968 +f 933/1002/969 964/1028/969 965/1030/969 +f 947/1003/970 978/1029/970 979/1031/970 +f 935/1006/971 934/1004/971 965/1030/971 +f 948/1005/972 979/1031/972 980/1033/972 +f 935/1006/973 966/1032/973 967/1034/973 +f 950/1009/974 949/1007/974 980/1033/974 +f 937/1010/975 936/1008/975 967/1034/975 +f 951/1011/976 950/1009/976 981/1035/976 +f 937/1010/977 968/1036/977 969/1038/977 +f 951/1011/979 982/1037/979 983/1041/979 +f 939/1016/980 938/1012/980 969/1038/980 +f 925/1014/981 956/1040/981 957/1043/981 +f 952/1015/982 983/1041/982 984/1044/982 +f 940/1019/983 939/1016/983 970/1042/983 +f 926/1017/984 957/1043/984 958/1046/984 +f 953/1018/985 984/1044/985 985/1047/985 +f 940/1019/986 971/1045/986 972/1048/986 +f 928/990/987 927/989/987 958/1046/987 +f 954/1020/988 985/1047/988 986/1050/988 +f 941/1021/989 972/1048/989 973/1051/989 +f 928/990/990 959/1049/990 960/1052/990 +f 943/995/992 942/992/992 973/1051/992 +f 962/1024/993 993/1087/993 994/1055/993 +f 977/1027/994 976/1025/994 1007/1056/994 +f 963/1026/995 994/1055/995 995/1058/995 +f 978/1029/996 977/1027/996 1008/1057/996 +f 964/1028/997 995/1058/997 996/1060/997 +f 979/1031/998 978/1029/998 1009/1059/998 +f 966/1032/999 965/1030/999 996/1060/999 +f 979/1031/1000 1010/1061/1000 1011/1063/1000 +f 966/1032/1001 997/1062/1001 998/1064/1001 +f 981/1035/1002 980/1033/1002 1011/1063/1002 +f 968/1036/1003 967/1034/1003 998/1064/1003 +f 981/1035/1004 1012/1065/1004 1013/1067/1004 +f 968/1036/1005 999/1066/1005 1000/1068/1005 +f 982/1037/1007 1013/1067/1007 1014/1071/1007 +f 970/1042/1008 969/1038/1008 1000/1068/1008 +f 956/1040/1009 987/1070/1009 988/1073/1009 +f 983/1041/1010 1014/1071/1010 1015/1074/1010 +f 971/1045/1011 970/1042/1011 1001/1072/1011 +f 957/1043/1012 988/1073/1012 989/1076/1012 +f 985/1047/1013 984/1044/1013 1015/1074/1013 +f 971/1045/1014 1002/1075/1014 1003/1078/1014 +f 959/1049/1015 958/1046/1015 989/1076/1015 +f 985/1047/1016 1016/1077/1016 1017/1080/1016 +f 972/1048/1017 1003/1078/1017 1004/1081/1017 +f 959/1049/1018 990/1079/1018 991/1082/1018 +f 974/1054/1020 973/1051/1020 1004/1081/1020 +f 960/1052/1021 991/1082/1021 992/1085/1021 +f 974/1054/1022 1005/1084/1022 1006/1086/1022 +f 962/1024/1023 961/1022/1023 992/1085/1023 +f 976/1025/1024 975/1023/1024 1006/1086/1024 +f 995/1058/1025 1026/1119/1025 1027/1088/1025 +f 1009/1059/1026 1040/1120/1026 1041/1089/1026 +f 997/1062/1027 996/1060/1027 1027/1088/1027 +f 1010/1061/1028 1041/1089/1028 1042/1091/1028 +f 997/1062/1029 1028/1090/1029 1029/1092/1029 +f 1012/1065/1030 1011/1063/1030 1042/1091/1030 +f 999/1066/1031 998/1064/1031 1029/1092/1031 +f 1013/1067/1032 1012/1065/1032 1043/1093/1032 +f 999/1066/1033 1030/1094/1033 1031/1096/1033 +f 1013/1067/1035 1044/1095/1035 1045/1099/1035 +f 1001/1072/1036 1000/1068/1036 1031/1096/1036 +f 987/1070/1037 1018/1098/1037 1019/1101/1037 +f 1015/1074/1038 1014/1071/1038 1045/1099/1038 +f 1002/1075/1039 1001/1072/1039 1032/1100/1039 +f 988/1073/1040 1019/1101/1040 1020/1104/1040 +f 1016/1077/1041 1015/1074/1041 1046/1102/1041 +f 1002/1075/1042 1033/1103/1042 1034/1106/1042 +f 989/1076/1043 1020/1104/1043 1021/1107/1043 +f 1016/1077/1044 1047/1105/1044 1048/1108/1044 +f 1003/1078/1045 1034/1106/1045 1035/1109/1045 +f 990/1079/1046 1021/1107/1046 1022/1110/1046 +f 1005/1084/1048 1004/1081/1048 1035/1109/1048 +f 991/1082/1049 1022/1110/1049 1023/1113/1049 +f 1005/1084/1050 1036/1112/1050 1037/1114/1050 +f 993/1087/1051 992/1085/1051 1023/1113/1051 +f 1007/1056/1052 1006/1086/1052 1037/1114/1052 +f 993/1087/1053 1024/1115/1053 1025/1117/1053 +f 1008/1057/1054 1007/1056/1054 1038/1116/1054 +f 994/1055/1055 1025/1117/1055 1026/1119/1055 +f 1009/1059/1056 1008/1057/1056 1039/1118/1056 +f 1028/1090/1057 1059/1153/1057 1060/1121/1057 +f 1043/1093/1058 1042/1091/1058 1073/1122/1058 +f 1030/1094/1059 1029/1092/1059 1060/1121/1059 +f 1043/1093/1060 1074/1123/1060 1075/1125/1060 +f 1030/1094/1061 1061/1124/1061 1062/1126/1061 +f 1044/1095/1063 1075/1125/1063 1076/1129/1063 +f 1032/1100/1064 1031/1096/1064 1062/1126/1064 +f 1018/1098/1065 1049/1128/1065 1050/1131/1065 +f 1046/1102/1066 1045/1099/1066 1076/1129/1066 +f 1033/1103/1067 1032/1100/1067 1063/1130/1067 +f 1019/1101/1068 1050/1131/1068 1051/1134/1068 +f 1046/1102/1069 1077/1132/1069 1078/1135/1069 +f 1033/1103/1070 1064/1133/1070 1065/1136/1070 +f 1021/1107/1071 1020/1104/1071 1051/1134/1071 +f 1048/1108/1072 1047/1105/1072 1078/1135/1072 +f 1034/1106/1073 1065/1136/1073 1066/1139/1073 +f 1021/1107/1074 1052/1137/1074 1053/1140/1074 +f 1036/1112/1076 1035/1109/1076 1066/1139/1076 +f 1022/1110/1077 1053/1140/1077 1054/1143/1077 +f 1036/1112/1078 1067/1142/1078 1068/1144/1078 +f 1024/1115/1079 1023/1113/1079 1054/1143/1079 +f 1038/1116/1080 1037/1114/1080 1068/1144/1080 +f 1024/1115/1081 1055/1145/1081 1056/1147/1081 +f 1039/1118/1082 1038/1116/1082 1069/1146/1082 +f 1025/1117/1083 1056/1147/1083 1057/1149/1083 +f 1040/1120/1084 1039/1118/1084 1070/1148/1084 +f 1026/1119/1085 1057/1149/1085 1058/1151/1085 +f 1040/1120/1086 1071/1150/1086 1072/1152/1086 +f 1028/1090/1087 1027/1088/1087 1058/1151/1087 +f 1041/1089/1088 1072/1152/1088 1073/1122/1088 +f 1061/1124/1089 1092/1185/1089 1093/1154/1089 +f 1075/1125/1091 1106/1186/1091 1107/1157/1091 +f 1063/1130/1092 1062/1126/1092 1093/1154/1092 +f 1049/1128/2075 1080/1156/2075 1081/1159/2075 +f 1077/1132/1094 1076/1129/1094 1107/1157/1094 +f 1064/1133/1095 1063/1130/1095 1094/1158/1095 +f 1050/1131/1096 1081/1159/1096 1082/1162/1096 +f 1078/1135/1097 1077/1132/1097 1108/1160/1097 +f 1064/1133/1098 1095/1161/1098 1096/1164/1098 +f 1052/1137/1099 1051/1134/1099 1082/1162/1099 +f 1078/1135/1100 1109/1163/1100 1110/1166/1100 +f 1065/1136/1101 1096/1164/1101 1097/1167/1101 +f 1052/1137/1102 1083/1165/1102 1084/1168/1102 +f 1067/1142/1104 1066/1139/1104 1097/1167/1104 +f 1053/1140/1105 1084/1168/1105 1085/1171/1105 +f 1067/1142/1106 1098/1170/1106 1099/1172/1106 +f 1055/1145/1107 1054/1143/1107 1085/1171/1107 +f 1069/1146/1108 1068/1144/1108 1099/1172/1108 +f 1056/1147/1109 1055/1145/1109 1086/1173/1109 +f 1070/1148/1110 1069/1146/1110 1100/1174/1110 +f 1056/1147/1111 1087/1175/1111 1088/1177/1111 +f 1070/1148/1112 1101/1176/1112 1102/1178/1112 +f 1057/1149/1113 1088/1177/1113 1089/1179/1113 +f 1071/1150/1114 1102/1178/1114 1103/1180/1114 +f 1059/1153/1115 1058/1151/1115 1089/1179/1115 +f 1072/1152/1116 1103/1180/1116 1104/1182/1116 +f 1059/1153/1117 1090/1181/1117 1091/1183/1117 +f 1074/1123/1118 1073/1122/1118 1104/1182/1118 +f 1061/1124/1119 1060/1121/1119 1091/1183/1119 +f 1075/1125/1120 1074/1123/1120 1105/1184/1120 +f 1095/1161/1121 1094/1158/1121 1125/1187/1121 +f 1081/1159/2076 1112/1219/2076 1113/1189/2076 +f 1109/1163/2077 1108/1160/2077 1139/1190/2077 +f 1095/1161/1124 1126/1188/1124 1127/1192/1124 +f 1083/1165/1125 1082/1162/1125 1113/1189/1125 +f 1109/1163/1126 1140/1191/1126 1141/1194/1126 +f 1096/1164/1127 1127/1192/1127 1128/1195/1127 +f 1083/1165/1128 1114/1193/1128 1115/1196/1128 +f 1098/1170/1130 1097/1167/1130 1128/1195/1130 +f 1084/1168/1131 1115/1196/1131 1116/1199/1131 +f 1098/1170/1132 1129/1198/1132 1130/1200/1132 +f 1086/1173/1133 1085/1171/1133 1116/1199/1133 +f 1100/1174/1134 1099/1172/1134 1130/1200/1134 +f 1086/1173/1135 1117/1201/1135 1118/1203/1135 +f 1101/1176/1136 1100/1174/1136 1131/1202/1136 +f 1087/1175/1137 1118/1203/1137 1119/1205/1137 +f 1102/1178/1138 1101/1176/1138 1132/1204/1138 +f 1088/1177/1139 1119/1205/1139 1120/1207/1139 +f 1102/1178/1140 1133/1206/1140 1134/1208/1140 +f 1090/1181/1141 1089/1179/1141 1120/1207/1141 +f 1103/1180/1142 1134/1208/1142 1135/1210/1142 +f 1090/1181/1143 1121/1209/1143 1122/1211/1143 +f 1105/1184/1144 1104/1182/1144 1135/1210/1144 +f 1092/1185/1145 1091/1183/1145 1122/1211/1145 +f 1105/1184/1146 1136/1212/1146 1137/1214/1146 +f 1092/1185/1147 1123/1213/1147 1124/1215/1147 +f 1106/1186/1149 1137/1214/1149 1138/1218/1149 +f 1094/1158/1150 1093/1154/1150 1124/1215/1150 +f 1080/1156/1151 1111/1217/1151 1112/1219/1151 +f 1108/1160/1152 1107/1157/1152 1138/1218/1152 +f 1127/1192/1153 1158/1251/1153 1159/1220/1153 +f 1114/1193/1154 1145/1252/1154 1146/1221/1154 +f 1129/1198/1156 1128/1195/1156 1159/1220/1156 +f 1115/1196/1157 1146/1221/1157 1147/1225/1157 +f 1129/1198/1158 1160/1224/1158 1161/1226/1158 +f 1116/1199/1159 1147/1225/1159 1148/1227/1159 +f 1131/1202/1160 1130/1200/1160 1161/1226/1160 +f 1117/1201/1161 1148/1227/1161 1149/1229/1161 +f 1132/1204/1162 1131/1202/1162 1162/1228/1162 +f 1118/1203/1163 1149/1229/1163 1150/1231/1163 +f 1133/1206/1164 1132/1204/1164 1163/1230/1164 +f 1119/1205/1165 1150/1231/1165 1151/1233/1165 +f 1134/1208/1166 1133/1206/1166 1164/1232/1166 +f 1121/1209/1167 1120/1207/1167 1151/1233/1167 +f 1134/1208/1168 1165/1234/1168 1166/1236/1168 +f 1121/1209/1169 1152/1235/1169 1153/1237/1169 +f 1136/1212/1170 1135/1210/1170 1166/1236/1170 +f 1123/1213/1171 1122/1211/1171 1153/1237/1171 +f 1137/1214/1172 1136/1212/1172 1167/1238/1172 +f 1123/1213/1173 1154/1239/1173 1155/1241/1173 +f 1137/1214/1175 1168/1240/1175 1169/1244/1175 +f 1125/1187/1176 1124/1215/1176 1155/1241/1176 +f 1111/1217/1177 1142/1243/1177 1143/1246/1177 +f 1139/1190/1178 1138/1218/1178 1169/1244/1178 +f 1126/1188/1179 1125/1187/1179 1156/1245/1179 +f 1112/1219/1180 1143/1246/1180 1144/1249/1180 +f 1140/1191/1181 1139/1190/1181 1170/1247/1181 +f 1126/1188/1182 1157/1248/1182 1158/1251/1182 +f 1114/1193/1183 1113/1189/1183 1144/1249/1183 +f 1141/1194/1184 1140/1191/1184 1171/1250/1184 +f 1160/1224/1185 1191/1285/1185 1192/1253/1185 +f 1148/1227/1186 1147/1225/1186 1178/1254/1186 +f 1162/1228/1187 1161/1226/1187 1192/1253/1187 +f 1148/1227/1188 1179/1255/1188 1180/1257/1188 +f 1163/1230/1189 1162/1228/1189 1193/1256/1189 +f 1149/1229/1190 1180/1257/1190 1181/1259/1190 +f 1163/1230/1191 1194/1258/1191 1195/1260/1191 +f 1150/1231/1192 1181/1259/1192 1182/1261/1192 +f 1165/1234/1193 1164/1232/1193 1195/1260/1193 +f 1152/1235/1194 1151/1233/1194 1182/1261/1194 +f 1165/1234/1195 1196/1262/1195 1197/1264/1195 +f 1152/1235/1196 1183/1263/1196 1184/1265/1196 +f 1167/1238/1197 1166/1236/1197 1197/1264/1197 +f 1154/1239/1198 1153/1237/1198 1184/1265/1198 +f 1168/1240/1199 1167/1238/1199 1198/1266/1199 +f 1154/1239/1200 1185/1267/1200 1186/1269/1200 +f 1168/1240/1202 1199/1268/1202 1200/1272/1202 +f 1156/1245/1203 1155/1241/1203 1186/1269/1203 +f 1142/1243/1204 1173/1271/1204 1174/1274/1204 +f 1170/1247/1205 1169/1244/1205 1200/1272/1205 +f 1157/1248/1206 1156/1245/1206 1187/1273/1206 +f 1143/1246/2078 1174/1274/2078 1175/1277/2078 +f 1170/1247/1208 1201/1275/1208 1202/1278/1208 +f 1157/1248/1209 1188/1276/1209 1189/1279/1209 +f 1145/1252/1210 1144/1249/1210 1175/1277/1210 +f 1171/1250/1211 1202/1278/1211 1203/1281/1211 +f 1158/1251/1212 1189/1279/1212 1190/1282/1212 +f 1145/1252/1213 1176/1280/1213 1177/1283/1213 +f 1160/1224/1215 1159/1220/1215 1190/1282/1215 +f 1146/1221/1216 1177/1283/1216 1178/1254/1216 +f 1194/1258/1217 1193/1256/1217 1224/1286/1217 +f 1180/1257/1218 1211/1318/1218 1212/1288/1218 +f 1194/1258/1219 1225/1287/1219 1226/1289/1219 +f 1182/1261/1220 1181/1259/1220 1212/1288/1220 +f 1196/1262/1221 1195/1260/1221 1226/1289/1221 +f 1183/1263/1222 1182/1261/1222 1213/1290/1222 +f 1196/1262/1223 1227/1291/1223 1228/1293/1223 +f 1183/1263/1224 1214/1292/1224 1215/1294/1224 +f 1198/1266/1225 1197/1264/1225 1228/1293/1225 +f 1185/1267/1226 1184/1265/1226 1215/1294/1226 +f 1198/1266/1227 1229/1295/1227 1230/1297/1227 +f 1185/1267/1228 1216/1296/1228 1217/1298/1228 +f 1199/1268/1230 1230/1297/1230 1231/1301/1230 +f 1187/1273/1231 1186/1269/1231 1217/1298/1231 +f 1173/1271/1232 1204/1300/1232 1205/1303/1232 +f 1201/1275/1233 1200/1272/1233 1231/1301/1233 +f 1188/1276/1234 1187/1273/1234 1218/1302/1234 +f 1174/1274/1235 1205/1303/1235 1206/1306/1235 +f 1201/1275/1236 1232/1304/1236 1233/1307/1236 +f 1188/1276/1237 1219/1305/1237 1220/1308/1237 +f 1176/1280/1238 1175/1277/1238 1206/1306/1238 +f 1203/1281/2079 1202/1278/2079 1233/1307/2079 +f 1189/1279/1240 1220/1308/1240 1221/1311/1240 +f 1177/1283/1241 1176/1280/1241 1207/1309/1241 +f 1191/1285/1243 1190/1282/1243 1221/1311/1243 +f 1177/1283/1244 1208/1312/1244 1209/1315/1244 +f 1191/1285/1245 1222/1314/1245 1223/1316/1245 +f 1178/1254/1246 1209/1315/1246 1210/1317/1246 +f 1193/1256/1247 1192/1253/1247 1223/1316/1247 +f 1179/1255/1248 1210/1317/1248 1211/1318/1248 +f 1226/1289/1249 1257/1350/1249 1258/1319/1249 +f 1213/1290/1250 1244/1351/1250 1245/1320/1250 +f 1227/1291/1251 1258/1319/1251 1259/1321/1251 +f 1214/1292/1252 1245/1320/1252 1246/1322/1252 +f 1229/1295/1253 1228/1293/1253 1259/1321/1253 +f 1216/1296/1254 1215/1294/1254 1246/1322/1254 +f 1230/1297/1255 1229/1295/1255 1260/1323/1255 +f 1216/1296/1256 1247/1324/1256 1248/1326/1256 +f 1231/1301/1258 1230/1297/1258 1261/1325/1258 +f 1218/1302/1259 1217/1298/1259 1248/1326/1259 +f 1204/1300/2080 1235/1328/2080 1236/1331/2080 +f 1232/1304/1261 1231/1301/1261 1262/1329/1261 +f 1219/1305/1262 1218/1302/1262 1249/1330/1262 +f 1205/1303/1263 1236/1331/1263 1237/1334/1263 +f 1233/1307/1264 1232/1304/1264 1263/1332/1264 +f 1220/1308/1265 1219/1305/1265 1250/1333/1265 +f 1206/1306/1266 1237/1334/1266 1238/1337/1266 +f 1234/1310/1267 1233/1307/1267 1264/1335/1267 +f 1220/1308/1268 1251/1336/1268 1252/1339/1268 +f 1207/1309/1269 1238/1337/1269 1239/1340/1269 +f 1222/1314/1271 1221/1311/1271 1252/1339/1271 +f 1208/1312/1272 1239/1340/1272 1240/1343/1272 +f 1222/1314/1273 1253/1342/1273 1254/1344/1273 +f 1210/1317/1274 1209/1315/1274 1240/1343/1274 +f 1224/1286/1275 1223/1316/1275 1254/1344/1275 +f 1210/1317/1276 1241/1345/1276 1242/1347/1276 +f 1225/1287/1277 1224/1286/1277 1255/1346/1277 +f 1211/1318/1278 1242/1347/1278 1243/1349/1278 +f 1225/1287/1279 1256/1348/1279 1257/1350/1279 +f 1213/1290/1280 1212/1288/1280 1243/1349/1280 +f 1260/1323/1281 1259/1321/1281 1290/1352/1281 +f 1247/1324/1282 1246/1322/1282 1277/1354/1282 +f 1261/1325/1283 1260/1323/1283 1291/1353/1283 +f 1247/1324/1284 1278/1355/1284 1279/1357/1284 +f 1262/1329/1286 1261/1325/1286 1292/1356/1286 +f 1249/1330/1287 1248/1326/1287 1279/1357/1287 +f 1236/1331/1288 1235/1328/1288 1266/1359/1288 +f 1263/1332/1289 1262/1329/1289 1293/1360/1289 +f 1249/1330/1290 1280/1361/1290 1281/1364/1290 +f 1236/1331/1291 1267/1362/1291 1268/1365/1291 +f 1263/1332/1292 1294/1363/1292 1295/1366/1292 +f 1251/1336/1293 1250/1333/1293 1281/1364/1293 +f 1237/1334/1294 1268/1365/1294 1269/1368/1294 +f 1264/1335/1295 1295/1366/1295 1296/1369/1295 +f 1251/1336/1296 1282/1367/1296 1283/1370/1296 +f 1238/1337/1297 1269/1368/1297 1270/1371/1297 +f 1253/1342/1299 1252/1339/1299 1283/1370/1299 +f 1240/1343/1300 1239/1340/1300 1270/1371/1300 +f 1253/1342/1301 1284/1373/1301 1285/1375/1301 +f 1240/1343/1302 1271/1374/1302 1272/1376/1302 +f 1255/1346/1303 1254/1344/1303 1285/1375/1303 +f 1241/1345/1304 1272/1376/1304 1273/1378/1304 +f 1256/1348/1305 1255/1346/1305 1286/1377/1305 +f 1243/1349/1306 1242/1347/1306 1273/1378/1306 +f 1256/1348/1307 1287/1379/1307 1288/1381/1307 +f 1244/1351/1308 1243/1349/1308 1274/1380/1308 +f 1257/1350/1309 1288/1381/1309 1289/1383/1309 +f 1244/1351/1310 1275/1382/1310 1276/1384/1310 +f 1258/1319/1311 1289/1383/1311 1290/1352/1311 +f 1245/1320/1312 1276/1384/1312 1277/1354/1312 +f 1293/1360/1314 1292/1356/1314 1323/1387/1314 +f 1280/1361/1315 1279/1357/1315 1310/1389/1315 +f 1266/1359/2081 1297/1386/2081 1298/1391/2081 +f 1294/1363/1317 1293/1360/1317 1324/1388/1317 +f 1280/1361/1318 1311/1390/1318 1312/1393/1318 +f 1267/1362/1319 1298/1391/1319 1299/1394/1319 +f 1294/1363/1320 1325/1392/1320 1326/1395/1320 +f 1282/1367/1321 1281/1364/1321 1312/1393/1321 +f 1268/1365/1322 1299/1394/1322 1300/1397/1322 +f 1295/1366/2082 1326/1395/2082 1327/1398/2082 +f 1282/1367/1324 1313/1396/1324 1314/1399/1324 +f 1269/1368/1325 1300/1397/1325 1301/1400/1325 +f 1284/1373/1327 1283/1370/1327 1314/1399/1327 +f 1270/1371/1328 1301/1400/1328 1302/1403/1328 +f 1284/1373/1329 1315/1402/1329 1316/1404/1329 +f 1271/1374/1330 1302/1403/1330 1303/1405/1330 +f 1286/1377/1331 1285/1375/1331 1316/1404/1331 +f 1273/1378/1332 1272/1376/1332 1303/1405/1332 +f 1287/1379/1333 1286/1377/1333 1317/1406/1333 +f 1273/1378/1334 1304/1407/1334 1305/1409/1334 +f 1287/1379/1335 1318/1408/1335 1319/1410/1335 +f 1275/1382/1336 1274/1380/1336 1305/1409/1336 +f 1288/1381/1337 1319/1410/1337 1320/1412/1337 +f 1275/1382/1338 1306/1411/1338 1307/1413/1338 +f 1289/1383/1339 1320/1412/1339 1321/1414/1339 +f 1276/1384/1340 1307/1413/1340 1308/1415/1340 +f 1290/1352/1341 1321/1414/1341 1322/1416/1341 +f 1278/1355/1342 1277/1354/1342 1308/1415/1342 +f 1292/1356/1343 1291/1353/1343 1322/1416/1343 +f 1278/1355/1344 1309/1417/1344 1310/1389/1344 +f 1298/1391/1345 1329/1449/1345 1330/1418/1345 +f 1325/1392/1346 1356/1450/1346 1357/1419/1346 +f 1313/1396/1347 1312/1393/1347 1343/1420/1347 +f 1299/1394/1348 1330/1418/1348 1331/1422/1348 +f 1326/1395/1349 1357/1419/1349 1358/1423/1349 +f 1313/1396/1350 1344/1421/1350 1345/1424/1350 +f 1300/1397/1351 1331/1422/1351 1332/1425/1351 +f 1315/1402/1353 1314/1399/1353 1345/1424/1353 +f 1301/1400/1354 1332/1425/1354 1333/1428/1354 +f 1315/1402/1355 1346/1427/1355 1347/1429/1355 +f 1303/1405/1356 1302/1403/1356 1333/1428/1356 +f 1317/1406/1357 1316/1404/1357 1347/1429/1357 +f 1304/1407/2083 1303/1405/2083 1334/1430/2083 +f 1318/1408/1359 1317/1406/1359 1348/1431/1359 +f 1304/1407/1360 1335/1432/1360 1336/1434/1360 +f 1319/1410/1361 1318/1408/1361 1349/1433/1361 +f 1306/1411/1362 1305/1409/1362 1336/1434/1362 +f 1319/1410/1363 1350/1435/1363 1351/1437/1363 +f 1306/1411/1364 1337/1436/1364 1338/1438/1364 +f 1320/1412/1365 1351/1437/1365 1352/1439/1365 +f 1308/1415/1366 1307/1413/1366 1338/1438/1366 +f 1322/1416/1367 1321/1414/1367 1352/1439/1367 +f 1309/1417/1368 1308/1415/1368 1339/1440/1368 +f 1322/1416/1369 1353/1441/1369 1354/1443/1369 +f 1309/1417/1370 1340/1442/1370 1341/1444/1370 +f 1323/1387/1372 1354/1443/1372 1355/1447/1372 +f 1311/1390/1373 1310/1389/1373 1341/1444/1373 +f 1297/1386/1374 1328/1446/1374 1329/1449/1374 +f 1325/1392/1375 1324/1388/1375 1355/1447/1375 +f 1311/1390/1376 1342/1448/1376 1343/1420/1376 +f 1331/1422/1377 1362/1483/1377 1363/1451/1377 +f 1346/1427/1379 1345/1424/1379 1376/1454/1379 +f 1332/1425/1380 1363/1451/1380 1364/1456/1380 +f 1346/1427/1381 1377/1455/1381 1378/1457/1381 +f 1334/1430/1382 1333/1428/1382 1364/1456/1382 +f 1348/1431/1383 1347/1429/1383 1378/1457/1383 +f 1334/1430/1384 1365/1458/1384 1366/1460/1384 +f 1349/1433/1385 1348/1431/1385 1379/1459/1385 +f 1335/1432/1386 1366/1460/1386 1367/1462/1386 +f 1349/1433/1387 1380/1461/1387 1381/1463/1387 +f 1337/1436/1388 1336/1434/1388 1367/1462/1388 +f 1350/1435/1389 1381/1463/1389 1382/1465/1389 +f 1337/1436/1390 1368/1464/1390 1369/1466/1390 +f 1351/1437/1391 1382/1465/1391 1383/1467/1391 +f 1338/1438/1392 1369/1466/1392 1370/1468/1392 +f 1352/1439/1393 1383/1467/1393 1384/1469/1393 +f 1340/1442/1394 1339/1440/1394 1370/1468/1394 +f 1354/1443/1395 1353/1441/1395 1384/1469/1395 +f 1340/1442/1396 1371/1470/1396 1372/1472/1396 +f 1354/1443/1398 1385/1471/1398 1386/1475/1398 +f 1342/1448/1399 1341/1444/1399 1372/1472/1399 +f 1328/1446/1400 1359/1474/1400 1360/1477/1400 +f 1356/1450/1401 1355/1447/1401 1386/1475/1401 +f 1342/1448/1402 1373/1476/1402 1374/1479/1402 +f 1329/1449/1403 1360/1477/1403 1361/1480/1403 +f 1356/1450/1404 1387/1478/1404 1388/1481/1404 +f 1344/1421/1405 1343/1420/1405 1374/1479/1405 +f 1330/1418/1406 1361/1480/1406 1362/1483/1406 +f 1357/1419/1407 1388/1481/1407 1389/1453/1407 +f 1344/1421/1408 1375/1482/1408 1376/1454/1408 +f 1365/1458/1409 1364/1456/1409 1395/1484/1409 +f 1379/1459/1410 1378/1457/1410 1409/1486/1410 +f 1366/1460/1411 1365/1458/1411 1396/1485/1411 +f 1380/1461/1412 1379/1459/1412 1410/1487/1412 +f 1366/1460/1413 1397/1488/1413 1398/1490/1413 +f 1381/1463/1414 1380/1461/1414 1411/1489/1414 +f 1367/1462/1415 1398/1490/1415 1399/1492/1415 +f 1381/1463/1416 1412/1491/1416 1413/1493/1416 +f 1368/1464/1417 1399/1492/1417 1400/1494/1417 +f 1382/1465/1418 1413/1493/1418 1414/1495/1418 +f 1369/1466/1419 1400/1494/1419 1401/1496/1419 +f 1383/1467/1420 1414/1495/1420 1415/1497/1420 +f 1371/1470/1421 1370/1468/1421 1401/1496/1421 +f 1385/1471/1422 1384/1469/1422 1415/1497/1422 +f 1371/1470/1423 1402/1498/1423 1403/1500/1423 +f 1385/1471/1425 1416/1499/1425 1417/1503/1425 +f 1373/1476/1426 1372/1472/1426 1403/1500/1426 +f 1359/1474/1427 1390/1502/1427 1391/1505/1427 +f 1387/1478/1428 1386/1475/1428 1417/1503/1428 +f 1373/1476/1429 1404/1504/1429 1405/1507/1429 +f 1361/1480/2084 1360/1477/2084 1391/1505/2084 +f 1387/1478/2085 1418/1506/2085 1419/1509/2085 +f 1375/1482/1432 1374/1479/1432 1405/1507/1432 +f 1361/1480/1433 1392/1508/1433 1393/1511/1433 +f 1389/1453/1434 1388/1481/1434 1419/1509/1434 +f 1375/1482/1435 1406/1510/1435 1407/1513/1435 +f 1362/1483/1436 1393/1511/1436 1394/1514/1436 +f 1377/1455/1438 1376/1454/1438 1407/1513/1438 +f 1364/1456/2086 1363/1451/2086 1394/1514/2086 +f 1377/1455/1440 1408/1516/1440 1409/1486/1440 +f 1397/1488/1441 1428/1549/1441 1429/1517/1441 +f 1412/1491/1442 1411/1489/1442 1442/1518/1442 +f 1399/1492/1443 1398/1490/1443 1429/1517/1443 +f 1412/1491/1444 1443/1519/1444 1444/1521/1444 +f 1399/1492/1445 1430/1520/1445 1431/1522/1445 +f 1413/1493/1446 1444/1521/1446 1445/1523/1446 +f 1400/1494/1447 1431/1522/1447 1432/1524/1447 +f 1414/1495/1448 1445/1523/1448 1446/1525/1448 +f 1402/1498/1449 1401/1496/1449 1432/1524/1449 +f 1415/1497/1450 1446/1525/1450 1447/1527/1450 +f 1402/1498/1451 1433/1526/1451 1434/1528/1451 +f 1417/1503/2087 1416/1499/2087 1447/1527/2087 +f 1404/1504/1454 1403/1500/1454 1434/1528/1454 +f 1390/1502/1455 1421/1530/1455 1422/1533/1455 +f 1418/1506/1456 1417/1503/1456 1448/1531/1456 +f 1404/1504/1457 1435/1532/1457 1436/1535/1457 +f 1391/1505/1458 1422/1533/1458 1423/1536/1458 +f 1418/1506/1459 1449/1534/1459 1450/1537/1459 +f 1406/1510/1460 1405/1507/1460 1436/1535/1460 +f 1392/1508/1461 1423/1536/1461 1424/1539/1461 +f 1419/1509/1462 1450/1537/1462 1451/1540/1462 +f 1406/1510/1463 1437/1538/1463 1438/1541/1463 +f 1394/1514/1464 1393/1511/1464 1424/1539/1464 +f 1408/1516/1466 1407/1513/1466 1438/1541/1466 +f 1395/1484/1467 1394/1514/1467 1425/1542/1467 +f 1408/1516/1468 1439/1544/1468 1440/1546/1468 +f 1396/1485/1469 1395/1484/1469 1426/1545/1469 +f 1410/1487/1470 1409/1486/1470 1440/1546/1470 +f 1397/1488/1471 1396/1485/1471 1427/1547/1471 +f 1411/1489/1472 1410/1487/1472 1441/1548/1472 +f 1430/1520/1473 1462/1581/1473 1463/1550/1473 +f 1444/1521/1474 1476/1582/1474 1477/1551/1474 +f 1431/1522/1475 1463/1550/1475 1464/1552/1475 +f 1445/1523/1476 1477/1551/1476 1478/1553/1476 +f 1433/1526/1477 1432/1524/1477 1464/1552/1477 +f 1446/1525/1478 1478/1553/1478 1479/1555/1478 +f 1433/1526/1479 1465/1554/1479 1466/1556/1479 +f 1447/1527/1481 1479/1555/1481 1480/1559/1481 +f 1435/1532/1482 1434/1528/1482 1466/1556/1482 +f 1421/1530/2088 1453/1558/2088 1454/1561/2088 +f 1449/1534/1484 1448/1531/1484 1480/1559/1484 +f 1435/1532/1485 1467/1560/1485 1468/1563/1485 +f 1422/1533/1486 1454/1561/1486 1455/1564/1486 +f 1449/1534/1487 1481/1562/1487 1482/1565/1487 +f 1437/1538/1488 1436/1535/1488 1468/1563/1488 +f 1423/1536/1489 1455/1564/1489 1456/1567/1489 +f 1450/1537/1490 1482/1565/1490 1483/1568/1490 +f 1437/1538/1491 1469/1566/1491 1470/1569/1491 +f 1424/1539/1492 1456/1567/1492 1457/1570/1492 +f 1439/1544/1494 1438/1541/1494 1470/1569/1494 +f 1425/1542/1495 1457/1570/1495 1458/1573/1495 +f 1439/1544/1496 1471/1572/1496 1472/1574/1496 +f 1427/1547/1497 1426/1545/1497 1458/1573/1497 +f 1441/1548/1498 1440/1546/1498 1472/1574/1498 +f 1428/1549/2089 1427/1547/2089 1459/1575/2089 +f 1442/1518/1500 1441/1548/1500 1473/1576/1500 +f 1428/1549/1501 1460/1577/1501 1461/1579/1501 +f 1442/1518/1502 1474/1578/1502 1475/1580/1502 +f 1430/1520/1503 1429/1517/1503 1461/1579/1503 +f 1443/1519/1504 1475/1580/1504 1476/1582/1504 +f 1465/1554/1505 1464/1552/1505 1495/1583/1505 +f 1478/1553/1506 1509/1615/1506 1510/1585/1506 +f 1465/1554/1507 1496/1584/1507 1497/1586/1507 +f 1479/1555/1509 1510/1585/1509 1511/1589/1509 +f 1467/1560/1510 1466/1556/1510 1497/1586/1510 +f 1453/1558/1511 1484/1588/1511 1485/1591/1511 +f 1481/1562/2090 1480/1559/2090 1511/1589/2090 +f 1467/1560/1513 1498/1590/1513 1499/1593/1513 +f 1454/1561/1514 1485/1591/1514 1486/1594/1514 +f 1481/1562/1515 1512/1592/1515 1513/1595/1515 +f 1469/1566/1516 1468/1563/1516 1499/1593/1516 +f 1455/1564/2091 1486/1594/2091 1487/1597/2091 +f 1482/1565/1518 1513/1595/1518 1514/1598/1518 +f 1469/1566/1519 1500/1596/1519 1501/1599/1519 +f 1456/1567/1520 1487/1597/1520 1488/1600/1520 +f 1471/1572/1522 1470/1569/1522 1501/1599/1522 +f 1457/1570/1523 1488/1600/1523 1489/1603/1523 +f 1471/1572/1524 1502/1602/1524 1503/1604/1524 +f 1459/1575/1525 1458/1573/1525 1489/1603/1525 +f 1473/1576/1526 1472/1574/1526 1503/1604/1526 +f 1460/1577/1527 1459/1575/1527 1490/1605/1527 +f 1474/1578/1528 1473/1576/1528 1504/1606/1528 +f 1460/1577/1529 1491/1607/1529 1492/1609/1529 +f 1474/1578/1530 1505/1608/1530 1506/1610/1530 +f 1462/1581/1531 1461/1579/1531 1492/1609/1531 +f 1475/1580/1532 1506/1610/1532 1507/1612/1532 +f 1462/1581/1533 1493/1611/1533 1494/1613/1533 +f 1476/1582/1534 1507/1612/1534 1508/1614/1534 +f 1463/1550/1535 1494/1613/1535 1495/1583/1535 +f 1477/1551/1536 1508/1614/1536 1509/1615/1536 +f 1498/1616/1537 1497/1676/1537 1528/1617/1537 +f 1484/1619/1538 1515/1678/1538 1516/1620/1538 +f 1512/1622/1539 1511/1679/1539 1542/1623/1539 +f 1498/1616/1540 1529/1618/1540 1530/1625/1540 +f 1485/1621/1541 1516/1620/1541 1517/1627/1541 +f 1512/1622/1542 1543/1624/1542 1544/1629/1542 +f 1500/1631/1543 1499/1626/1543 1530/1625/1543 +f 1486/1628/2092 1517/1627/2092 1518/1633/2092 +f 1513/1630/1545 1544/1629/1545 1545/1635/1545 +f 1500/1631/1546 1531/1632/1546 1532/1637/1546 +f 1487/1634/1547 1518/1633/1547 1519/1639/1547 +f 1502/1642/1549 1501/1638/1549 1532/1637/1549 +f 1489/1644/1550 1488/1640/1550 1519/1639/1550 +f 1502/1642/1551 1533/1643/1551 1534/1646/1551 +f 1489/1644/1552 1520/1645/1552 1521/1648/1552 +f 1504/1650/1553 1503/1647/1553 1534/1646/1553 +f 1490/1649/1554 1521/1648/1554 1522/1652/1554 +f 1505/1654/1555 1504/1650/1555 1535/1651/1555 +f 1491/1653/1556 1522/1652/1556 1523/1656/1556 +f 1505/1654/1557 1536/1655/1557 1537/1658/1557 +f 1493/1660/1558 1492/1657/1558 1523/1656/1558 +f 1506/1659/1559 1537/1658/1559 1538/1662/1559 +f 1493/1660/1560 1524/1661/1560 1525/1664/1560 +f 1507/1663/1561 1538/1662/1561 1539/1666/1561 +f 1494/1665/1562 1525/1664/1562 1526/1668/1562 +f 1508/1667/1563 1539/1666/1563 1540/1670/1563 +f 1496/1672/1564 1495/1669/1564 1526/1668/1564 +f 1509/1671/1565 1540/1670/1565 1541/1674/1565 +f 1496/1672/1566 1527/1673/1566 1528/1617/1566 +f 1510/1675/1568 1541/1674/1568 1542/1623/1568 +f 1531/1632/1569 1530/1625/1569 1561/1680/1569 +f 1517/1627/1570 1548/1711/1570 1549/1682/1570 +f 1544/1629/1571 1575/1712/1571 1576/1683/1571 +f 1531/1632/1572 1562/1681/1572 1563/1684/1572 +f 1518/1633/1573 1549/1682/1573 1550/1685/1573 +f 1533/1643/1575 1532/1637/1575 1563/1684/1575 +f 1520/1645/1576 1519/1639/1576 1550/1685/1576 +f 1533/1643/1577 1564/1687/1577 1565/1689/1577 +f 1521/1648/1578 1520/1645/1578 1551/1688/1578 +f 1535/1651/1579 1534/1646/1579 1565/1689/1579 +f 1522/1652/1580 1521/1648/1580 1552/1690/1580 +f 1536/1655/1581 1535/1651/1581 1566/1691/1581 +f 1522/1652/1582 1553/1692/1582 1554/1694/1582 +f 1536/1655/1583 1567/1693/1583 1568/1695/1583 +f 1524/1661/1584 1523/1656/1584 1554/1694/1584 +f 1537/1658/1585 1568/1695/1585 1569/1697/1585 +f 1524/1661/1586 1555/1696/1586 1556/1698/1586 +f 1538/1662/1587 1569/1697/1587 1570/1699/1587 +f 1526/1668/1588 1525/1664/1588 1556/1698/1588 +f 1539/1666/1589 1570/1699/1589 1571/1701/1589 +f 1527/1673/1590 1526/1668/1590 1557/1700/1590 +f 1540/1670/1591 1571/1701/1591 1572/1703/1591 +f 1527/1673/1592 1558/1702/1592 1559/1704/1592 +f 1541/1674/1594 1572/1703/1594 1573/1707/1594 +f 1529/1618/1595 1528/1617/1595 1559/1704/1595 +f 1515/1678/2093 1546/1706/2093 1547/1709/2093 +f 1543/1624/1597 1542/1623/1597 1573/1707/1597 +f 1529/1618/1598 1560/1708/1598 1561/1680/1598 +f 1516/1620/1599 1547/1709/1599 1548/1711/1599 +f 1543/1624/1600 1574/1710/1600 1575/1712/1600 +f 1564/1687/1601 1563/1684/1601 1594/1713/1601 +f 1551/1688/1602 1550/1685/1602 1581/1715/1602 +f 1564/1687/1603 1595/1714/1603 1596/1717/1603 +f 1552/1690/1604 1551/1688/1604 1582/1716/1604 +f 1566/1691/1605 1565/1689/1605 1596/1717/1605 +f 1553/1692/1606 1552/1690/1606 1583/1718/1606 +f 1567/1693/1607 1566/1691/1607 1597/1719/1607 +f 1553/1692/1608 1584/1720/1608 1585/1722/1608 +f 1567/1693/1609 1598/1721/1609 1599/1723/1609 +f 1555/1696/1610 1554/1694/1610 1585/1722/1610 +f 1568/1695/1611 1599/1723/1611 1600/1725/1611 +f 1555/1696/1612 1586/1724/1612 1587/1726/1612 +f 1569/1697/1613 1600/1725/1613 1601/1727/1613 +f 1556/1698/1614 1587/1726/1614 1588/1728/1614 +f 1570/1699/1615 1601/1727/1615 1602/1729/1615 +f 1558/1702/1616 1557/1700/1616 1588/1728/1616 +f 1571/1701/1617 1602/1729/1617 1603/1731/1617 +f 1558/1702/1618 1589/1730/1618 1590/1732/1618 +f 1572/1703/1620 1603/1731/1620 1604/1735/1620 +f 1560/1708/2094 1559/1704/2094 1590/1732/2094 +f 1546/1706/1622 1577/1734/1622 1578/1737/1622 +f 1574/1710/1623 1573/1707/1623 1604/1735/1623 +f 1560/1708/1624 1591/1736/1624 1592/1739/1624 +f 1547/1709/1625 1578/1737/1625 1579/1740/1625 +f 1574/1710/1626 1605/1738/1626 1606/1741/1626 +f 1562/1681/1627 1561/1680/1627 1592/1739/1627 +f 1548/1711/1628 1579/1740/1628 1580/1743/1628 +f 1575/1712/1629 1606/1741/1629 1607/1744/1629 +f 1562/1681/2095 1593/1742/2095 1594/1713/2095 +f 1549/1682/1631 1580/1743/1631 1581/1715/1631 +f 1591/1736/1633 1622/1776/1633 1623/1746/1633 +f 1578/1737/1634 1609/1777/1634 1610/1747/1634 +f 1605/1738/2096 1636/1778/2096 1637/1748/2096 +f 1593/1742/1636 1592/1739/1636 1623/1746/1636 +f 1579/1740/1637 1610/1747/1637 1611/1750/1637 +f 1606/1741/1638 1637/1748/1638 1638/1751/1638 +f 1593/1742/2097 1624/1749/2097 1625/1752/2097 +f 1581/1715/1640 1580/1743/1640 1611/1750/1640 +f 1595/1714/1642 1594/1713/1642 1625/1752/1642 +f 1581/1715/1643 1612/1753/1643 1613/1756/1643 +f 1595/1714/1644 1626/1755/1644 1627/1757/1644 +f 1583/1718/1645 1582/1716/1645 1613/1756/1645 +f 1597/1719/1646 1596/1717/1646 1627/1757/1646 +f 1584/1720/1647 1583/1718/1647 1614/1758/1647 +f 1598/1721/1648 1597/1719/1648 1628/1759/1648 +f 1584/1720/1649 1615/1760/1649 1616/1762/1649 +f 1598/1721/1650 1629/1761/1650 1630/1763/1650 +f 1585/1722/1651 1616/1762/1651 1617/1764/1651 +f 1599/1723/1652 1630/1763/1652 1631/1765/1652 +f 1586/1724/1653 1617/1764/1653 1618/1766/1653 +f 1600/1725/1654 1631/1765/1654 1632/1767/1654 +f 1587/1726/1655 1618/1766/1655 1619/1768/1655 +f 1601/1727/1656 1632/1767/1656 1633/1769/1656 +f 1589/1730/1657 1588/1728/1657 1619/1768/1657 +f 1603/1731/2098 1602/1729/2098 1633/1769/2098 +f 1589/1730/1659 1620/1770/1659 1621/1772/1659 +f 1603/1731/1661 1634/1771/1661 1635/1775/1661 +f 1591/1736/2099 1590/1732/2099 1621/1772/2099 +f 1577/1734/1663 1608/1774/1663 1609/1777/1663 +f 1605/1738/1664 1604/1735/1664 1635/1775/1664 +f 1624/1749/2100 1655/1810/2100 1656/1779/2100 +f 1611/1750/1666 1642/1811/1666 1643/1780/1666 +f 1626/1755/1668 1625/1752/1668 1656/1779/1668 +f 1612/1753/1669 1643/1780/1669 1644/1784/1669 +f 1626/1755/1670 1657/1783/1670 1658/1785/1670 +f 1614/1758/1671 1613/1756/1671 1644/1784/1671 +f 1628/1759/1672 1627/1757/1672 1658/1785/1672 +f 1614/1758/1673 1645/1786/1673 1646/1788/1673 +f 1629/1761/1674 1628/1759/1674 1659/1787/1674 +f 1615/1760/1675 1646/1788/1675 1647/1790/1675 +f 1629/1761/1676 1660/1789/1676 1661/1791/1676 +f 1617/1764/1677 1616/1762/1677 1647/1790/1677 +f 1630/1763/1678 1661/1791/1678 1662/1793/1678 +f 1617/1764/1679 1648/1792/1679 1649/1794/1679 +f 1631/1765/1680 1662/1793/1680 1663/1795/1680 +f 1618/1766/1681 1649/1794/1681 1650/1796/1681 +f 1632/1767/1682 1663/1795/1682 1664/1797/1682 +f 1620/1770/1683 1619/1768/1683 1650/1796/1683 +f 1634/1771/1684 1633/1769/1684 1664/1797/1684 +f 1620/1770/1685 1651/1798/1685 1652/1800/1685 +f 1634/1771/1687 1665/1799/1687 1666/1803/1687 +f 1622/1776/2101 1621/1772/2101 1652/1800/2101 +f 1608/1774/1689 1639/1802/1689 1640/1805/1689 +f 1636/1778/1690 1635/1775/1690 1666/1803/1690 +f 1622/1776/1691 1653/1804/1691 1654/1807/1691 +f 1609/1777/1692 1640/1805/1692 1641/1808/1692 +f 1636/1778/1693 1667/1806/1693 1668/1809/1693 +f 1624/1749/1694 1623/1746/1694 1654/1807/1694 +f 1610/1747/1695 1641/1808/1695 1642/1811/1695 +f 1637/1748/1696 1668/1809/1696 1669/1782/1696 +f 1657/1783/1697 1688/1844/1697 1689/1812/1697 +f 1645/1786/1698 1644/1784/1698 1675/1813/1698 +f 1659/1787/1699 1658/1785/1699 1689/1812/1699 +f 1645/1786/2102 1676/1814/2102 1677/1816/2102 +f 1660/1789/1701 1659/1787/1701 1690/1815/1701 +f 1646/1788/1702 1677/1816/1702 1678/1818/1702 +f 1660/1789/1703 1691/1817/1703 1692/1819/1703 +f 1648/1792/1704 1647/1790/1704 1678/1818/1704 +f 1661/1791/1705 1692/1819/1705 1693/1821/1705 +f 1648/1792/1706 1679/1820/1706 1680/1822/1706 +f 1662/1793/1707 1693/1821/1707 1694/1823/1707 +f 1649/1794/1708 1680/1822/1708 1681/1824/1708 +f 1663/1795/1709 1694/1823/1709 1695/1825/1709 +f 1651/1798/1710 1650/1796/1710 1681/1824/1710 +f 1665/1799/2103 1664/1797/2103 1695/1825/2103 +f 1651/1798/1712 1682/1826/1712 1683/1828/1712 +f 1665/1799/1714 1696/1827/1714 1697/1831/1714 +f 1653/1804/1715 1652/1800/1715 1683/1828/1715 +f 1640/1805/1716 1639/1802/1716 1670/1830/1716 +f 1667/1806/1717 1666/1803/1717 1697/1831/1717 +f 1653/1804/1718 1684/1832/1718 1685/1835/1718 +f 1641/1808/1719 1640/1805/1719 1671/1833/1719 +f 1667/1806/1720 1698/1834/1720 1699/1837/1720 +f 1655/1810/1721 1654/1807/1721 1685/1835/1721 +f 1641/1808/1722 1672/1836/1722 1673/1839/1722 +f 1668/1809/1723 1699/1837/1723 1700/1840/1723 +f 1655/1810/1724 1686/1838/1724 1687/1841/1724 +f 1642/1811/1725 1673/1839/1725 1674/1842/1725 +f 1657/1783/1727 1656/1779/1727 1687/1841/1727 +f 1643/1780/2104 1674/1842/2104 1675/1813/2104 +f 1691/1817/1729 1690/1815/1729 1721/1845/1729 +f 1677/1816/1730 1708/1877/1730 1709/1847/1730 +f 1691/1817/1731 1722/1846/1731 1723/1848/1731 +f 1678/1818/1732 1709/1847/1732 1710/1849/1732 +f 1692/1819/1733 1723/1848/1733 1724/1850/1733 +f 1679/1820/1734 1710/1849/1734 1711/1851/1734 +f 1693/1821/1735 1724/1850/1735 1725/1852/1735 +f 1680/1822/1736 1711/1851/1736 1712/1853/1736 +f 1695/1825/1737 1694/1823/1737 1725/1852/1737 +f 1682/1826/1738 1681/1824/1738 1712/1853/1738 +f 1696/1827/1739 1695/1825/1739 1726/1854/1739 +f 1682/1826/1740 1713/1855/1740 1714/1857/1740 +f 1696/1827/1742 1727/1856/1742 1728/1860/1742 +f 1684/1832/1743 1683/1828/1743 1714/1857/1743 +f 1670/1830/1744 1701/1859/1744 1702/1862/1744 +f 1698/1834/1745 1697/1831/1745 1728/1860/1745 +f 1684/1832/1746 1715/1861/1746 1716/1864/1746 +f 1671/1833/1747 1702/1862/1747 1703/1865/1747 +f 1699/1837/1748 1698/1834/1748 1729/1863/1748 +f 1686/1838/1749 1685/1835/1749 1716/1864/1749 +f 1672/1836/1750 1703/1865/1750 1704/1868/1750 +f 1700/1840/1751 1699/1837/1751 1730/1866/1751 +f 1686/1838/1752 1717/1867/1752 1718/1870/1752 +f 1674/1842/1753 1673/1839/1753 1704/1868/1753 +f 1688/1844/1755 1687/1841/1755 1718/1870/1755 +f 1674/1842/1756 1705/1871/1756 1706/1874/1756 +f 1688/1844/1757 1719/1873/1757 1720/1875/1757 +f 1676/1814/1758 1675/1813/1758 1706/1874/1758 +f 1690/1815/1759 1689/1812/1759 1720/1875/1759 +f 1676/1814/1760 1707/1876/1760 1708/1877/1760 +f 1723/1848/1761 1754/1909/1761 1755/1878/1761 +f 1710/1849/1762 1741/1910/1762 1742/1879/1762 +f 1724/1850/1763 1755/1878/1763 1756/1880/1763 +f 1712/1853/1764 1711/1851/1764 1742/1879/1764 +f 1725/1852/1765 1756/1880/1765 1757/1882/1765 +f 1713/1855/1766 1712/1853/1766 1743/1881/1766 +f 1727/1856/1767 1726/1854/1767 1757/1882/1767 +f 1713/1855/1768 1744/1883/1768 1745/1885/1768 +f 1727/1856/1770 1758/1884/1770 1759/1888/1770 +f 1715/1861/1771 1714/1857/1771 1745/1885/1771 +f 1701/1859/1772 1732/1887/1772 1733/1890/1772 +f 1728/1860/1773 1759/1888/1773 1760/1891/1773 +f 1715/1861/1774 1746/1889/1774 1747/1892/1774 +f 1703/1865/1775 1702/1862/1775 1733/1890/1775 +f 1729/1863/1776 1760/1891/1776 1761/1894/1776 +f 1717/1867/1777 1716/1864/1777 1747/1892/1777 +f 1703/1865/1778 1734/1893/1778 1735/1896/1778 +f 1730/1866/1779 1761/1894/1779 1762/1897/1779 +f 1717/1867/1780 1748/1895/1780 1749/1898/1780 +f 1704/1868/1781 1735/1896/1781 1736/1899/1781 +f 1719/1873/1783 1718/1870/1783 1749/1898/1783 +f 1705/1871/1784 1736/1899/1784 1737/1902/1784 +f 1719/1873/1785 1750/1901/1785 1751/1903/1785 +f 1706/1874/1786 1737/1902/1786 1738/1904/1786 +f 1721/1845/1787 1720/1875/1787 1751/1903/1787 +f 1708/1877/1788 1707/1876/1788 1738/1904/1788 +f 1722/1846/1789 1721/1845/1789 1752/1905/1789 +f 1709/1847/1790 1708/1877/1790 1739/1906/1790 +f 1723/1848/1791 1722/1846/1791 1753/1907/1791 +f 1710/1849/1792 1709/1847/1792 1740/1908/1792 +f 1756/1880/1793 1787/1943/1793 1788/1911/1793 +f 1744/1883/1794 1743/1881/1794 1774/1912/1794 +f 1758/1884/1795 1757/1882/1795 1788/1911/1795 +f 1744/1883/1796 1775/1913/1796 1776/1915/1796 +f 1758/1884/1798 1789/1914/1798 1790/1918/1798 +f 1746/1889/2105 1745/1885/2105 1776/1915/2105 +f 1732/1887/2106 1763/1917/2106 1764/1920/2106 +f 1759/1888/1801 1790/1918/1801 1791/1921/1801 +f 1746/1889/1802 1777/1919/1802 1778/1922/1802 +f 1734/1893/1803 1733/1890/1803 1764/1920/1803 +f 1760/1891/1804 1791/1921/1804 1792/1924/1804 +f 1748/1895/1805 1747/1892/1805 1778/1922/1805 +f 1734/1893/1806 1765/1923/1806 1766/1926/1806 +f 1762/1897/2107 1761/1894/2107 1792/1924/2107 +f 1748/1895/2108 1779/1925/2108 1780/1928/2108 +f 1736/1899/1809 1735/1896/1809 1766/1926/1809 +f 1750/1901/1811 1749/1898/1811 1780/1928/1811 +f 1736/1899/1812 1767/1929/1812 1768/1932/1812 +f 1750/1901/1813 1781/1931/1813 1782/1933/1813 +f 1738/1904/1814 1737/1902/1814 1768/1932/1814 +f 1752/1905/1815 1751/1903/1815 1782/1933/1815 +f 1739/1906/2109 1738/1904/2109 1769/1934/2109 +f 1753/1907/1817 1752/1905/1817 1783/1935/1817 +f 1740/1908/1818 1739/1906/1818 1770/1936/1818 +f 1754/1909/1819 1753/1907/1819 1784/1937/1819 +f 1740/1908/1820 1771/1938/1820 1772/1940/1820 +f 1754/1909/1821 1785/1939/1821 1786/1941/1821 +f 1741/1910/1822 1772/1940/1822 1773/1942/1822 +f 1755/1878/2110 1786/1941/2110 1787/1943/2110 +f 1742/1879/1824 1773/1942/1824 1774/1912/1824 +f 1789/1914/1826 1820/1976/1826 1821/1946/1826 +f 1777/1919/1827 1776/1915/1827 1807/1947/1827 +f 1763/1917/1828 1794/1945/1828 1795/1949/1828 +f 1790/1918/1829 1821/1946/1829 1822/1950/1829 +f 1777/1919/1830 1808/1948/1830 1809/1951/1830 +f 1764/1920/1831 1795/1949/1831 1796/1952/1831 +f 1792/1924/1832 1791/1921/1832 1822/1950/1832 +f 1779/1925/1833 1778/1922/1833 1809/1951/1833 +f 1766/1926/1834 1765/1923/1834 1796/1952/1834 +f 1792/1924/2111 1823/1953/2111 1824/1956/2111 +f 1779/1925/1836 1810/1954/1836 1811/1957/1836 +f 1767/1929/1837 1766/1926/1837 1797/1955/1837 +f 1781/1931/1839 1780/1928/1839 1811/1957/1839 +f 1767/1929/1840 1798/1958/1840 1799/1961/1840 +f 1781/1931/1841 1812/1960/1841 1813/1962/1841 +f 1768/1932/1842 1799/1961/1842 1800/1963/1842 +f 1783/1935/1843 1782/1933/1843 1813/1962/1843 +f 1770/1936/1844 1769/1934/1844 1800/1963/1844 +f 1784/1937/1845 1783/1935/1845 1814/1964/1845 +f 1770/1936/1846 1801/1965/1846 1802/1967/1846 +f 1785/1939/1847 1784/1937/1847 1815/1966/1847 +f 1771/1938/1848 1802/1967/1848 1803/1969/1848 +f 1785/1939/1849 1816/1968/1849 1817/1970/1849 +f 1772/1940/1850 1803/1969/1850 1804/1971/1850 +f 1786/1941/2112 1817/1970/2112 1818/1972/2112 +f 1774/1912/1852 1773/1942/1852 1804/1971/1852 +f 1787/1943/1853 1818/1972/1853 1819/1974/1853 +f 1775/1913/1854 1774/1912/1854 1805/1973/1854 +f 1789/1914/1855 1788/1911/1855 1819/1974/1855 +f 1775/1913/1856 1806/1975/1856 1807/1947/1856 +f 1795/1949/1857 1826/2008/1857 1827/1977/1857 +f 1822/1950/1858 1853/2009/1858 1854/1978/1858 +f 1810/1954/1859 1809/1951/1859 1840/1979/1859 +f 1796/1952/1860 1827/1977/1860 1828/1981/1860 +f 1824/1956/1861 1823/1953/1861 1854/1978/1861 +f 1810/1954/2113 1841/1980/2113 1842/1983/2113 +f 1798/1958/1863 1797/1955/1863 1828/1981/1863 +f 1812/1960/1865 1811/1957/1865 1842/1983/1865 +f 1798/1958/2114 1829/1984/2114 1830/1987/2114 +f 1812/1960/1867 1843/1986/1867 1844/1988/1867 +f 1800/1963/1868 1799/1961/1868 1830/1987/1868 +f 1814/1964/1869 1813/1962/1869 1844/1988/1869 +f 1800/1963/1870 1831/1989/1870 1832/1991/1870 +f 1814/1964/1871 1845/1990/1871 1846/1992/1871 +f 1801/1965/1872 1832/1991/1872 1833/1993/1872 +f 1816/1968/1873 1815/1966/1873 1846/1992/1873 +f 1802/1967/1874 1833/1993/1874 1834/1995/1874 +f 1816/1968/1875 1847/1994/1875 1848/1996/1875 +f 1803/1969/1876 1834/1995/1876 1835/1997/1876 +f 1817/1970/2115 1848/1996/2115 1849/1998/2115 +f 1805/1973/1878 1804/1971/1878 1835/1997/1878 +f 1818/1972/1879 1849/1998/1879 1850/2000/1879 +f 1806/1975/1880 1805/1973/1880 1836/1999/1880 +f 1820/1976/1881 1819/1974/1881 1850/2000/1881 +f 1806/1975/1882 1837/2001/1882 1838/2003/1882 +f 1820/1976/1884 1851/2002/1884 1852/2006/1884 +f 1808/1948/2116 1807/1947/2116 1838/2003/2116 +f 1794/1945/1886 1825/2005/1886 1826/2008/1886 +f 1821/1946/1887 1852/2006/1887 1853/2009/1887 +f 1808/1948/1888 1839/2007/1888 1840/1979/1888 +f 1828/1981/1889 1859/2042/1889 1860/2010/1889 +f 1843/1986/1891 1842/1983/1891 1873/2013/1891 +f 1829/1984/1892 1860/2010/1892 1861/2015/1892 +f 1843/1986/1893 1874/2014/1893 1875/2016/1893 +f 1831/1989/1894 1830/1987/1894 1861/2015/1894 +f 1845/1990/1895 1844/1988/1895 1875/2016/1895 +f 1832/1991/1896 1831/1989/1896 1862/2017/1896 +f 1845/1990/1897 1876/2018/1897 1877/2020/1897 +f 1832/1991/1898 1863/2019/1898 1864/2021/1898 +f 1847/1994/1899 1846/1992/1899 1877/2020/1899 +f 1833/1993/1900 1864/2021/1900 1865/2023/1900 +f 1847/1994/1901 1878/2022/1901 1879/2024/1901 +f 1834/1995/1902 1865/2023/1902 1866/2025/1902 +f 1848/1996/1903 1879/2024/1903 1880/2026/1903 +f 1836/1999/1904 1835/1997/1904 1866/2025/1904 +f 1849/1998/1905 1880/2026/1905 1881/2028/1905 +f 1837/2001/1906 1836/1999/1906 1867/2027/1906 +f 1851/2002/1907 1850/2000/1907 1881/2028/1907 +f 1837/2001/1908 1868/2029/1908 1869/2031/1908 +f 1852/2006/1910 1851/2002/1910 1882/2030/1910 +f 1839/2007/2117 1838/2003/2117 1869/2031/2117 +f 1825/2005/1912 1856/2033/1912 1857/2036/1912 +f 1852/2006/1913 1883/2034/1913 1884/2037/1913 +f 1839/2007/1914 1870/2035/1914 1871/2038/1914 +f 1826/2008/1915 1857/2036/1915 1858/2039/1915 +f 1853/2009/1916 1884/2037/1916 1885/2040/1916 +f 1841/1980/1917 1840/1979/1917 1871/2038/1917 +f 1827/1977/1918 1858/2039/1918 1859/2042/1918 +f 1855/1982/1919 1854/1978/1919 1885/2040/1919 +f 1841/1980/2118 1872/2041/2118 1873/2013/2118 +f 1862/2017/1921 1861/2015/1921 1893/2043/1921 +f 1876/2018/1922 1875/2016/1922 1907/2045/1922 +f 1862/2017/1923 1894/2044/1923 1895/2047/1923 +f 1877/2020/1924 1876/2018/1924 1908/2046/1924 +f 1863/2019/1925 1895/2047/1925 1896/2049/1925 +f 1878/2022/1926 1877/2020/1926 1909/2048/1926 +f 1864/2021/1927 1896/2049/1927 1897/2051/1927 +f 1878/2022/1928 1910/2050/1928 1911/2052/1928 +f 1865/2023/1929 1897/2051/1929 1898/2053/1929 +f 1879/2024/1930 1911/2052/1930 1912/2054/1930 +f 1867/2027/1931 1866/2025/1931 1898/2053/1931 +f 1881/2028/1932 1880/2026/1932 1912/2054/1932 +f 1868/2029/1933 1867/2027/1933 1899/2055/1933 +f 1882/2030/1934 1881/2028/1934 1913/2056/1934 +f 1868/2029/1935 1900/2057/1935 1901/2059/1935 +f 1883/2034/1937 1882/2030/1937 1914/2058/1937 +f 1870/2035/2119 1869/2031/2119 1901/2059/2119 +f 1856/2033/1939 1888/2061/1939 1889/2064/1939 +f 1883/2034/1940 1915/2062/1940 1916/2065/1940 +f 1870/2035/1941 1902/2063/1941 1903/2066/1941 +f 1857/2036/2120 1889/2064/2120 1890/2067/2120 +f 1884/2037/1943 1916/2065/1943 1917/2068/1943 +f 1872/2041/1944 1871/2038/1944 1903/2066/1944 +f 1859/2042/1945 1858/2039/1945 1890/2067/1945 +f 1885/2040/1946 1917/2068/1946 1918/2071/1946 +f 1872/2041/2121 1904/2069/2121 1905/2072/2121 +f 1859/2042/1948 1891/2070/1948 1892/2073/1948 +f 1874/2014/1950 1873/2013/1950 1905/2072/1950 +f 1860/2010/1951 1892/2073/1951 1893/2043/1951 +f 1874/2014/1952 1906/2075/1952 1907/2045/1952 +f 1895/2047/1953 1926/2108/1953 1927/2076/1953 +f 1910/2050/1954 1909/2048/1954 1940/2077/1954 +f 1896/2049/1955 1927/2076/1955 1928/2079/1955 +f 1910/2050/1956 1941/2078/1956 1942/2080/1956 +f 1897/2051/1957 1928/2079/1957 1929/2081/1957 +f 1911/2052/1958 1942/2080/1958 1943/2082/1958 +f 1899/2055/1959 1898/2053/1959 1929/2081/1959 +f 1913/2056/1960 1912/2054/1960 1943/2082/1960 +f 1900/2057/1961 1899/2055/1961 1930/2083/1961 +f 1914/2058/1962 1913/2056/1962 1944/2084/1962 +f 1900/2057/1963 1931/2085/1963 1932/2087/1963 +f 1915/2062/2122 1914/2058/2122 1945/2086/2122 +f 1902/2063/1966 1901/2059/1966 1932/2087/1966 +f 1888/2061/1967 1919/2089/1967 1920/2092/1967 +f 1915/2062/1968 1946/2090/1968 1947/2093/1968 +f 1902/2063/1969 1933/2091/1969 1934/2094/1969 +f 1890/2067/1970 1889/2064/1970 1920/2092/1970 +f 1916/2065/1971 1947/2093/1971 1948/2096/1971 +f 1904/2069/1972 1903/2066/1972 1934/2094/1972 +f 1891/2070/1973 1890/2067/1973 1921/2095/1973 +f 1917/2068/1974 1948/2096/1974 1949/2099/1974 +f 1904/2069/1975 1935/2097/1975 1936/2100/1975 +f 1892/2073/2123 1891/2070/2123 1922/2098/2123 +f 1906/2075/1978 1905/2072/1978 1936/2100/1978 +f 1893/2043/1979 1892/2073/1979 1923/2101/1979 +f 1906/2075/1980 1937/2103/1980 1938/2105/1980 +f 1894/2044/1981 1893/2043/1981 1924/2104/1981 +f 1908/2046/1982 1907/2045/1982 1938/2105/1982 +f 1895/2047/1983 1894/2044/1983 1925/2106/1983 +f 1909/2048/1984 1908/2046/1984 1939/2107/1984 +f 1928/2079/1985 1959/2140/1985 1960/2109/1985 +f 1942/2080/1986 1973/2141/1986 1974/2110/1986 +f 1930/2083/1987 1929/2081/1987 1960/2109/1987 +f 1943/2082/1988 1974/2110/1988 1975/2112/1988 +f 1931/2085/1989 1930/2083/1989 1961/2111/1989 +f 1944/2084/1990 1975/2112/1990 1976/2114/1990 +f 1931/2085/1991 1962/2113/1991 1963/2115/1991 +f 1945/2086/1993 1976/2114/1993 1977/2118/1993 +f 1933/2091/1994 1932/2087/1994 1963/2115/1994 +f 1919/2089/1995 1950/2117/1995 1951/2120/1995 +f 1946/2090/1996 1977/2118/1996 1978/2121/1996 +f 1933/2091/1997 1964/2119/1997 1965/2122/1997 +f 1920/2092/1998 1951/2120/1998 1952/2123/1998 +f 1947/2093/1999 1978/2121/1999 1979/2124/1999 +f 1935/2097/2000 1934/2094/2000 1965/2122/2000 +f 1922/2098/2001 1921/2095/2001 1952/2123/2001 +f 1949/2099/2002 1948/2096/2002 1979/2124/2002 +f 1935/2097/2003 1966/2125/2003 1967/2128/2003 +f 1922/2098/2004 1953/2126/2004 1954/2129/2004 +f 1937/2103/2006 1936/2100/2006 1967/2128/2006 +f 1924/2104/2007 1923/2101/2007 1954/2129/2007 +f 1937/2103/2008 1968/2131/2008 1969/2133/2008 +f 1924/2104/2009 1955/2132/2009 1956/2134/2009 +f 1939/2107/2010 1938/2105/2010 1969/2133/2010 +f 1926/2108/2124 1925/2106/2124 1956/2134/2124 +f 1940/2077/2012 1939/2107/2012 1970/2135/2012 +f 1926/2108/2013 1957/2136/2013 1958/2138/2013 +f 1941/2078/2014 1940/2077/2014 1971/2137/2014 +f 1927/2076/2015 1958/2138/2015 1959/2140/2015 +f 1941/2078/2016 1972/2139/2016 1973/2141/2016 +f 1962/2113/2017 1961/2111/2017 11/13/2017 +f 1975/2112/2125 23/15/2125 24/19/2125 +f 1962/2113/2019 12/17/2019 13/21/2019 +f 1976/2114/2021 24/19/2021 1984/27/2021 +f 1964/2119/2126 1963/2115/2126 13/21/2126 +f 1951/2120/2023 1950/2117/2023 1/23/2023 +f 1977/2118/2024 1984/27/2024 25/33/2024 +f 1964/2119/2025 14/28/2025 15/35/2025 +f 1951/2120/2026 2/31/2026 3/37/2026 +f 1979/2124/2027 1978/2121/2027 25/33/2027 +f 1966/2125/2028 1965/2122/2028 15/35/2028 +f 1953/2126/2029 1952/2123/2029 3/37/2029 +f 1979/2124/2030 1985/39/2030 1986/45/2030 +f 1966/2125/2127 16/41/2127 1982/47/2127 +f 1954/2129/2032 1953/2126/2032 4/42/2032 +f 1968/2131/2034 1967/2128/2034 1982/47/2034 +f 1955/2132/2128 1954/2129/2128 5/48/2128 +f 1968/2131/2036 17/51/2036 1983/56/2036 +f 1956/2134/2037 1955/2132/2037 6/54/2037 +f 1970/2135/2038 1969/2133/2038 1983/56/2038 +f 1957/2136/2129 1956/2134/2129 7/58/2129 +f 1970/2135/2040 18/60/2040 19/63/2040 +f 1958/2138/2041 1957/2136/2041 8/62/2041 +f 1971/2137/2042 19/63/2042 20/1/2042 +f 1959/2140/2043 1958/2138/2043 9/4/2043 +f 1972/2139/2044 20/1/2044 21/7/2044 +f 1960/2109/2045 1959/2140/2045 10/6/2045 +f 1973/2141/2046 21/7/2046 22/11/2046 +f 1961/2111/2047 1960/2109/2047 1981/9/2047 +f 1974/2110/2048 22/11/2048 23/15/2048 diff --git a/examples/models/rlights.h b/examples/models/rlights.h index 19504473a..6593ab4a5 100644 --- a/examples/models/rlights.h +++ b/examples/models/rlights.h @@ -33,6 +33,8 @@ #ifndef RLIGHTS_H #define RLIGHTS_H +#include "raylib.h" + //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- @@ -65,16 +67,11 @@ typedef struct { extern "C" { // Prevents name mangling of functions #endif -//---------------------------------------------------------------------------------- -// Global Variables Definition -//---------------------------------------------------------------------------------- -int lightsCount = 0; // Current amount of created lights - //---------------------------------------------------------------------------------- // Module Functions Declaration //---------------------------------------------------------------------------------- -Light CreateLight(int type, Vector3 pos, Vector3 targ, Color color, Shader shader); // Defines a light and get locations from PBR shader -void UpdateLightValues(Shader shader, Light light); // Send to PBR shader light values +void CreateLight(int type, Vector3 pos, Vector3 targ, Color color, Shader shader); // Defines a light and get locations from PBR shader +void UpdateLightValues(Shader shader, Light light); // Send to PBR shader light values #ifdef __cplusplus } @@ -106,7 +103,8 @@ void UpdateLightValues(Shader shader, Light light); //---------------------------------------------------------------------------------- // Global Variables Definition //---------------------------------------------------------------------------------- -// ... +static Light lights[MAX_LIGHTS] = { 0 }; +static int lightsCount = 0; // Current amount of created lights //---------------------------------------------------------------------------------- // Module specific Functions Declaration @@ -118,7 +116,7 @@ void UpdateLightValues(Shader shader, Light light); //---------------------------------------------------------------------------------- // Defines a light and get locations from PBR shader -Light CreateLight(int type, Vector3 pos, Vector3 targ, Color color, Shader shader) +void CreateLight(int type, Vector3 pos, Vector3 targ, Color color, Shader shader) { Light light = { 0 }; @@ -148,10 +146,10 @@ Light CreateLight(int type, Vector3 pos, Vector3 targ, Color color, Shader shade light.colorLoc = GetShaderLocation(shader, colorName); UpdateLightValues(shader, light); + + lights[lightsCount] = light; lightsCount++; } - - return light; } // Send to PBR shader light values diff --git a/examples/network/network_ping_pong.c b/examples/network/network_ping_pong.c index 719f6739e..684678c51 100644 --- a/examples/network/network_ping_pong.c +++ b/examples/network/network_ping_pong.c @@ -48,178 +48,178 @@ char recvBuffer[512]; // Attempt to connect to the network (Either TCP, or UDP) void NetworkConnect() { - // If the server is configured as UDP, ignore connection requests - if (server_cfg.type == SOCKET_UDP && client_cfg.type == SOCKET_UDP) { - ping = true; - connected = true; - } else { - // If the client is connected, run the server code to check for a connection - if (client_connected) { - int active = CheckSockets(socket_set, 0); - if (active != 0) { - TraceLog(LOG_DEBUG, - "There are currently %d socket(s) with data to be processed.", active); - } - if (active > 0) { - if ((connection = SocketAccept(server_res->socket, &connection_cfg)) != NULL) { - AddSocket(socket_set, connection); - ping = true; - connected = true; - } - } - } else { - // Check if we're connected every _delay_ seconds - elapsed += GetFrameTime(); - if (elapsed > delay) { - if (IsSocketConnected(client_res->socket)) { - client_connected = true; - } - elapsed = 0.0f; - } - } - } + // If the server is configured as UDP, ignore connection requests + if (server_cfg.type == SOCKET_UDP && client_cfg.type == SOCKET_UDP) { + ping = true; + connected = true; + } else { + // If the client is connected, run the server code to check for a connection + if (client_connected) { + int active = CheckSockets(socket_set, 0); + if (active != 0) { + TraceLog(LOG_DEBUG, + "There are currently %d socket(s) with data to be processed.", active); + } + if (active > 0) { + if ((connection = SocketAccept(server_res->socket, &connection_cfg)) != NULL) { + AddSocket(socket_set, connection); + ping = true; + connected = true; + } + } + } else { + // Check if we're connected every _delay_ seconds + elapsed += GetFrameTime(); + if (elapsed > delay) { + if (IsSocketConnected(client_res->socket)) { + client_connected = true; + } + elapsed = 0.0f; + } + } + } } // Once connected to the network, check the sockets for pending information // and when information is ready, send either a Ping or a Pong. void NetworkUpdate() { - // CheckSockets - // - // If any of the sockets in the socket_set are pending (received data, or requests) - // then mark the socket as being ready. You can check this with IsSocketReady(client_res->socket) - int active = CheckSockets(socket_set, 0); - if (active != 0) { - TraceLog(LOG_DEBUG, - "There are currently %d socket(s) with data to be processed.", active); - } + // CheckSockets + // + // If any of the sockets in the socket_set are pending (received data, or requests) + // then mark the socket as being ready. You can check this with IsSocketReady(client_res->socket) + int active = CheckSockets(socket_set, 0); + if (active != 0) { + TraceLog(LOG_DEBUG, + "There are currently %d socket(s) with data to be processed.", active); + } - // IsSocketReady - // - // If the socket is ready, attempt to receive data from the socket - int bytesRecv = 0; - if (server_cfg.type == SOCKET_UDP && client_cfg.type == SOCKET_UDP) { - if (IsSocketReady(client_res->socket)) { - bytesRecv = SocketReceive(client_res->socket, recvBuffer, msglen); - } - if (IsSocketReady(server_res->socket)) { - bytesRecv = SocketReceive(server_res->socket, recvBuffer, msglen); - } - } else { - if (IsSocketReady(connection)) { - bytesRecv = SocketReceive(connection, recvBuffer, msglen); - } - } + // IsSocketReady + // + // If the socket is ready, attempt to receive data from the socket + int bytesRecv = 0; + if (server_cfg.type == SOCKET_UDP && client_cfg.type == SOCKET_UDP) { + if (IsSocketReady(client_res->socket)) { + bytesRecv = SocketReceive(client_res->socket, recvBuffer, msglen); + } + if (IsSocketReady(server_res->socket)) { + bytesRecv = SocketReceive(server_res->socket, recvBuffer, msglen); + } + } else { + if (IsSocketReady(connection)) { + bytesRecv = SocketReceive(connection, recvBuffer, msglen); + } + } - // If we received data, was that data a "Ping!" or a "Pong!" - if (bytesRecv > 0) { - if (strcmp(recvBuffer, pingmsg) == 0) { pong = true; } - if (strcmp(recvBuffer, pongmsg) == 0) { ping = true; } - } + // If we received data, was that data a "Ping!" or a "Pong!" + if (bytesRecv > 0) { + if (strcmp(recvBuffer, pingmsg) == 0) { pong = true; } + if (strcmp(recvBuffer, pongmsg) == 0) { ping = true; } + } - // After each delay has expired, send a response "Ping!" for a "Pong!" and vice versa - elapsed += GetFrameTime(); - if (elapsed > delay) { - if (ping) { - ping = false; - if (server_cfg.type == SOCKET_UDP && client_cfg.type == SOCKET_UDP) { - SocketSend(client_res->socket, pingmsg, msglen); - } else { - SocketSend(client_res->socket, pingmsg, msglen); - } - } else if (pong) { - pong = false; - if (server_cfg.type == SOCKET_UDP && client_cfg.type == SOCKET_UDP) { - SocketSend(client_res->socket, pongmsg, msglen); - } else { - SocketSend(client_res->socket, pongmsg, msglen); - } - } - elapsed = 0.0f; - } + // After each delay has expired, send a response "Ping!" for a "Pong!" and vice versa + elapsed += GetFrameTime(); + if (elapsed > delay) { + if (ping) { + ping = false; + if (server_cfg.type == SOCKET_UDP && client_cfg.type == SOCKET_UDP) { + SocketSend(client_res->socket, pingmsg, msglen); + } else { + SocketSend(client_res->socket, pingmsg, msglen); + } + } else if (pong) { + pong = false; + if (server_cfg.type == SOCKET_UDP && client_cfg.type == SOCKET_UDP) { + SocketSend(client_res->socket, pongmsg, msglen); + } else { + SocketSend(client_res->socket, pongmsg, msglen); + } + } + elapsed = 0.0f; + } } int main() { - // Setup - int screenWidth = 800; - int screenHeight = 450; - InitWindow( - screenWidth, screenHeight, "raylib [network] example - ping pong"); - SetTargetFPS(60); - SetTraceLogLevel(LOG_DEBUG); + // Setup + int screenWidth = 800; + int screenHeight = 450; + InitWindow( + screenWidth, screenHeight, "raylib [network] example - ping pong"); + SetTargetFPS(60); + SetTraceLogLevel(LOG_DEBUG); - // Networking - InitNetwork(); + // Networking + InitNetwork(); - // Create the server - // - // Performs - // getaddrinfo - // socket - // setsockopt - // bind - // listen - server_res = AllocSocketResult(); - if (!SocketCreate(&server_cfg, server_res)) { - TraceLog(LOG_WARNING, "Failed to open server: status %d, errno %d", - server_res->status, server_res->socket->status); - } else { - if (!SocketBind(&server_cfg, server_res)) { - TraceLog(LOG_WARNING, "Failed to bind server: status %d, errno %d", - server_res->status, server_res->socket->status); - } else { - if (!(server_cfg.type == SOCKET_UDP)) { - if (!SocketListen(&server_cfg, server_res)) { - TraceLog(LOG_WARNING, - "Failed to start listen server: status %d, errno %d", - server_res->status, server_res->socket->status); - } - } - } - } + // Create the server + // + // Performs + // getaddrinfo + // socket + // setsockopt + // bind + // listen + server_res = AllocSocketResult(); + if (!SocketCreate(&server_cfg, server_res)) { + TraceLog(LOG_WARNING, "Failed to open server: status %d, errno %d", + server_res->status, server_res->socket->status); + } else { + if (!SocketBind(&server_cfg, server_res)) { + TraceLog(LOG_WARNING, "Failed to bind server: status %d, errno %d", + server_res->status, server_res->socket->status); + } else { + if (!(server_cfg.type == SOCKET_UDP)) { + if (!SocketListen(&server_cfg, server_res)) { + TraceLog(LOG_WARNING, + "Failed to start listen server: status %d, errno %d", + server_res->status, server_res->socket->status); + } + } + } + } - // Create the client - // - // Performs - // getaddrinfo - // socket - // setsockopt - // connect (TCP only) - client_res = AllocSocketResult(); - if (!SocketCreate(&client_cfg, client_res)) { - TraceLog(LOG_WARNING, "Failed to open client: status %d, errno %d", - client_res->status, client_res->socket->status); - } else { - if (!(client_cfg.type == SOCKET_UDP)) { - if (!SocketConnect(&client_cfg, client_res)) { - TraceLog(LOG_WARNING, - "Failed to connect to server: status %d, errno %d", - client_res->status, client_res->socket->status); - } - } - } + // Create the client + // + // Performs + // getaddrinfo + // socket + // setsockopt + // connect (TCP only) + client_res = AllocSocketResult(); + if (!SocketCreate(&client_cfg, client_res)) { + TraceLog(LOG_WARNING, "Failed to open client: status %d, errno %d", + client_res->status, client_res->socket->status); + } else { + if (!(client_cfg.type == SOCKET_UDP)) { + if (!SocketConnect(&client_cfg, client_res)) { + TraceLog(LOG_WARNING, + "Failed to connect to server: status %d, errno %d", + client_res->status, client_res->socket->status); + } + } + } - // Create & Add sockets to the socket set - socket_set = AllocSocketSet(3); - msglen = strlen(pingmsg) + 1; - memset(recvBuffer, '\0', sizeof(recvBuffer)); - AddSocket(socket_set, server_res->socket); - AddSocket(socket_set, client_res->socket); + // Create & Add sockets to the socket set + socket_set = AllocSocketSet(3); + msglen = strlen(pingmsg) + 1; + memset(recvBuffer, '\0', sizeof(recvBuffer)); + AddSocket(socket_set, server_res->socket); + AddSocket(socket_set, client_res->socket); - // Main game loop - while (!WindowShouldClose()) { - BeginDrawing(); - ClearBackground(RAYWHITE); - if (connected) { - NetworkUpdate(); - } else { - NetworkConnect(); - } - EndDrawing(); - } + // Main game loop + while (!WindowShouldClose()) { + BeginDrawing(); + ClearBackground(RAYWHITE); + if (connected) { + NetworkUpdate(); + } else { + NetworkConnect(); + } + EndDrawing(); + } - // Cleanup - CloseWindow(); - return 0; + // Cleanup + CloseWindow(); + return 0; } \ No newline at end of file diff --git a/examples/network/network_resolve_host.c b/examples/network/network_resolve_host.c index 195e03b52..45d6e4e9a 100644 --- a/examples/network/network_resolve_host.c +++ b/examples/network/network_resolve_host.c @@ -28,30 +28,30 @@ uint16_t port = 0; int main() { - // Setup - int screenWidth = 800; - int screenHeight = 450; - InitWindow( - screenWidth, screenHeight, "raylib [network] example - ping pong"); - SetTargetFPS(60); + // Setup + int screenWidth = 800; + int screenHeight = 450; + InitWindow( + screenWidth, screenHeight, "raylib [network] example - ping pong"); + SetTargetFPS(60); - SetTraceLogLevel(LOG_DEBUG); + SetTraceLogLevel(LOG_DEBUG); - // Networking - InitNetwork(); - + // Networking + InitNetwork(); + AddressInformation* addr = AllocAddressList(1); - int count = ResolveHost( - NULL, - "5210", - ADDRESS_TYPE_IPV4, + int count = ResolveHost( + NULL, + "5210", + ADDRESS_TYPE_IPV4, 0 // Uncomment any of these flags // ADDRESS_INFO_NUMERICHOST // or try them in conjunction to // ADDRESS_INFO_NUMERICSERV // specify custom behaviour from // ADDRESS_INFO_DNS_ONLY // the function getaddrinfo() // ADDRESS_INFO_ALL // // ADDRESS_INFO_FQDN // e.g. ADDRESS_INFO_CANONNAME | ADDRESS_INFO_NUMERICSERV - , + , addr ); @@ -61,20 +61,20 @@ int main() TraceLog(LOG_INFO, "Resolved to ip %s::%d\n", buffer, port); } - // Main game loop - while (!WindowShouldClose()) - { - // Draw - BeginDrawing(); + // Main game loop + while (!WindowShouldClose()) + { + // Draw + BeginDrawing(); - // Clear - ClearBackground(RAYWHITE); + // Clear + ClearBackground(RAYWHITE); - // End draw - EndDrawing(); - } + // End draw + EndDrawing(); + } - // Cleanup - CloseWindow(); - return 0; + // Cleanup + CloseWindow(); + return 0; } \ No newline at end of file diff --git a/examples/network/network_tcp_client.c b/examples/network/network_tcp_client.c index 6eed205ae..3f69dcd28 100644 --- a/examples/network/network_tcp_client.c +++ b/examples/network/network_tcp_client.c @@ -43,109 +43,109 @@ char recvBuffer[512]; // Attempt to connect to the network (Either TCP, or UDP) void NetworkConnect() { - // Check if we're connected every _delay_ seconds - elapsed += GetFrameTime(); - if (elapsed > delay) { - if (IsSocketConnected(client_res->socket)) { connected = true; } - elapsed = 0.0f; - } + // Check if we're connected every _delay_ seconds + elapsed += GetFrameTime(); + if (elapsed > delay) { + if (IsSocketConnected(client_res->socket)) { connected = true; } + elapsed = 0.0f; + } } // Once connected to the network, check the sockets for pending information // and when information is ready, send either a Ping or a Pong. void NetworkUpdate() { - // CheckSockets - // - // If any of the sockets in the socket_set are pending (received data, or requests) - // then mark the socket as being ready. You can check this with IsSocketReady(client_res->socket) - int active = CheckSockets(socket_set, 0); - if (active != 0) { - TraceLog(LOG_DEBUG, - "There are currently %d socket(s) with data to be processed.", active); - } + // CheckSockets + // + // If any of the sockets in the socket_set are pending (received data, or requests) + // then mark the socket as being ready. You can check this with IsSocketReady(client_res->socket) + int active = CheckSockets(socket_set, 0); + if (active != 0) { + TraceLog(LOG_DEBUG, + "There are currently %d socket(s) with data to be processed.", active); + } - // IsSocketReady - // - // If the socket is ready, attempt to receive data from the socket - int bytesRecv = 0; - if (IsSocketReady(client_res->socket)) { - bytesRecv = SocketReceive(client_res->socket, recvBuffer, msglen); - } + // IsSocketReady + // + // If the socket is ready, attempt to receive data from the socket + int bytesRecv = 0; + if (IsSocketReady(client_res->socket)) { + bytesRecv = SocketReceive(client_res->socket, recvBuffer, msglen); + } - // If we received data, was that data a "Ping!" or a "Pong!" - if (bytesRecv > 0) { - if (strcmp(recvBuffer, pingmsg) == 0) { pong = true; } - if (strcmp(recvBuffer, pongmsg) == 0) { ping = true; } - } + // If we received data, was that data a "Ping!" or a "Pong!" + if (bytesRecv > 0) { + if (strcmp(recvBuffer, pingmsg) == 0) { pong = true; } + if (strcmp(recvBuffer, pongmsg) == 0) { ping = true; } + } - // After each delay has expired, send a response "Ping!" for a "Pong!" and vice versa - elapsed += GetFrameTime(); - if (elapsed > delay) { - if (ping) { - ping = false; - SocketSend(client_res->socket, pingmsg, msglen); - } else if (pong) { - pong = false; - SocketSend(client_res->socket, pongmsg, msglen); - } - elapsed = 0.0f; - } + // After each delay has expired, send a response "Ping!" for a "Pong!" and vice versa + elapsed += GetFrameTime(); + if (elapsed > delay) { + if (ping) { + ping = false; + SocketSend(client_res->socket, pingmsg, msglen); + } else if (pong) { + pong = false; + SocketSend(client_res->socket, pongmsg, msglen); + } + elapsed = 0.0f; + } } int main() { - // Setup - int screenWidth = 800; - int screenHeight = 450; - InitWindow( - screenWidth, screenHeight, "raylib [network] example - tcp client"); - SetTargetFPS(60); - SetTraceLogLevel(LOG_DEBUG); + // Setup + int screenWidth = 800; + int screenHeight = 450; + InitWindow( + screenWidth, screenHeight, "raylib [network] example - tcp client"); + SetTargetFPS(60); + SetTraceLogLevel(LOG_DEBUG); - // Networking - InitNetwork(); + // Networking + InitNetwork(); - // Create the client - // - // Performs - // getaddrinfo - // socket - // setsockopt - // connect (TCP only) - client_res = AllocSocketResult(); - if (!SocketCreate(&client_cfg, client_res)) { - TraceLog(LOG_WARNING, "Failed to open client: status %d, errno %d", - client_res->status, client_res->socket->status); - } else { - if (!(client_cfg.type == SOCKET_UDP)) { - if (!SocketConnect(&client_cfg, client_res)) { - TraceLog(LOG_WARNING, - "Failed to connect to server: status %d, errno %d", - client_res->status, client_res->socket->status); - } - } - } + // Create the client + // + // Performs + // getaddrinfo + // socket + // setsockopt + // connect (TCP only) + client_res = AllocSocketResult(); + if (!SocketCreate(&client_cfg, client_res)) { + TraceLog(LOG_WARNING, "Failed to open client: status %d, errno %d", + client_res->status, client_res->socket->status); + } else { + if (!(client_cfg.type == SOCKET_UDP)) { + if (!SocketConnect(&client_cfg, client_res)) { + TraceLog(LOG_WARNING, + "Failed to connect to server: status %d, errno %d", + client_res->status, client_res->socket->status); + } + } + } - // Create & Add sockets to the socket set - socket_set = AllocSocketSet(1); - msglen = strlen(pingmsg) + 1; - memset(recvBuffer, '\0', sizeof(recvBuffer)); - AddSocket(socket_set, client_res->socket); + // Create & Add sockets to the socket set + socket_set = AllocSocketSet(1); + msglen = strlen(pingmsg) + 1; + memset(recvBuffer, '\0', sizeof(recvBuffer)); + AddSocket(socket_set, client_res->socket); - // Main game loop - while (!WindowShouldClose()) { - BeginDrawing(); - ClearBackground(RAYWHITE); - if (connected) { - NetworkUpdate(); - } else { - NetworkConnect(); - } - EndDrawing(); - } + // Main game loop + while (!WindowShouldClose()) { + BeginDrawing(); + ClearBackground(RAYWHITE); + if (connected) { + NetworkUpdate(); + } else { + NetworkConnect(); + } + EndDrawing(); + } - // Cleanup - CloseWindow(); - return 0; + // Cleanup + CloseWindow(); + return 0; } \ No newline at end of file diff --git a/examples/network/network_tcp_server.c b/examples/network/network_tcp_server.c index 89e9c1810..e93687260 100644 --- a/examples/network/network_tcp_server.c +++ b/examples/network/network_tcp_server.c @@ -45,121 +45,121 @@ char recvBuffer[512]; // Attempt to connect to the network (Either TCP, or UDP) void NetworkConnect() { - int active = CheckSockets(socket_set, 0); - if (active != 0) { - TraceLog(LOG_DEBUG, - "There are currently %d socket(s) with data to be processed.", active); - } - if (active > 0) { - if ((connection = SocketAccept(server_res->socket, &connection_cfg)) != NULL) { - AddSocket(socket_set, connection); - ping = true; - connected = true; - } - } + int active = CheckSockets(socket_set, 0); + if (active != 0) { + TraceLog(LOG_DEBUG, + "There are currently %d socket(s) with data to be processed.", active); + } + if (active > 0) { + if ((connection = SocketAccept(server_res->socket, &connection_cfg)) != NULL) { + AddSocket(socket_set, connection); + ping = true; + connected = true; + } + } } // Once connected to the network, check the sockets for pending information // and when information is ready, send either a Ping or a Pong. void NetworkUpdate() { - // CheckSockets - // - // If any of the sockets in the socket_set are pending (received data, or requests) - // then mark the socket as being ready. You can check this with IsSocketReady(client_res->socket) - int active = CheckSockets(socket_set, 0); - if (active != 0) { - TraceLog(LOG_DEBUG, - "There are currently %d socket(s) with data to be processed.", active); - } + // CheckSockets + // + // If any of the sockets in the socket_set are pending (received data, or requests) + // then mark the socket as being ready. You can check this with IsSocketReady(client_res->socket) + int active = CheckSockets(socket_set, 0); + if (active != 0) { + TraceLog(LOG_DEBUG, + "There are currently %d socket(s) with data to be processed.", active); + } - // IsSocketReady - // - // If the socket is ready, attempt to receive data from the socket - int bytesRecv = 0; - if (IsSocketReady(connection)) { - bytesRecv = SocketReceive(connection, recvBuffer, msglen); - } + // IsSocketReady + // + // If the socket is ready, attempt to receive data from the socket + int bytesRecv = 0; + if (IsSocketReady(connection)) { + bytesRecv = SocketReceive(connection, recvBuffer, msglen); + } - // If we received data, was that data a "Ping!" or a "Pong!" - if (bytesRecv > 0) { - if (strcmp(recvBuffer, pingmsg) == 0) { pong = true; } - if (strcmp(recvBuffer, pongmsg) == 0) { ping = true; } - } + // If we received data, was that data a "Ping!" or a "Pong!" + if (bytesRecv > 0) { + if (strcmp(recvBuffer, pingmsg) == 0) { pong = true; } + if (strcmp(recvBuffer, pongmsg) == 0) { ping = true; } + } - // After each delay has expired, send a response "Ping!" for a "Pong!" and vice versa - elapsed += GetFrameTime(); - if (elapsed > delay) { - if (ping) { - ping = false; - SocketSend(connection, pingmsg, msglen); - } else if (pong) { - pong = false; - SocketSend(connection, pongmsg, msglen); - } - elapsed = 0.0f; - } + // After each delay has expired, send a response "Ping!" for a "Pong!" and vice versa + elapsed += GetFrameTime(); + if (elapsed > delay) { + if (ping) { + ping = false; + SocketSend(connection, pingmsg, msglen); + } else if (pong) { + pong = false; + SocketSend(connection, pongmsg, msglen); + } + elapsed = 0.0f; + } } int main() { - // Setup - int screenWidth = 800; - int screenHeight = 450; - InitWindow( - screenWidth, screenHeight, "raylib [network] example - tcp server"); - SetTargetFPS(60); - SetTraceLogLevel(LOG_DEBUG); + // Setup + int screenWidth = 800; + int screenHeight = 450; + InitWindow( + screenWidth, screenHeight, "raylib [network] example - tcp server"); + SetTargetFPS(60); + SetTraceLogLevel(LOG_DEBUG); - // Networking - InitNetwork(); + // Networking + InitNetwork(); - // Create the server - // - // Performs - // getaddrinfo - // socket - // setsockopt - // bind - // listen - server_res = AllocSocketResult(); - if (!SocketCreate(&server_cfg, server_res)) { - TraceLog(LOG_WARNING, "Failed to open server: status %d, errno %d", - server_res->status, server_res->socket->status); - } else { - if (!SocketBind(&server_cfg, server_res)) { - TraceLog(LOG_WARNING, "Failed to bind server: status %d, errno %d", - server_res->status, server_res->socket->status); - } else { - if (!(server_cfg.type == SOCKET_UDP)) { - if (!SocketListen(&server_cfg, server_res)) { - TraceLog(LOG_WARNING, - "Failed to start listen server: status %d, errno %d", - server_res->status, server_res->socket->status); - } - } - } - } + // Create the server + // + // Performs + // getaddrinfo + // socket + // setsockopt + // bind + // listen + server_res = AllocSocketResult(); + if (!SocketCreate(&server_cfg, server_res)) { + TraceLog(LOG_WARNING, "Failed to open server: status %d, errno %d", + server_res->status, server_res->socket->status); + } else { + if (!SocketBind(&server_cfg, server_res)) { + TraceLog(LOG_WARNING, "Failed to bind server: status %d, errno %d", + server_res->status, server_res->socket->status); + } else { + if (!(server_cfg.type == SOCKET_UDP)) { + if (!SocketListen(&server_cfg, server_res)) { + TraceLog(LOG_WARNING, + "Failed to start listen server: status %d, errno %d", + server_res->status, server_res->socket->status); + } + } + } + } - // Create & Add sockets to the socket set - socket_set = AllocSocketSet(2); - msglen = strlen(pingmsg) + 1; - memset(recvBuffer, '\0', sizeof(recvBuffer)); - AddSocket(socket_set, server_res->socket); + // Create & Add sockets to the socket set + socket_set = AllocSocketSet(2); + msglen = strlen(pingmsg) + 1; + memset(recvBuffer, '\0', sizeof(recvBuffer)); + AddSocket(socket_set, server_res->socket); - // Main game loop - while (!WindowShouldClose()) { - BeginDrawing(); - ClearBackground(RAYWHITE); - if (connected) { - NetworkUpdate(); - } else { - NetworkConnect(); - } - EndDrawing(); - } + // Main game loop + while (!WindowShouldClose()) { + BeginDrawing(); + ClearBackground(RAYWHITE); + if (connected) { + NetworkUpdate(); + } else { + NetworkConnect(); + } + EndDrawing(); + } - // Cleanup - CloseWindow(); - return 0; + // Cleanup + CloseWindow(); + return 0; } \ No newline at end of file diff --git a/examples/network/network_test.c b/examples/network/network_test.c index f18a8b13c..56d9095ed 100644 --- a/examples/network/network_test.c +++ b/examples/network/network_test.c @@ -27,80 +27,80 @@ void test_network_initialise() { - assert(InitNetwork() == true); + assert(InitNetwork() == true); } void test_socket_result() { - SocketResult *result = AllocSocketResult(); - assert(result != NULL); - FreeSocketResult(&result); - assert(result == NULL); + SocketResult *result = AllocSocketResult(); + assert(result != NULL); + FreeSocketResult(&result); + assert(result == NULL); } void test_socket() { - Socket *socket = AllocSocket(); - assert(socket != NULL); - FreeSocket(&socket); - assert(socket == NULL); + Socket *socket = AllocSocket(); + assert(socket != NULL); + FreeSocket(&socket); + assert(socket == NULL); } void test_resolve_ip() { - const char *host = "8.8.8.8"; - const char *port = "8080"; - char ip[ADDRESS_IPV6_ADDRSTRLEN]; + const char *host = "8.8.8.8"; + const char *port = "8080"; + char ip[ADDRESS_IPV6_ADDRSTRLEN]; char service[ADDRESS_MAXSERV]; - memset(ip, '\0', ADDRESS_IPV6_ADDRSTRLEN); - ResolveIP(host, port, NAME_INFO_NUMERICHOST, ip, service); - TraceLog(LOG_INFO, "Resolved %s to %s", host, ip); - assert(strcmp(ip, "8.8.8.8") == 0); + memset(ip, '\0', ADDRESS_IPV6_ADDRSTRLEN); + ResolveIP(host, port, NAME_INFO_NUMERICHOST, ip, service); + TraceLog(LOG_INFO, "Resolved %s to %s", host, ip); + assert(strcmp(ip, "8.8.8.8") == 0); - memset(ip, '\0', ADDRESS_IPV6_ADDRSTRLEN); - ResolveIP(host, port, NAME_INFO_DEFAULT, ip, service); - TraceLog(LOG_INFO, "Resolved %s to %s", host, ip); - assert(strcmp(ip, "google-public-dns-a.google.com") == 0); + memset(ip, '\0', ADDRESS_IPV6_ADDRSTRLEN); + ResolveIP(host, port, NAME_INFO_DEFAULT, ip, service); + TraceLog(LOG_INFO, "Resolved %s to %s", host, ip); + assert(strcmp(ip, "google-public-dns-a.google.com") == 0); - memset(ip, '\0', ADDRESS_IPV6_ADDRSTRLEN); - ResolveIP(host, port, NAME_INFO_NOFQDN, ip, service); - TraceLog(LOG_INFO, "Resolved %s to %s", host, ip); - assert(strcmp(ip, "google-public-dns-a") == 0); + memset(ip, '\0', ADDRESS_IPV6_ADDRSTRLEN); + ResolveIP(host, port, NAME_INFO_NOFQDN, ip, service); + TraceLog(LOG_INFO, "Resolved %s to %s", host, ip); + assert(strcmp(ip, "google-public-dns-a") == 0); - memset(ip, '\0', ADDRESS_IPV6_ADDRSTRLEN); - ResolveIP(host, port, NAME_INFO_NUMERICHOST, ip, service); - TraceLog(LOG_INFO, "Resolved %s to %s", host, ip); - assert(strcmp(ip, "8.8.8.8") == 0); + memset(ip, '\0', ADDRESS_IPV6_ADDRSTRLEN); + ResolveIP(host, port, NAME_INFO_NUMERICHOST, ip, service); + TraceLog(LOG_INFO, "Resolved %s to %s", host, ip); + assert(strcmp(ip, "8.8.8.8") == 0); - memset(ip, '\0', ADDRESS_IPV6_ADDRSTRLEN); - ResolveIP(host, port, NAME_INFO_NAMEREQD, ip, service); - TraceLog(LOG_INFO, "Resolved %s to %s", host, ip); - assert(strcmp(ip, "google-public-dns-a.google.com") == 0); + memset(ip, '\0', ADDRESS_IPV6_ADDRSTRLEN); + ResolveIP(host, port, NAME_INFO_NAMEREQD, ip, service); + TraceLog(LOG_INFO, "Resolved %s to %s", host, ip); + assert(strcmp(ip, "google-public-dns-a.google.com") == 0); - memset(ip, '\0', ADDRESS_IPV6_ADDRSTRLEN); - ResolveIP(host, port, NAME_INFO_NUMERICSERV, ip, service); - TraceLog(LOG_INFO, "Resolved %s to %s", host, ip); - assert(strcmp(ip, "google-public-dns-a.google.com") == 0); + memset(ip, '\0', ADDRESS_IPV6_ADDRSTRLEN); + ResolveIP(host, port, NAME_INFO_NUMERICSERV, ip, service); + TraceLog(LOG_INFO, "Resolved %s to %s", host, ip); + assert(strcmp(ip, "google-public-dns-a.google.com") == 0); - memset(ip, '\0', ADDRESS_IPV6_ADDRSTRLEN); - ResolveIP(host, port, NAME_INFO_DGRAM, ip, service); - TraceLog(LOG_INFO, "Resolved %s to %s", host, ip); - assert(strcmp(ip, "google-public-dns-a.google.com") == 0); + memset(ip, '\0', ADDRESS_IPV6_ADDRSTRLEN); + ResolveIP(host, port, NAME_INFO_DGRAM, ip, service); + TraceLog(LOG_INFO, "Resolved %s to %s", host, ip); + assert(strcmp(ip, "google-public-dns-a.google.com") == 0); } void test_resolve_host() { - const char * address = "localhost"; - const char * port = "80"; - AddressInformation *addr = AllocAddressList(3); - int count = ResolveHost(address, port, ADDRESS_TYPE_ANY, 0, addr); + const char * address = "localhost"; + const char * port = "80"; + AddressInformation *addr = AllocAddressList(3); + int count = ResolveHost(address, port, ADDRESS_TYPE_ANY, 0, addr); - assert(GetAddressFamily(addr[0]) == ADDRESS_TYPE_IPV6); - assert(GetAddressFamily(addr[1]) == ADDRESS_TYPE_IPV4); - assert(GetAddressSocketType(addr[0]) == 0); - assert(GetAddressProtocol(addr[0]) == 0); - // for (size_t i = 0; i < count; i++) { PrintAddressInfo(addr[i]); } + assert(GetAddressFamily(addr[0]) == ADDRESS_TYPE_IPV6); + assert(GetAddressFamily(addr[1]) == ADDRESS_TYPE_IPV4); + assert(GetAddressSocketType(addr[0]) == 0); + assert(GetAddressProtocol(addr[0]) == 0); + // for (size_t i = 0; i < count; i++) { PrintAddressInfo(addr[i]); } } void test_address() @@ -113,36 +113,36 @@ void test_address_list() void test_socket_create() { - SocketConfig server_cfg = {.host = "127.0.0.1", .port = "8080", .server = true, .nonblocking = true}; - Socket * socket = AllocSocket(); - SocketResult *server_res = AllocSocketResult(); - SocketSet * socket_set = AllocSocketSet(1); - assert(SocketCreate(&server_cfg, server_res)); - assert(AddSocket(socket_set, server_res->socket)); - assert(SocketListen(&server_cfg, server_res)); + SocketConfig server_cfg = {.host = "127.0.0.1", .port = "8080", .server = true, .nonblocking = true}; + Socket * socket = AllocSocket(); + SocketResult *server_res = AllocSocketResult(); + SocketSet * socket_set = AllocSocketSet(1); + assert(SocketCreate(&server_cfg, server_res)); + assert(AddSocket(socket_set, server_res->socket)); + assert(SocketListen(&server_cfg, server_res)); } int main() { - int screenWidth = 800; - int screenHeight = 450; - InitWindow( - screenWidth, screenHeight, "raylib [network] example - network test"); - SetTargetFPS(60); + int screenWidth = 800; + int screenHeight = 450; + InitWindow( + screenWidth, screenHeight, "raylib [network] example - network test"); + SetTargetFPS(60); - // Run the tests - test_network_initialise(); - test_resolve_host(); + // Run the tests + test_network_initialise(); + test_resolve_host(); // test_socket_create(); - // Main game loop - while (!WindowShouldClose()) { - BeginDrawing(); - ClearBackground(RAYWHITE); - DrawText("Congrats! You created your first window!", 190, 200, 20, LIGHTGRAY); - EndDrawing(); - } - CloseWindow(); + // Main game loop + while (!WindowShouldClose()) { + BeginDrawing(); + ClearBackground(RAYWHITE); + DrawText("Congrats! You created your first window!", 190, 200, 20, LIGHTGRAY); + EndDrawing(); + } + CloseWindow(); - return 0; + return 0; } \ No newline at end of file diff --git a/examples/network/network_udp_client.c b/examples/network/network_udp_client.c index c1c89c8db..fbc0589fb 100644 --- a/examples/network/network_udp_client.c +++ b/examples/network/network_udp_client.c @@ -43,86 +43,86 @@ char recvBuffer[512]; // and when information is ready, send either a Ping or a Pong. void NetworkUpdate() { - // CheckSockets - // - // If any of the sockets in the socket_set are pending (received data, or requests) - // then mark the socket as being ready. You can check this with IsSocketReady(client_res->socket) - int active = CheckSockets(socket_set, 0); - if (active != 0) { - TraceLog(LOG_DEBUG, - "There are currently %d socket(s) with data to be processed.", active); - } + // CheckSockets + // + // If any of the sockets in the socket_set are pending (received data, or requests) + // then mark the socket as being ready. You can check this with IsSocketReady(client_res->socket) + int active = CheckSockets(socket_set, 0); + if (active != 0) { + TraceLog(LOG_DEBUG, + "There are currently %d socket(s) with data to be processed.", active); + } - // IsSocketReady - // - // If the socket is ready, attempt to receive data from the socket - int bytesRecv = 0; - if (IsSocketReady(client_res->socket)) { - bytesRecv = SocketReceive(client_res->socket, recvBuffer, msglen); - } + // IsSocketReady + // + // If the socket is ready, attempt to receive data from the socket + int bytesRecv = 0; + if (IsSocketReady(client_res->socket)) { + bytesRecv = SocketReceive(client_res->socket, recvBuffer, msglen); + } - // If we received data, was that data a "Ping!" or a "Pong!" - if (bytesRecv > 0) { - if (strcmp(recvBuffer, pingmsg) == 0) { pong = true; } - if (strcmp(recvBuffer, pongmsg) == 0) { ping = true; } - } + // If we received data, was that data a "Ping!" or a "Pong!" + if (bytesRecv > 0) { + if (strcmp(recvBuffer, pingmsg) == 0) { pong = true; } + if (strcmp(recvBuffer, pongmsg) == 0) { ping = true; } + } - // After each delay has expired, send a response "Ping!" for a "Pong!" and vice versa - elapsed += GetFrameTime(); - if (elapsed > delay) { - if (ping) { - ping = false; - SocketSend(client_res->socket, pingmsg, msglen); - } else if (pong) { - pong = false; - SocketSend(client_res->socket, pongmsg, msglen); - } - elapsed = 0.0f; - } + // After each delay has expired, send a response "Ping!" for a "Pong!" and vice versa + elapsed += GetFrameTime(); + if (elapsed > delay) { + if (ping) { + ping = false; + SocketSend(client_res->socket, pingmsg, msglen); + } else if (pong) { + pong = false; + SocketSend(client_res->socket, pongmsg, msglen); + } + elapsed = 0.0f; + } } int main() { - // Setup - int screenWidth = 800; - int screenHeight = 450; - InitWindow( - screenWidth, screenHeight, "raylib [network] example - udp client"); - SetTargetFPS(60); - SetTraceLogLevel(LOG_DEBUG); + // Setup + int screenWidth = 800; + int screenHeight = 450; + InitWindow( + screenWidth, screenHeight, "raylib [network] example - udp client"); + SetTargetFPS(60); + SetTraceLogLevel(LOG_DEBUG); - // Networking - InitNetwork(); + // Networking + InitNetwork(); - // Create the client - // - // Performs - // getaddrinfo - // socket - // setsockopt - // connect (TCP only) - client_res = AllocSocketResult(); - if (!SocketCreate(&client_cfg, client_res)) { - TraceLog(LOG_WARNING, "Failed to open client: status %d, errno %d", - client_res->status, client_res->socket->status); - } + // Create the client + // + // Performs + // getaddrinfo + // socket + // setsockopt + // connect (TCP only) + client_res = AllocSocketResult(); + if (!SocketCreate(&client_cfg, client_res)) { + TraceLog(LOG_WARNING, "Failed to open client: status %d, errno %d", + client_res->status, client_res->socket->status); + } - // Create & Add sockets to the socket set - socket_set = AllocSocketSet(1); - msglen = strlen(pingmsg) + 1; - ping = true; - memset(recvBuffer, '\0', sizeof(recvBuffer)); - AddSocket(socket_set, client_res->socket); + // Create & Add sockets to the socket set + socket_set = AllocSocketSet(1); + msglen = strlen(pingmsg) + 1; + ping = true; + memset(recvBuffer, '\0', sizeof(recvBuffer)); + AddSocket(socket_set, client_res->socket); - // Main game loop - while (!WindowShouldClose()) { - BeginDrawing(); - ClearBackground(RAYWHITE); - NetworkUpdate(); - EndDrawing(); - } + // Main game loop + while (!WindowShouldClose()) { + BeginDrawing(); + ClearBackground(RAYWHITE); + NetworkUpdate(); + EndDrawing(); + } - // Cleanup - CloseWindow(); - return 0; + // Cleanup + CloseWindow(); + return 0; } \ No newline at end of file diff --git a/examples/network/network_udp_server.c b/examples/network/network_udp_server.c index 982cdf633..5ab45bb5c 100644 --- a/examples/network/network_udp_server.c +++ b/examples/network/network_udp_server.c @@ -43,92 +43,92 @@ char recvBuffer[512]; // and when information is ready, send either a Ping or a Pong. void NetworkUpdate() { - // CheckSockets - // - // If any of the sockets in the socket_set are pending (received data, or requests) - // then mark the socket as being ready. You can check this with IsSocketReady(client_res->socket) - int active = CheckSockets(socket_set, 0); - if (active != 0) { - TraceLog(LOG_DEBUG, - "There are currently %d socket(s) with data to be processed.", active); - } + // CheckSockets + // + // If any of the sockets in the socket_set are pending (received data, or requests) + // then mark the socket as being ready. You can check this with IsSocketReady(client_res->socket) + int active = CheckSockets(socket_set, 0); + if (active != 0) { + TraceLog(LOG_DEBUG, + "There are currently %d socket(s) with data to be processed.", active); + } - // IsSocketReady - // - // If the socket is ready, attempt to receive data from the socket - // int bytesRecv = 0; - // if (IsSocketReady(server_res->socket)) { - // bytesRecv = SocketReceive(server_res->socket, recvBuffer, msglen); - // } - int bytesRecv = SocketReceive(server_res->socket, recvBuffer, msglen); + // IsSocketReady + // + // If the socket is ready, attempt to receive data from the socket + // int bytesRecv = 0; + // if (IsSocketReady(server_res->socket)) { + // bytesRecv = SocketReceive(server_res->socket, recvBuffer, msglen); + // } + int bytesRecv = SocketReceive(server_res->socket, recvBuffer, msglen); - // If we received data, was that data a "Ping!" or a "Pong!" - if (bytesRecv > 0) { - if (strcmp(recvBuffer, pingmsg) == 0) { pong = true; } - if (strcmp(recvBuffer, pongmsg) == 0) { ping = true; } - } + // If we received data, was that data a "Ping!" or a "Pong!" + if (bytesRecv > 0) { + if (strcmp(recvBuffer, pingmsg) == 0) { pong = true; } + if (strcmp(recvBuffer, pongmsg) == 0) { ping = true; } + } - // After each delay has expired, send a response "Ping!" for a "Pong!" and vice versa - elapsed += GetFrameTime(); - if (elapsed > delay) { - if (ping) { - ping = false; - SocketSend(server_res->socket, pingmsg, msglen); - } else if (pong) { - pong = false; - SocketSend(server_res->socket, pongmsg, msglen); - } - elapsed = 0.0f; - } + // After each delay has expired, send a response "Ping!" for a "Pong!" and vice versa + elapsed += GetFrameTime(); + if (elapsed > delay) { + if (ping) { + ping = false; + SocketSend(server_res->socket, pingmsg, msglen); + } else if (pong) { + pong = false; + SocketSend(server_res->socket, pongmsg, msglen); + } + elapsed = 0.0f; + } } int main() { - // Setup - int screenWidth = 800; - int screenHeight = 450; - InitWindow( - screenWidth, screenHeight, "raylib [network] example - udp server"); - SetTargetFPS(60); - SetTraceLogLevel(LOG_DEBUG); + // Setup + int screenWidth = 800; + int screenHeight = 450; + InitWindow( + screenWidth, screenHeight, "raylib [network] example - udp server"); + SetTargetFPS(60); + SetTraceLogLevel(LOG_DEBUG); - // Networking - InitNetwork(); + // Networking + InitNetwork(); - // Create the server - // - // Performs - // getaddrinfo - // socket - // setsockopt - // bind - // listen - server_res = AllocSocketResult(); - if (!SocketCreate(&server_cfg, server_res)) { - TraceLog(LOG_WARNING, "Failed to open server: status %d, errno %d", - server_res->status, server_res->socket->status); - } else { - if (!SocketBind(&server_cfg, server_res)) { - TraceLog(LOG_WARNING, "Failed to bind server: status %d, errno %d", - server_res->status, server_res->socket->status); - } - } + // Create the server + // + // Performs + // getaddrinfo + // socket + // setsockopt + // bind + // listen + server_res = AllocSocketResult(); + if (!SocketCreate(&server_cfg, server_res)) { + TraceLog(LOG_WARNING, "Failed to open server: status %d, errno %d", + server_res->status, server_res->socket->status); + } else { + if (!SocketBind(&server_cfg, server_res)) { + TraceLog(LOG_WARNING, "Failed to bind server: status %d, errno %d", + server_res->status, server_res->socket->status); + } + } - // Create & Add sockets to the socket set - socket_set = AllocSocketSet(1); - msglen = strlen(pingmsg) + 1; - memset(recvBuffer, '\0', sizeof(recvBuffer)); - AddSocket(socket_set, server_res->socket); + // Create & Add sockets to the socket set + socket_set = AllocSocketSet(1); + msglen = strlen(pingmsg) + 1; + memset(recvBuffer, '\0', sizeof(recvBuffer)); + AddSocket(socket_set, server_res->socket); - // Main game loop - while (!WindowShouldClose()) { - BeginDrawing(); - ClearBackground(RAYWHITE); - NetworkUpdate(); - EndDrawing(); - } + // Main game loop + while (!WindowShouldClose()) { + BeginDrawing(); + ClearBackground(RAYWHITE); + NetworkUpdate(); + EndDrawing(); + } - // Cleanup - CloseWindow(); - return 0; + // Cleanup + CloseWindow(); + return 0; } \ No newline at end of file diff --git a/examples/others/easings.h b/examples/others/easings.h new file mode 100644 index 000000000..1b08af0a5 --- /dev/null +++ b/examples/others/easings.h @@ -0,0 +1,263 @@ +/******************************************************************************************* +* +* raylib easings (header only file) +* +* Useful easing functions for values animation +* +* This header uses: +* #define EASINGS_STATIC_INLINE // Inlines all functions code, so it runs faster. +* // This requires lots of memory on system. +* How to use: +* The four inputs t,b,c,d are defined as follows: +* t = current time (in any unit measure, but same unit as duration) +* b = starting value to interpolate +* c = the total change in value of b that needs to occur +* d = total time it should take to complete (duration) +* +* Example: +* +* int currentTime = 0; +* int duration = 100; +* float startPositionX = 0.0f; +* float finalPositionX = 30.0f; +* float currentPositionX = startPositionX; +* +* while (currentPositionX < finalPositionX) +* { +* currentPositionX = EaseSineIn(currentTime, startPositionX, finalPositionX - startPositionX, duration); +* currentTime++; +* } +* +* A port of Robert Penner's easing equations to C (http://robertpenner.com/easing/) +* +* Robert Penner License +* --------------------------------------------------------------------------------- +* Open source under the BSD License. +* +* Copyright (c) 2001 Robert Penner. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, +* are permitted provided that the following conditions are met: +* +* - Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* - Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* - Neither the name of the author nor the names of contributors may be used +* to endorse or promote products derived from this software without specific +* prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +* OF THE POSSIBILITY OF SUCH DAMAGE. +* --------------------------------------------------------------------------------- +* +* Copyright (c) 2015 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 EASINGS_H +#define EASINGS_H + +#define EASINGS_STATIC_INLINE // NOTE: By default, compile functions as static inline + +#if defined(EASINGS_STATIC_INLINE) + #define EASEDEF static inline +#else + #define EASEDEF extern +#endif + +#include // Required for: sinf(), cosf(), sqrt(), pow() + +#ifndef PI + #define PI 3.14159265358979323846f //Required as PI is not always defined in math.h +#endif + +#ifdef __cplusplus +extern "C" { // Prevents name mangling of functions +#endif + +// Linear Easing functions +EASEDEF float EaseLinearNone(float t, float b, float c, float d) { return (c*t/d + b); } +EASEDEF float EaseLinearIn(float t, float b, float c, float d) { return (c*t/d + b); } +EASEDEF float EaseLinearOut(float t, float b, float c, float d) { return (c*t/d + b); } +EASEDEF float EaseLinearInOut(float t,float b, float c, float d) { return (c*t/d + b); } + +// Sine Easing functions +EASEDEF float EaseSineIn(float t, float b, float c, float d) { return (-c*cosf(t/d*(PI/2.0f)) + c + b); } +EASEDEF float EaseSineOut(float t, float b, float c, float d) { return (c*sinf(t/d*(PI/2.0f)) + b); } +EASEDEF float EaseSineInOut(float t, float b, float c, float d) { return (-c/2.0f*(cosf(PI*t/d) - 1.0f) + b); } + +// Circular Easing functions +EASEDEF float EaseCircIn(float t, float b, float c, float d) { t /= d; return (-c*(sqrt(1.0f - t*t) - 1.0f) + b); } +EASEDEF float EaseCircOut(float t, float b, float c, float d) { t = t/d - 1.0f; return (c*sqrt(1.0f - t*t) + b); } +EASEDEF float EaseCircInOut(float t, float b, float c, float d) +{ + if ((t/=d/2.0f) < 1.0f) return (-c/2.0f*(sqrt(1.0f - t*t) - 1.0f) + b); + t -= 2.0f; return (c/2.0f*(sqrt(1.0f - t*t) + 1.0f) + b); +} + +// Cubic Easing functions +EASEDEF float EaseCubicIn(float t, float b, float c, float d) { t /= d; return (c*t*t*t + b); } +EASEDEF float EaseCubicOut(float t, float b, float c, float d) { t = t/d - 1.0f; return (c*(t*t*t + 1.0f) + b); } +EASEDEF float EaseCubicInOut(float t, float b, float c, float d) +{ + if ((t/=d/2.0f) < 1.0f) return (c/2.0f*t*t*t + b); + t -= 2.0f; return (c/2.0f*(t*t*t + 2.0f) + b); +} + +// Quadratic Easing functions +EASEDEF float EaseQuadIn(float t, float b, float c, float d) { t /= d; return (c*t*t + b); } +EASEDEF float EaseQuadOut(float t, float b, float c, float d) { t /= d; return (-c*t*(t - 2.0f) + b); } +EASEDEF float EaseQuadInOut(float t, float b, float c, float d) +{ + if ((t/=d/2) < 1) return (((c/2)*(t*t)) + b); + return (-c/2.0f*(((t - 1.0f)*(t - 3.0f)) - 1.0f) + b); +} + +// Exponential Easing functions +EASEDEF float EaseExpoIn(float t, float b, float c, float d) { return (t == 0.0f) ? b : (c*pow(2.0f, 10.0f*(t/d - 1.0f)) + b); } +EASEDEF float EaseExpoOut(float t, float b, float c, float d) { return (t == d) ? (b + c) : (c*(-pow(2.0f, -10.0f*t/d) + 1.0f) + b); } +EASEDEF float EaseExpoInOut(float t, float b, float c, float d) +{ + if (t == 0.0f) return b; + if (t == d) return (b + c); + if ((t/=d/2.0f) < 1.0f) return (c/2.0f*pow(2.0f, 10.0f*(t - 1.0f)) + b); + + return (c/2.0f*(-pow(2.0f, -10.0f*(t - 1.0f)) + 2.0f) + b); +} + +// Back Easing functions +EASEDEF float EaseBackIn(float t, float b, float c, float d) +{ + float s = 1.70158f; + float postFix = t/=d; + return (c*(postFix)*t*((s + 1.0f)*t - s) + b); +} + +EASEDEF float EaseBackOut(float t, float b, float c, float d) +{ + float s = 1.70158f; + t = t/d - 1.0f; + return (c*(t*t*((s + 1.0f)*t + s) + 1.0f) + b); +} + +EASEDEF float EaseBackInOut(float t, float b, float c, float d) +{ + float s = 1.70158f; + if ((t/=d/2.0f) < 1.0f) + { + s *= 1.525f; + return (c/2.0f*(t*t*((s + 1.0f)*t - s)) + b); + } + + float postFix = t-=2.0f; + s *= 1.525f; + return (c/2.0f*((postFix)*t*((s + 1.0f)*t + s) + 2.0f) + b); +} + +// Bounce Easing functions +EASEDEF float EaseBounceOut(float t, float b, float c, float d) +{ + if ((t/=d) < (1.0f/2.75f)) + { + return (c*(7.5625f*t*t) + b); + } + else if (t < (2.0f/2.75f)) + { + float postFix = t-=(1.5f/2.75f); + return (c*(7.5625f*(postFix)*t + 0.75f) + b); + } + else if (t < (2.5/2.75)) + { + float postFix = t-=(2.25f/2.75f); + return (c*(7.5625f*(postFix)*t + 0.9375f) + b); + } + else + { + float postFix = t-=(2.625f/2.75f); + return (c*(7.5625f*(postFix)*t + 0.984375f) + b); + } +} + +EASEDEF float EaseBounceIn(float t, float b, float c, float d) { return (c - EaseBounceOut(d - t, 0.0f, c, d) + b); } +EASEDEF float EaseBounceInOut(float t, float b, float c, float d) +{ + if (t < d/2.0f) return (EaseBounceIn(t*2.0f, 0.0f, c, d)*0.5f + b); + else return (EaseBounceOut(t*2.0f - d, 0.0f, c, d)*0.5f + c*0.5f + b); +} + +// Elastic Easing functions +EASEDEF float EaseElasticIn(float t, float b, float c, float d) +{ + if (t == 0.0f) return b; + if ((t/=d) == 1.0f) return (b + c); + + float p = d*0.3f; + float a = c; + float s = p/4.0f; + float postFix = a*pow(2.0f, 10.0f*(t-=1.0f)); + + return (-(postFix*sinf((t*d-s)*(2.0f*PI)/p )) + b); +} + +EASEDEF float EaseElasticOut(float t, float b, float c, float d) +{ + if (t == 0.0f) return b; + if ((t/=d) == 1.0f) return (b + c); + + float p = d*0.3f; + float a = c; + float s = p/4.0f; + + return (a*pow(2.0f,-10.0f*t)*sinf((t*d-s)*(2.0f*PI)/p) + c + b); +} + +EASEDEF float EaseElasticInOut(float t, float b, float c, float d) +{ + if (t == 0.0f) return b; + if ((t/=d/2.0f) == 2.0f) return (b + c); + + float p = d*(0.3f*1.5f); + float a = c; + float s = p/4.0f; + + if (t < 1.0f) + { + float postFix = a*pow(2.0f, 10.0f*(t-=1.0f)); + return -0.5f*(postFix*sinf((t*d-s)*(2.0f*PI)/p)) + b; + } + + float postFix = a*pow(2.0f, -10.0f*(t-=1.0f)); + + return (postFix*sinf((t*d-s)*(2.0f*PI)/p)*0.5f + c + b); +} + +#ifdef __cplusplus +} +#endif + +#endif // EASINGS_H diff --git a/examples/others/easings_testbed.c b/examples/others/easings_testbed.c new file mode 100644 index 000000000..9c94cfc3e --- /dev/null +++ b/examples/others/easings_testbed.c @@ -0,0 +1,227 @@ +/******************************************************************************************* +* +* raylib [easings] example - Easings Testbed +* +* This example has been created using raylib 2.5 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Example contributed by Juan Miguel López (@flashback-fx) and reviewed by Ramon Santamaria (@raysan5) +* +* Copyright (c) 2019 Juan Miguel López (@flashback-fx ) and Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include + +#include "easings.h" + +#define FONT_SIZE 20 + +#define D_STEP 20.0f +#define D_STEP_FINE 2.0f +#define D_MIN 1.0f +#define D_MAX 10000.0f + +// Easing types +enum EasingTypes { + EASE_LINEAR_NONE = 0, + EASE_LINEAR_IN, + EASE_LINEAR_OUT, + EASE_LINEAR_IN_OUT, + EASE_SINE_IN, + EASE_SINE_OUT, + EASE_SINE_IN_OUT, + EASE_CIRC_IN, + EASE_CIRC_OUT, + EASE_CIRC_IN_OUT, + EASE_CUBIC_IN, + EASE_CUBIC_OUT, + EASE_CUBIC_IN_OUT, + EASE_QUAD_IN, + EASE_QUAD_OUT, + EASE_QUAD_IN_OUT, + EASE_EXPO_IN, + EASE_EXPO_OUT, + EASE_EXPO_IN_OUT, + EASE_BACK_IN, + EASE_BACK_OUT, + EASE_BACK_IN_OUT, + EASE_BOUNCE_OUT, + EASE_BOUNCE_IN, + EASE_BOUNCE_IN_OUT, + EASE_ELASTIC_IN, + EASE_ELASTIC_OUT, + EASE_ELASTIC_IN_OUT, + NUM_EASING_TYPES, + EASING_NONE = NUM_EASING_TYPES +}; + + +static float NoEase(float t, float b, float c, float d); // NoEase function declaration, function used when "no easing" is selected for any axis + + +// Easing functions reference data +static const struct { + const char *name; + float (*func)(float, float, float, float); +} Easings[] = { + [EASE_LINEAR_NONE] = { .name = "EaseLinearNone", .func = EaseLinearNone }, + [EASE_LINEAR_IN] = { .name = "EaseLinearIn", .func = EaseLinearIn }, + [EASE_LINEAR_OUT] = { .name = "EaseLinearOut", .func = EaseLinearOut }, + [EASE_LINEAR_IN_OUT] = { .name = "EaseLinearInOut", .func = EaseLinearInOut }, + [EASE_SINE_IN] = { .name = "EaseSineIn", .func = EaseSineIn }, + [EASE_SINE_OUT] = { .name = "EaseSineOut", .func = EaseSineOut }, + [EASE_SINE_IN_OUT] = { .name = "EaseSineInOut", .func = EaseSineInOut }, + [EASE_CIRC_IN] = { .name = "EaseCircIn", .func = EaseCircIn }, + [EASE_CIRC_OUT] = { .name = "EaseCircOut", .func = EaseCircOut }, + [EASE_CIRC_IN_OUT] = { .name = "EaseCircInOut", .func = EaseCircInOut }, + [EASE_CUBIC_IN] = { .name = "EaseCubicIn", .func = EaseCubicIn }, + [EASE_CUBIC_OUT] = { .name = "EaseCubicOut", .func = EaseCubicOut }, + [EASE_CUBIC_IN_OUT] = { .name = "EaseCubicInOut", .func = EaseCubicInOut }, + [EASE_QUAD_IN] = { .name = "EaseQuadIn", .func = EaseQuadIn }, + [EASE_QUAD_OUT] = { .name = "EaseQuadOut", .func = EaseQuadOut }, + [EASE_QUAD_IN_OUT] = { .name = "EaseQuadInOut", .func = EaseQuadInOut }, + [EASE_EXPO_IN] = { .name = "EaseExpoIn", .func = EaseExpoIn }, + [EASE_EXPO_OUT] = { .name = "EaseExpoOut", .func = EaseExpoOut }, + [EASE_EXPO_IN_OUT] = { .name = "EaseExpoInOut", .func = EaseExpoInOut }, + [EASE_BACK_IN] = { .name = "EaseBackIn", .func = EaseBackIn }, + [EASE_BACK_OUT] = { .name = "EaseBackOut", .func = EaseBackOut }, + [EASE_BACK_IN_OUT] = { .name = "EaseBackInOut", .func = EaseBackInOut }, + [EASE_BOUNCE_OUT] = { .name = "EaseBounceOut", .func = EaseBounceOut }, + [EASE_BOUNCE_IN] = { .name = "EaseBounceIn", .func = EaseBounceIn }, + [EASE_BOUNCE_IN_OUT] = { .name = "EaseBounceInOut", .func = EaseBounceInOut }, + [EASE_ELASTIC_IN] = { .name = "EaseElasticIn", .func = EaseElasticIn }, + [EASE_ELASTIC_OUT] = { .name = "EaseElasticOut", .func = EaseElasticOut }, + [EASE_ELASTIC_IN_OUT] = { .name = "EaseElasticInOut", .func = EaseElasticInOut }, + [EASING_NONE] = { .name = "None", .func = NoEase }, +}; + + +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [easings] example - easings testbed"); + + Vector2 ballPosition = { 100.0f, 200.0f }; + + float t = 0.0f; // Current time (in any unit measure, but same unit as duration) + float d = 300.0f; // Total time it should take to complete (duration) + bool paused = true; + bool boundedT = true; // If true, t will stop when d >= td, otherwise t will keep adding td to its value every loop + + int easingX = EASING_NONE; // Easing selected for x axis + int easingY = EASING_NONE; // Easing selected for y axis + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + if (IsKeyPressed(KEY_T)) boundedT = !boundedT; + + // Choose easing for the X axis + if (IsKeyPressed(KEY_RIGHT)) + { + easingX++; + + if (easingX > EASING_NONE) easingX = 0; + } + else if (IsKeyPressed(KEY_LEFT)) + { + if (easingX == 0) easingX = EASING_NONE; + else easingX--; + } + + // Choose easing for the Y axis + if (IsKeyPressed(KEY_DOWN)) + { + easingY++; + + if (easingY > EASING_NONE) easingY = 0; + } + else if (IsKeyPressed(KEY_UP)) + { + if (easingY == 0) easingY = EASING_NONE; + else easingY--; + } + + // Change d (duration) value + if (IsKeyPressed(KEY_W) && d < D_MAX - D_STEP) d += D_STEP; + else if (IsKeyPressed(KEY_Q) && d > D_MIN + D_STEP) d -= D_STEP; + + if (IsKeyDown(KEY_S) && d < D_MAX - D_STEP_FINE) d += D_STEP_FINE; + else if (IsKeyDown(KEY_A) && d > D_MIN + D_STEP_FINE) d -= D_STEP_FINE; + + // Play, pause and restart controls + if (IsKeyPressed(KEY_SPACE) || IsKeyPressed(KEY_T) || + IsKeyPressed(KEY_RIGHT) || IsKeyPressed(KEY_LEFT) || + IsKeyPressed(KEY_DOWN) || IsKeyPressed(KEY_UP) || + IsKeyPressed(KEY_W) || IsKeyPressed(KEY_Q) || + IsKeyDown(KEY_S) || IsKeyDown(KEY_A) || + (IsKeyPressed(KEY_ENTER) && (boundedT == true) && (t >= d))) + { + t = 0.0f; + ballPosition.x = 100.0f; + ballPosition.y = 100.0f; + paused = true; + } + + if (IsKeyPressed(KEY_ENTER)) paused = !paused; + + // Movement computation + if (!paused && ((boundedT && t < d) || !boundedT)) + { + ballPosition.x = Easings[easingX].func(t, 100.0f, 700.0f - 100.0f, d); + ballPosition.y = Easings[easingY].func(t, 100.0f, 400.0f - 100.0f, d); + t += 1.0f; + } + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + // Draw information text + DrawText(TextFormat("Easing x: %s", Easings[easingX].name), 0, FONT_SIZE*2, FONT_SIZE, LIGHTGRAY); + DrawText(TextFormat("Easing y: %s", Easings[easingY].name), 0, FONT_SIZE*3, FONT_SIZE, LIGHTGRAY); + DrawText(TextFormat("t (%c) = %.2f d = %.2f", (boundedT == true)? 'b' : 'u', t, d), 0, FONT_SIZE*4, FONT_SIZE, LIGHTGRAY); + + // Draw instructions text + DrawText("Use ENTER to play or pause movement, use SPACE to restart", 0, GetScreenHeight() - FONT_SIZE*2, FONT_SIZE, LIGHTGRAY); + DrawText("Use D and W or A and S keys to change duration", 0, GetScreenHeight() - FONT_SIZE*3, FONT_SIZE, LIGHTGRAY); + DrawText("Use LEFT or RIGHT keys to choose easing for the x axis", 0, GetScreenHeight() - FONT_SIZE*4, FONT_SIZE, LIGHTGRAY); + DrawText("Use UP or DOWN keys to choose easing for the y axis", 0, GetScreenHeight() - FONT_SIZE*5, FONT_SIZE, LIGHTGRAY); + + // Draw ball + DrawCircleV(ballPosition, 16.0f, MAROON); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + CloseWindow(); + //-------------------------------------------------------------------------------------- + + return 0; +} + + +// NoEase function, used when "no easing" is selected for any axis. It just ignores all parameters besides b. +static float NoEase(float t, float b, float c, float d) +{ + float burn = t + b + c + d; // Hack to avoid compiler warning (about unused variables) + d += burn; + + return b; +} \ No newline at end of file diff --git a/examples/others/raudio_standalone.c b/examples/others/raudio_standalone.c index 027208379..9122c3210 100644 --- a/examples/others/raudio_standalone.c +++ b/examples/others/raudio_standalone.c @@ -58,29 +58,29 @@ // Check if a key has been pressed static int kbhit(void) { - struct termios oldt, newt; - int ch; - int oldf; + struct termios oldt, newt; + int ch; + int oldf; - tcgetattr(STDIN_FILENO, &oldt); - newt = oldt; - newt.c_lflag &= ~(ICANON | ECHO); - tcsetattr(STDIN_FILENO, TCSANOW, &newt); - oldf = fcntl(STDIN_FILENO, F_GETFL, 0); - fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK); + tcgetattr(STDIN_FILENO, &oldt); + newt = oldt; + newt.c_lflag &= ~(ICANON | ECHO); + tcsetattr(STDIN_FILENO, TCSANOW, &newt); + oldf = fcntl(STDIN_FILENO, F_GETFL, 0); + fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK); - ch = getchar(); + ch = getchar(); - tcsetattr(STDIN_FILENO, TCSANOW, &oldt); - fcntl(STDIN_FILENO, F_SETFL, oldf); + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); + fcntl(STDIN_FILENO, F_SETFL, oldf); - if (ch != EOF) - { - ungetc(ch, stdin); - return 1; - } + if (ch != EOF) + { + ungetc(ch, stdin); + return 1; + } - return 0; + return 0; } // Get pressed character @@ -94,7 +94,7 @@ int main() { // Initialization //-------------------------------------------------------------------------------------- - static unsigned char key; + static unsigned char key = 0; InitAudioDevice(); diff --git a/examples/others/rlgl_standalone.c b/examples/others/rlgl_standalone.c index 42aec2e2f..d8100ce5a 100644 --- a/examples/others/rlgl_standalone.c +++ b/examples/others/rlgl_standalone.c @@ -131,7 +131,7 @@ int main(void) rlClearColor(245, 245, 245, 255); // Define clear color rlEnableDepthTest(); // Enable DEPTH_TEST for 3D - Camera camera; + Camera camera = { 0 }; camera.position = (Vector3){ 5.0f, 5.0f, 5.0f }; // Camera position camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target) diff --git a/examples/physac/physics_demo.c b/examples/physac/physics_demo.c index a92bb9e15..421c82a90 100644 --- a/examples/physac/physics_demo.c +++ b/examples/physac/physics_demo.c @@ -10,7 +10,7 @@ * gcc -o $(NAME_PART).exe $(FILE_NAME) -s -static / * -lraylib -lpthread -lglfw3 -lopengl32 -lgdi32 -lopenal32 -lwinmm / * -std=c99 -Wl,--subsystem,windows -Wl,-allow-multiple-definition -* +* * Copyright (c) 2016-2018 Victor Fisac * ********************************************************************************************/ @@ -21,12 +21,12 @@ #define PHYSAC_NO_THREADS #include "physac.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; SetConfigFlags(FLAG_MSAA_4X_HINT); InitWindow(screenWidth, screenHeight, "Physac [raylib] - Physics demo"); @@ -41,13 +41,13 @@ int main() // Create floor rectangle physics body PhysicsBody floor = CreatePhysicsBodyRectangle((Vector2){ screenWidth/2, screenHeight }, 500, 100, 10); - floor->enabled = false; // Disable body state to convert it to static (no dynamics, but collisions) + floor->enabled = false; // Disable body state to convert it to static (no dynamics, but collisions) // Create obstacle circle physics body PhysicsBody circle = CreatePhysicsBodyCircle((Vector2){ screenWidth/2, screenHeight/2 }, 45, 10); - circle->enabled = false; // Disable body state to convert it to static (no dynamics, but collisions) - - SetTargetFPS(60); + circle->enabled = false; // Disable body state to convert it to static (no dynamics, but collisions) + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop @@ -132,9 +132,9 @@ int main() } // De-Initialization - //-------------------------------------------------------------------------------------- + //-------------------------------------------------------------------------------------- ClosePhysics(); // Unitialize physics - + CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/physac/physics_friction.c b/examples/physac/physics_friction.c index 337a12653..0acf88aea 100644 --- a/examples/physac/physics_friction.c +++ b/examples/physac/physics_friction.c @@ -10,7 +10,7 @@ * gcc -o $(NAME_PART).exe $(FILE_NAME) -s -static / * -lraylib -lpthread -lglfw3 -lopengl32 -lgdi32 -lopenal32 -lwinmm / * -std=c99 -Wl,--subsystem,windows -Wl,-allow-multiple-definition -* +* * Copyright (c) 2016-2018 Victor Fisac * ********************************************************************************************/ @@ -21,12 +21,12 @@ #define PHYSAC_NO_THREADS #include "physac.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; SetConfigFlags(FLAG_MSAA_4X_HINT); InitWindow(screenWidth, screenHeight, "Physac [raylib] - Physics friction"); @@ -61,11 +61,11 @@ int main() SetPhysicsBodyRotation(bodyA, 30*DEG2RAD); PhysicsBody bodyB = CreatePhysicsBodyRectangle((Vector2){ screenWidth - 35, screenHeight*0.6f }, 40, 40, 10); - bodyB->staticFriction = 1; - bodyB->dynamicFriction = 1; + bodyB->staticFriction = 1.0f; + bodyB->dynamicFriction = 1.0f; SetPhysicsBodyRotation(bodyB, 330*DEG2RAD); - SetTargetFPS(60); + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop @@ -82,7 +82,7 @@ int main() bodyA->velocity = (Vector2){ 0, 0 }; bodyA->angularVelocity = 0; SetPhysicsBodyRotation(bodyA, 30*DEG2RAD); - + bodyB->position = (Vector2){ screenWidth - 35, screenHeight*0.6f }; bodyB->velocity = (Vector2){ 0, 0 }; bodyB->angularVelocity = 0; @@ -137,9 +137,9 @@ int main() } // De-Initialization - //-------------------------------------------------------------------------------------- + //-------------------------------------------------------------------------------------- ClosePhysics(); // Unitialize physics - + CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/physac/physics_movement.c b/examples/physac/physics_movement.c index e799eaadb..d946811d1 100644 --- a/examples/physac/physics_movement.c +++ b/examples/physac/physics_movement.c @@ -10,7 +10,7 @@ * gcc -o $(NAME_PART).exe $(FILE_NAME) -s -static / * -lraylib -lpthread -lglfw3 -lopengl32 -lgdi32 -lopenal32 -lwinmm / * -std=c99 -Wl,--subsystem,windows -Wl,-allow-multiple-definition -* +* * Copyright (c) 2016-2018 Victor Fisac * ********************************************************************************************/ @@ -23,12 +23,12 @@ #define VELOCITY 0.5f -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; SetConfigFlags(FLAG_MSAA_4X_HINT); InitWindow(screenWidth, screenHeight, "Physac [raylib] - Physics movement"); @@ -56,9 +56,9 @@ int main() // Create movement physics body PhysicsBody body = CreatePhysicsBodyRectangle((Vector2){ screenWidth/2, screenHeight/2 }, 50, 50, 1); - body->freezeOrient = true; // Constrain body rotation to avoid little collision torque amounts - - SetTargetFPS(60); + body->freezeOrient = true; // Constrain body rotation to avoid little collision torque amounts + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop @@ -123,9 +123,9 @@ int main() } // De-Initialization - //-------------------------------------------------------------------------------------- + //-------------------------------------------------------------------------------------- ClosePhysics(); // Unitialize physics - + CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/physac/physics_restitution.c b/examples/physac/physics_restitution.c index 3231d0cf6..12a2a9220 100644 --- a/examples/physac/physics_restitution.c +++ b/examples/physac/physics_restitution.c @@ -10,7 +10,7 @@ * gcc -o $(NAME_PART).exe $(FILE_NAME) -s -static / * -lraylib -lpthread -lglfw3 -lopengl32 -lgdi32 -lopenal32 -lwinmm / * -std=c99 -Wl,--subsystem,windows -Wl,-allow-multiple-definition -* +* * Copyright (c) 2016-2018 Victor Fisac * ********************************************************************************************/ @@ -21,12 +21,12 @@ #define PHYSAC_NO_THREADS #include "physac.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; SetConfigFlags(FLAG_MSAA_4X_HINT); InitWindow(screenWidth, screenHeight, "Physac [raylib] - Physics restitution"); @@ -50,11 +50,11 @@ int main() circleB->restitution = 0.5f; PhysicsBody circleC = CreatePhysicsBodyCircle((Vector2){ screenWidth*0.75f, screenHeight/2 }, 30, 10); circleC->restitution = 1; - - SetTargetFPS(60); // Restitution demo needs a very tiny physics time step for a proper simulation - SetPhysicsTimeStep(1.0/60.0/100 * 1000); + SetPhysicsTimeStep(1.0/60.0/100*1000); + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop @@ -119,9 +119,13 @@ int main() } // De-Initialization - //-------------------------------------------------------------------------------------- + //-------------------------------------------------------------------------------------- + DestroyPhysicsBody(circleA); + DestroyPhysicsBody(circleB); + DestroyPhysicsBody(circleC); + DestroyPhysicsBody(floor); ClosePhysics(); // Unitialize physics - + CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/physac/physics_shatter.c b/examples/physac/physics_shatter.c index 747852276..cbc65221d 100644 --- a/examples/physac/physics_shatter.c +++ b/examples/physac/physics_shatter.c @@ -10,7 +10,7 @@ * gcc -o $(NAME_PART).exe $(FILE_NAME) -s -static / * -lraylib -lpthread -lglfw3 -lopengl32 -lgdi32 -lopenal32 -lwinmm / * -std=c99 -Wl,--subsystem,windows -Wl,-allow-multiple-definition -* +* * Copyright (c) 2016-2018 Victor Fisac * ********************************************************************************************/ @@ -21,12 +21,12 @@ #define PHYSAC_NO_THREADS #include "physac.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; SetConfigFlags(FLAG_MSAA_4X_HINT); InitWindow(screenWidth, screenHeight, "Physac [raylib] - Body shatter"); @@ -43,7 +43,7 @@ int main() // Create random polygon physics body to shatter CreatePhysicsBodyPolygon((Vector2){ screenWidth/2, screenHeight/2 }, GetRandomValue(80, 200), GetRandomValue(3, 8), 10); - SetTargetFPS(60); + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop @@ -115,9 +115,9 @@ int main() } // De-Initialization - //-------------------------------------------------------------------------------------- + //-------------------------------------------------------------------------------------- ClosePhysics(); // Unitialize physics - + CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/raylib_compile_execute.bat b/examples/raylib_compile_execute.bat index aaae40562..4b356419d 100644 --- a/examples/raylib_compile_execute.bat +++ b/examples/raylib_compile_execute.bat @@ -25,7 +25,7 @@ cmd /c if exist %NAMEPART%.exe del /F %NAMEPART%.exe :: -std=c99 : Use C99 language standard :: -Wall : Enable all compilation Warnings :: -mwindows : Compile a Windows executable, no cmd window -gcc -o %NAMEPART%.exe %FILENAME% %RAYLIB_RES_FILE% -s -O2 -I%RAYLIB_INCLUDE_DIR% -I%RAYLIB_LIB_DIR% -lraylib -lopengl32 -lgdi32 -std=c99 -Wall -mwindows +gcc -o %NAMEPART%.exe %FILENAME% %RAYLIB_RES_FILE% -s -O2 -I%RAYLIB_INCLUDE_DIR% -I%RAYLIB_LIB_DIR% -lraylib -lopengl32 -lgdi32 -lwinmm -std=c99 -Wall -mwindows :: . :: > Executing program :: ------------------------- diff --git a/examples/shaders/resources/mask.png b/examples/shaders/resources/mask.png new file mode 100644 index 000000000..06a259787 Binary files /dev/null and b/examples/shaders/resources/mask.png differ diff --git a/examples/shaders/resources/plasma.png b/examples/shaders/resources/plasma.png new file mode 100644 index 000000000..01c2d8837 Binary files /dev/null and b/examples/shaders/resources/plasma.png differ diff --git a/examples/shaders/resources/shaders/glsl100/cubes_panning.fs b/examples/shaders/resources/shaders/glsl100/cubes_panning.fs new file mode 100644 index 000000000..1b1ab15c0 --- /dev/null +++ b/examples/shaders/resources/shaders/glsl100/cubes_panning.fs @@ -0,0 +1,60 @@ +#version 100 + +precision mediump float; + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +// Custom variables +#define PI 3.14159265358979323846 +uniform float uTime = 0.0; + +float divisions = 5.0; +float angle = 0.0; + +vec2 VectorRotateTime(vec2 v, float speed) +{ + float time = uTime*speed; + float localTime = fract(time); // The time domain this works on is 1 sec. + + if ((localTime >= 0.0) && (localTime < 0.25)) angle = 0.0; + else if ((localTime >= 0.25) && (localTime < 0.50)) angle = PI/4*sin(2*PI*localTime - PI/2); + else if ((localTime >= 0.50) && (localTime < 0.75)) angle = PI*0.25; + else if ((localTime >= 0.75) && (localTime < 1.00)) angle = PI/4*sin(2*PI*localTime); + + // Rotate vector by angle + v -= 0.5; + v = mat2(cos(angle), -sin(angle), sin(angle), cos(angle))*v; + v += 0.5; + + return v; +} + +float Rectangle(in vec2 st, in float size, in float fill) +{ + float roundSize = 0.5 - size/2.0; + float left = step(roundSize, st.x); + float top = step(roundSize, st.y); + float bottom = step(roundSize, 1.0 - st.y); + float right = step(roundSize, 1.0 - st.x); + + return (left*bottom*right*top)*fill; +} + +void main() +{ + vec2 fragPos = fragTexCoord; + fragPos.xy += uTime/9.0; + + fragPos *= divisions; + vec2 ipos = floor(fragPos); // Get the integer coords + vec2 fpos = fract(fragPos); // Get the fractional coords + + fpos = VectorRotateTime(fpos, 0.2); + + float alpha = Rectangle(fpos, 0.216, 1.0); + vec3 color = vec3(0.3, 0.3, 0.3); + + gl_FragColor = vec4(color, alpha); +} \ No newline at end of file diff --git a/examples/shaders/resources/shaders/glsl100/depth.fs b/examples/shaders/resources/shaders/glsl100/depth.fs new file mode 100644 index 000000000..f6a14eb2f --- /dev/null +++ b/examples/shaders/resources/shaders/glsl100/depth.fs @@ -0,0 +1,26 @@ +#version 100 + +precision mediump float; + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; // Depth texture +uniform vec4 colDiffuse; + +// NOTE: Add here your custom variables + +void main() +{ + float zNear = 0.01; // camera z near + float zFar = 10.0; // camera z far + float z = texture2D(texture0, fragTexCoord).x; + + // Linearize depth value + float depth = (2.0*zNear)/(zFar + zNear - z*(zFar - zNear)); + + // Calculate final fragment color + gl_FragColor = vec4(depth, depth, depth, 1.0f); +} \ No newline at end of file diff --git a/examples/shaders/resources/shaders/glsl100/eratosthenes.fs b/examples/shaders/resources/shaders/glsl100/eratosthenes.fs new file mode 100644 index 000000000..0d598cacb --- /dev/null +++ b/examples/shaders/resources/shaders/glsl100/eratosthenes.fs @@ -0,0 +1,58 @@ +#version 100 + +precision mediump float; + +/************************************************************************************* + + The Sieve of Eratosthenes -- a simple shader by ProfJski + An early prime number sieve: https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes + + The screen is divided into a square grid of boxes, each representing an integer value. + Each integer is tested to see if it is a prime number. Primes are colored white. + Non-primes are colored with a color that indicates the smallest factor which evenly divdes our integer. + + You can change the scale variable to make a larger or smaller grid. + Total number of integers displayed = scale squared, so scale = 100 tests the first 10,000 integers. + + WARNING: If you make scale too large, your GPU may bog down! + +***************************************************************************************/ + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +// Make a nice spectrum of colors based on counter and maxSize +vec4 Colorizer(float counter, float maxSize) +{ + float red = 0.0, green = 0.0, blue = 0.0; + float normsize = counter/maxSize; + + red = smoothstep(0.3, 0.7, normsize); + green = sin(3.14159*normsize); + blue = 1.0 - smoothstep(0.0, 0.4, normsize); + + return vec4(0.8*red, 0.8*green, 0.8*blue, 1.0); +} + +void main() +{ + vec4 color = vec4(1.0); + float scale = 1000.0; // Makes 100x100 square grid. Change this variable to make a smaller or larger grid. + int value = int(scale*floor(fragTexCoord.y*scale) + floor(fragTexCoord.x*scale)); // Group pixels into boxes representing integer values + + if ((value == 0) || (value == 1) || (value == 2)) gl_FragColor = vec4(1.0); + else + { + for (int i = 2; (i < max(2, sqrt(value) + 1)); i++) + { + if ((value - i*floor(value/i)) == 0) + { + color = Colorizer(float(i), scale); + //break; // Uncomment to color by the largest factor instead + } + } + + gl_FragColor = color; + } +} diff --git a/examples/shaders/resources/shaders/glsl100/julia_set.fs b/examples/shaders/resources/shaders/glsl100/julia_set.fs new file mode 100644 index 000000000..149a559c1 --- /dev/null +++ b/examples/shaders/resources/shaders/glsl100/julia_set.fs @@ -0,0 +1,81 @@ +#version 100 + +precision mediump float; + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +uniform vec2 screenDims; // Dimensions of the screen +uniform vec2 c; // c.x = real, c.y = imaginary component. Equation done is z^2 + c +uniform vec2 offset; // Offset of the scale. +uniform float zoom; // Zoom of the scale. + +const int MAX_ITERATIONS = 255; // Max iterations to do. + +// Square a complex number +vec2 ComplexSquare(vec2 z) +{ + return vec2( + z.x * z.x - z.y * z.y, + z.x * z.y * 2.0 + ); +} + +// Convert Hue Saturation Value (HSV) color into RGB +vec3 Hsv2rgb(vec3 c) +{ + vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); + vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); + return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); +} + + +void main() +{ + /********************************************************************************************** + Julia sets use a function z^2 + c, where c is a constant. + This function is iterated until the nature of the point is determined. + + If the magnitude of the number becomes greater than 2, then from that point onward + the number will get bigger and bigger, and will never get smaller (tends towards infinity). + 2^2 = 4, 4^2 = 8 and so on. + So at 2 we stop iterating. + + If the number is below 2, we keep iterating. + But when do we stop iterating if the number is always below 2 (it converges)? + That is what MAX_ITERATIONS is for. + Then we can divide the iterations by the MAX_ITERATIONS value to get a normalized value that we can + then map to a color. + + We use dot product (z.x * z.x + z.y * z.y) to determine the magnitude (length) squared. + And once the magnitude squared is > 4, then magnitude > 2 is also true (saves computational power). + *************************************************************************************************/ + + // The pixel coordinates are scaled so they are on the mandelbrot scale + // NOTE: fragTexCoord already comes as normalized screen coordinates but offset must be normalized before scaling and zoom + vec2 z = vec2((fragTexCoord.x + offset.x/screenDims.x)*2.5/zoom, (fragTexCoord.y + offset.y/screenDims.y)*1.5/zoom); + + int iterations = 0; + for (iterations = 0; iterations < MAX_ITERATIONS; iterations++) + { + z = ComplexSquare(z) + c; // Iterate function + + if (dot(z, z) > 4.0) break; + } + + // Another few iterations decreases errors in the smoothing calculation. + // See http://linas.org/art-gallery/escape/escape.html for more information. + z = ComplexSquare(z) + c; + z = ComplexSquare(z) + c; + + // This last part smooths the color (again see link above). + float smoothVal = float(iterations) + 1.0 - (log(log(length(z)))/log(2.0)); + + // Normalize the value so it is between 0 and 1. + float norm = smoothVal/float(MAX_ITERATIONS); + + // If in set, color black. 0.999 allows for some float accuracy error. + if (norm > 0.999) gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); + else gl_FragColor = vec4(Hsv2rgb(vec3(norm, 1.0, 1.0)), 1.0); +} diff --git a/examples/shaders/resources/shaders/glsl100/palette_switch.fs b/examples/shaders/resources/shaders/glsl100/palette_switch.fs index 7f09137e7..3861d4c11 100644 --- a/examples/shaders/resources/shaders/glsl100/palette_switch.fs +++ b/examples/shaders/resources/shaders/glsl100/palette_switch.fs @@ -15,7 +15,7 @@ uniform ivec3 palette[colors]; void main() { // Texel color fetching from texture sampler - vec4 texelColor = texture(texture0, fragTexCoord) * fragColor; + vec4 texelColor = texture2D(texture0, fragTexCoord) * fragColor; // Convert the (normalized) texel color RED component (GB would work, too) // to the palette index by scaling up from [0, 1] to [0, 255]. diff --git a/examples/shaders/resources/shaders/glsl100/raymarching.fs b/examples/shaders/resources/shaders/glsl100/raymarching.fs new file mode 100644 index 000000000..c823e01eb --- /dev/null +++ b/examples/shaders/resources/shaders/glsl100/raymarching.fs @@ -0,0 +1,429 @@ +#version 100 + +precision mediump float; + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +uniform vec3 viewEye; +uniform vec3 viewCenter; +uniform float runTime; +uniform vec2 resolution; + +// The MIT License +// Copyright © 2013 Inigo Quilez +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +// A list of useful distance function to simple primitives, and an example on how to +// do some interesting boolean operations, repetition and displacement. +// +// More info here: http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm + +#define AA 1 // make this 1 is your machine is too slow + +//------------------------------------------------------------------ + +float sdPlane( vec3 p ) +{ + return p.y; +} + +float sdSphere( vec3 p, float s ) +{ + return length(p)-s; +} + +float sdBox( vec3 p, vec3 b ) +{ + vec3 d = abs(p) - b; + return min(max(d.x,max(d.y,d.z)),0.0) + length(max(d,0.0)); +} + +float sdEllipsoid( in vec3 p, in vec3 r ) +{ + return (length( p/r ) - 1.0) * min(min(r.x,r.y),r.z); +} + +float udRoundBox( vec3 p, vec3 b, float r ) +{ + return length(max(abs(p)-b,0.0))-r; +} + +float sdTorus( vec3 p, vec2 t ) +{ + return length( vec2(length(p.xz)-t.x,p.y) )-t.y; +} + +float sdHexPrism( vec3 p, vec2 h ) +{ + vec3 q = abs(p); +#if 0 + return max(q.z-h.y,max((q.x*0.866025+q.y*0.5),q.y)-h.x); +#else + float d1 = q.z-h.y; + float d2 = max((q.x*0.866025+q.y*0.5),q.y)-h.x; + return length(max(vec2(d1,d2),0.0)) + min(max(d1,d2), 0.); +#endif +} + +float sdCapsule( vec3 p, vec3 a, vec3 b, float r ) +{ + vec3 pa = p-a, ba = b-a; + float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 ); + return length( pa - ba*h ) - r; +} + +float sdEquilateralTriangle( in vec2 p ) +{ + const float k = sqrt(3.0); + p.x = abs(p.x) - 1.0; + p.y = p.y + 1.0/k; + if( p.x + k*p.y > 0.0 ) p = vec2( p.x - k*p.y, -k*p.x - p.y )/2.0; + p.x += 2.0 - 2.0*clamp( (p.x+2.0)/2.0, 0.0, 1.0 ); + return -length(p)*sign(p.y); +} + +float sdTriPrism( vec3 p, vec2 h ) +{ + vec3 q = abs(p); + float d1 = q.z-h.y; +#if 1 + // distance bound + float d2 = max(q.x*0.866025+p.y*0.5,-p.y)-h.x*0.5; +#else + // correct distance + h.x *= 0.866025; + float d2 = sdEquilateralTriangle(p.xy/h.x)*h.x; +#endif + return length(max(vec2(d1,d2),0.0)) + min(max(d1,d2), 0.); +} + +float sdCylinder( vec3 p, vec2 h ) +{ + vec2 d = abs(vec2(length(p.xz),p.y)) - h; + return min(max(d.x,d.y),0.0) + length(max(d,0.0)); +} + +float sdCone( in vec3 p, in vec3 c ) +{ + vec2 q = vec2( length(p.xz), p.y ); + float d1 = -q.y-c.z; + float d2 = max( dot(q,c.xy), q.y); + return length(max(vec2(d1,d2),0.0)) + min(max(d1,d2), 0.); +} + +float sdConeSection( in vec3 p, in float h, in float r1, in float r2 ) +{ + float d1 = -p.y - h; + float q = p.y - h; + float si = 0.5*(r1-r2)/h; + float d2 = max( sqrt( dot(p.xz,p.xz)*(1.0-si*si)) + q*si - r2, q ); + return length(max(vec2(d1,d2),0.0)) + min(max(d1,d2), 0.); +} + +float sdPryamid4(vec3 p, vec3 h ) // h = { cos a, sin a, height } +{ + // Tetrahedron = Octahedron - Cube + float box = sdBox( p - vec3(0,-2.0*h.z,0), vec3(2.0*h.z) ); + + float d = 0.0; + d = max( d, abs( dot(p, vec3( -h.x, h.y, 0 )) )); + d = max( d, abs( dot(p, vec3( h.x, h.y, 0 )) )); + d = max( d, abs( dot(p, vec3( 0, h.y, h.x )) )); + d = max( d, abs( dot(p, vec3( 0, h.y,-h.x )) )); + float octa = d - h.z; + return max(-box,octa); // Subtraction + } + +float length2( vec2 p ) +{ + return sqrt( p.x*p.x + p.y*p.y ); +} + +float length6( vec2 p ) +{ + p = p*p*p; p = p*p; + return pow( p.x + p.y, 1.0/6.0 ); +} + +float length8( vec2 p ) +{ + p = p*p; p = p*p; p = p*p; + return pow( p.x + p.y, 1.0/8.0 ); +} + +float sdTorus82( vec3 p, vec2 t ) +{ + vec2 q = vec2(length2(p.xz)-t.x,p.y); + return length8(q)-t.y; +} + +float sdTorus88( vec3 p, vec2 t ) +{ + vec2 q = vec2(length8(p.xz)-t.x,p.y); + return length8(q)-t.y; +} + +float sdCylinder6( vec3 p, vec2 h ) +{ + return max( length6(p.xz)-h.x, abs(p.y)-h.y ); +} + +//------------------------------------------------------------------ + +float opS( float d1, float d2 ) +{ + return max(-d2,d1); +} + +vec2 opU( vec2 d1, vec2 d2 ) +{ + return (d1.x0.0 ) tmax = min( tmax, tp1 ); + float tp2 = (1.6-ro.y)/rd.y; if( tp2>0.0 ) { if( ro.y>1.6 ) tmin = max( tmin, tp2 ); + else tmax = min( tmax, tp2 ); } +#endif + + float t = tmin; + float m = -1.0; + for( int i=0; i<64; i++ ) + { + float precis = 0.0005*t; + vec2 res = map( ro+rd*t ); + if( res.xtmax ) break; + t += res.x; + m = res.y; + } + + if( t>tmax ) m=-1.0; + return vec2( t, m ); +} + + +float calcSoftshadow( in vec3 ro, in vec3 rd, in float mint, in float tmax ) +{ + float res = 1.0; + float t = mint; + for( int i=0; i<16; i++ ) + { + float h = map( ro + rd*t ).x; + res = min( res, 8.0*h/t ); + t += clamp( h, 0.02, 0.10 ); + if( h<0.001 || t>tmax ) break; + } + return clamp( res, 0.0, 1.0 ); +} + +vec3 calcNormal( in vec3 pos ) +{ + vec2 e = vec2(1.0,-1.0)*0.5773*0.0005; + return normalize( e.xyy*map( pos + e.xyy ).x + + e.yyx*map( pos + e.yyx ).x + + e.yxy*map( pos + e.yxy ).x + + e.xxx*map( pos + e.xxx ).x ); + /* + vec3 eps = vec3( 0.0005, 0.0, 0.0 ); + vec3 nor = vec3( + map(pos+eps.xyy).x - map(pos-eps.xyy).x, + map(pos+eps.yxy).x - map(pos-eps.yxy).x, + map(pos+eps.yyx).x - map(pos-eps.yyx).x ); + return normalize(nor); + */ +} + +float calcAO( in vec3 pos, in vec3 nor ) +{ + float occ = 0.0; + float sca = 1.0; + for( int i=0; i<5; i++ ) + { + float hr = 0.01 + 0.12*float(i)/4.0; + vec3 aopos = nor * hr + pos; + float dd = map( aopos ).x; + occ += -(dd-hr)*sca; + sca *= 0.95; + } + return clamp( 1.0 - 3.0*occ, 0.0, 1.0 ); +} + +// http://iquilezles.org/www/articles/checkerfiltering/checkerfiltering.htm +float checkersGradBox( in vec2 p ) +{ + // filter kernel + vec2 w = fwidth(p) + 0.001; + // analytical integral (box filter) + vec2 i = 2.0*(abs(fract((p-0.5*w)*0.5)-0.5)-abs(fract((p+0.5*w)*0.5)-0.5))/w; + // xor pattern + return 0.5 - 0.5*i.x*i.y; +} + +vec3 render( in vec3 ro, in vec3 rd ) +{ + vec3 col = vec3(0.7, 0.9, 1.0) +rd.y*0.8; + vec2 res = castRay(ro,rd); + float t = res.x; + float m = res.y; + if( m>-0.5 ) + { + vec3 pos = ro + t*rd; + vec3 nor = calcNormal( pos ); + vec3 ref = reflect( rd, nor ); + + // material + col = 0.45 + 0.35*sin( vec3(0.05,0.08,0.10)*(m-1.0) ); + if( m<1.5 ) + { + + float f = checkersGradBox( 5.0*pos.xz ); + col = 0.3 + f*vec3(0.1); + } + + // lighting + float occ = calcAO( pos, nor ); + vec3 lig = normalize( vec3(cos(-0.4 * runTime), sin(0.7 * runTime), -0.6) ); + vec3 hal = normalize( lig-rd ); + float amb = clamp( 0.5+0.5*nor.y, 0.0, 1.0 ); + float dif = clamp( dot( nor, lig ), 0.0, 1.0 ); + float bac = clamp( dot( nor, normalize(vec3(-lig.x,0.0,-lig.z))), 0.0, 1.0 )*clamp( 1.0-pos.y,0.0,1.0); + float dom = smoothstep( -0.1, 0.1, ref.y ); + float fre = pow( clamp(1.0+dot(nor,rd),0.0,1.0), 2.0 ); + + dif *= calcSoftshadow( pos, lig, 0.02, 2.5 ); + dom *= calcSoftshadow( pos, ref, 0.02, 2.5 ); + + float spe = pow( clamp( dot( nor, hal ), 0.0, 1.0 ),16.0)* + dif * + (0.04 + 0.96*pow( clamp(1.0+dot(hal,rd),0.0,1.0), 5.0 )); + + vec3 lin = vec3(0.0); + lin += 1.30*dif*vec3(1.00,0.80,0.55); + lin += 0.40*amb*vec3(0.40,0.60,1.00)*occ; + lin += 0.50*dom*vec3(0.40,0.60,1.00)*occ; + lin += 0.50*bac*vec3(0.25,0.25,0.25)*occ; + lin += 0.25*fre*vec3(1.00,1.00,1.00)*occ; + col = col*lin; + col += 10.00*spe*vec3(1.00,0.90,0.70); + + col = mix( col, vec3(0.8,0.9,1.0), 1.0-exp( -0.0002*t*t*t ) ); + } + + return vec3( clamp(col,0.0,1.0) ); +} + +mat3 setCamera( in vec3 ro, in vec3 ta, float cr ) +{ + vec3 cw = normalize(ta-ro); + vec3 cp = vec3(sin(cr), cos(cr),0.0); + vec3 cu = normalize( cross(cw,cp) ); + vec3 cv = normalize( cross(cu,cw) ); + return mat3( cu, cv, cw ); +} + +void main() +{ + vec3 tot = vec3(0.0); +#if AA>1 + for( int m=0; m1 + } + tot /= float(AA*AA); +#endif + + gl_FragColor = vec4( tot, 1.0 ); +} diff --git a/examples/shaders/resources/shaders/glsl100/wave.fs b/examples/shaders/resources/shaders/glsl100/wave.fs new file mode 100644 index 000000000..bcc156cc6 --- /dev/null +++ b/examples/shaders/resources/shaders/glsl100/wave.fs @@ -0,0 +1,36 @@ +#version 100 + +precision mediump float; + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +uniform float secondes; + +uniform vec2 size; + +uniform float freqX; +uniform float freqY; +uniform float ampX; +uniform float ampY; +uniform float speedX; +uniform float speedY; + +void main() { + float pixelWidth = 1.0 / size.x; + float pixelHeight = 1.0 / size.y; + float aspect = pixelHeight / pixelWidth; + float boxLeft = 0.0; + float boxTop = 0.0; + + vec2 p = fragTexCoord; + p.x += cos((fragTexCoord.y - boxTop) * freqX / ( pixelWidth * 750.0) + (secondes * speedX)) * ampX * pixelWidth; + p.y += sin((fragTexCoord.x - boxLeft) * freqY * aspect / ( pixelHeight * 750.0) + (secondes * speedY)) * ampY * pixelHeight; + + gl_FragColor = texture2D(texture0, p)*colDiffuse*fragColor; +} diff --git a/examples/shaders/resources/shaders/glsl330/basic_lighting.fs b/examples/shaders/resources/shaders/glsl330/basic_lighting.fs new file mode 100644 index 000000000..50b41f09f --- /dev/null +++ b/examples/shaders/resources/shaders/glsl330/basic_lighting.fs @@ -0,0 +1,82 @@ +#version 330 + +// Input vertex attributes (from vertex shader) +in vec3 fragPosition; +in vec2 fragTexCoord; +in vec4 fragColor; +in vec3 fragNormal; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// Output fragment color +out vec4 finalColor; + +// NOTE: Add here your custom variables + +#define MAX_LIGHTS 4 +#define LIGHT_DIRECTIONAL 0 +#define LIGHT_POINT 1 + +struct MaterialProperty { + vec3 color; + int useSampler; + sampler2D sampler; +}; + +struct Light { + int enabled; + int type; + vec3 position; + vec3 target; + vec4 color; +}; + +// Input lighting values +uniform Light lights[MAX_LIGHTS]; +uniform vec4 ambient; +uniform vec3 viewPos; + +void main() +{ + // Texel color fetching from texture sampler + vec4 texelColor = texture(texture0, fragTexCoord); + vec3 lightDot = vec3(0.0); + vec3 normal = normalize(fragNormal); + vec3 viewD = normalize(viewPos - fragPosition); + vec3 specular = vec3(0.0); + + // NOTE: Implement here your fragment shader code + + for (int i = 0; i < MAX_LIGHTS; i++) + { + if (lights[i].enabled == 1) + { + vec3 light = vec3(0.0); + + if (lights[i].type == LIGHT_DIRECTIONAL) + { + light = -normalize(lights[i].target - lights[i].position); + } + + if (lights[i].type == LIGHT_POINT) + { + light = normalize(lights[i].position - fragPosition); + } + + float NdotL = max(dot(normal, light), 0.0); + lightDot += lights[i].color.rgb*NdotL; + + float specCo = 0.0; + if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewD, reflect(-(light), normal))), 16); // 16 refers to shine + specular += specCo; + } + } + + finalColor = (texelColor*((colDiffuse + vec4(specular, 1.0))*vec4(lightDot, 1.0))); + finalColor += texelColor*(ambient/10.0); + + // Gamma correction + finalColor = pow(finalColor, vec4(1.0/2.2)); +} diff --git a/examples/shaders/resources/shaders/glsl330/basic_lighting.vs b/examples/shaders/resources/shaders/glsl330/basic_lighting.vs new file mode 100644 index 000000000..509954ddd --- /dev/null +++ b/examples/shaders/resources/shaders/glsl330/basic_lighting.vs @@ -0,0 +1,33 @@ +#version 330 + +// Input vertex attributes +in vec3 vertexPosition; +in vec2 vertexTexCoord; +in vec3 vertexNormal; +in vec4 vertexColor; + +// Input uniform values +uniform mat4 mvp; +uniform mat4 matModel; + +// Output vertex attributes (to fragment shader) +out vec3 fragPosition; +out vec2 fragTexCoord; +out vec4 fragColor; +out vec3 fragNormal; + +// NOTE: Add here your custom variables + +void main() +{ + // Send vertex attributes to fragment shader + fragPosition = vec3(matModel*vec4(vertexPosition, 1.0f)); + fragTexCoord = vertexTexCoord; + fragColor = vertexColor; + + mat3 normalMatrix = transpose(inverse(mat3(matModel))); + fragNormal = normalize(normalMatrix*vertexNormal); + + // Calculate final vertex position + gl_Position = mvp*vec4(vertexPosition, 1.0); +} diff --git a/examples/shaders/resources/shaders/glsl330/eratosthenes.fs b/examples/shaders/resources/shaders/glsl330/eratosthenes.fs new file mode 100644 index 000000000..a6390b745 --- /dev/null +++ b/examples/shaders/resources/shaders/glsl330/eratosthenes.fs @@ -0,0 +1,59 @@ +#version 330 + +/************************************************************************************* + + The Sieve of Eratosthenes -- a simple shader by ProfJski + An early prime number sieve: https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes + + The screen is divided into a square grid of boxes, each representing an integer value. + Each integer is tested to see if it is a prime number. Primes are colored white. + Non-primes are colored with a color that indicates the smallest factor which evenly divdes our integer. + + You can change the scale variable to make a larger or smaller grid. + Total number of integers displayed = scale squared, so scale = 100 tests the first 10,000 integers. + + WARNING: If you make scale too large, your GPU may bog down! + +***************************************************************************************/ + +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; +in vec4 fragColor; + +// Output fragment color +out vec4 finalColor; + +// Make a nice spectrum of colors based on counter and maxSize +vec4 Colorizer(float counter, float maxSize) +{ + float red = 0.0, green = 0.0, blue = 0.0; + float normsize = counter/maxSize; + + red = smoothstep(0.3, 0.7, normsize); + green = sin(3.14159*normsize); + blue = 1.0 - smoothstep(0.0, 0.4, normsize); + + return vec4(0.8*red, 0.8*green, 0.8*blue, 1.0); +} + +void main() +{ + vec4 color = vec4(1.0); + float scale = 1000.0; // Makes 100x100 square grid. Change this variable to make a smaller or larger grid. + int value = int(scale*floor(fragTexCoord.y*scale)+floor(fragTexCoord.x*scale)); // Group pixels into boxes representing integer values + + if ((value == 0) || (value == 1) || (value == 2)) finalColor = vec4(1.0); + else + { + for (int i = 2; (i < max(2, sqrt(value) + 1)); i++) + { + if ((value - i*floor(value/i)) == 0) + { + color = Colorizer(float(i), scale); + //break; // Uncomment to color by the largest factor instead + } + } + + finalColor = color; + } +} diff --git a/examples/shaders/resources/shaders/glsl330/fog.fs b/examples/shaders/resources/shaders/glsl330/fog.fs new file mode 100644 index 000000000..57ed14807 --- /dev/null +++ b/examples/shaders/resources/shaders/glsl330/fog.fs @@ -0,0 +1,99 @@ +#version 330 + +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; +in vec4 fragColor; +in vec3 fragPosition; +in vec3 fragNormal; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// Output fragment color +out vec4 finalColor; + +// NOTE: Add here your custom variables + +#define MAX_LIGHTS 4 +#define LIGHT_DIRECTIONAL 0 +#define LIGHT_POINT 1 + +struct MaterialProperty { + vec3 color; + int useSampler; + sampler2D sampler; +}; + +struct Light { + int enabled; + int type; + vec3 position; + vec3 target; + vec4 color; +}; + +// Input lighting values +uniform Light lights[MAX_LIGHTS]; +uniform vec4 ambient; +uniform vec3 viewPos; +uniform float fogDensity; + +void main() +{ + // Texel color fetching from texture sampler + vec4 texelColor = texture(texture0, fragTexCoord); + vec3 lightDot = vec3(0.0); + vec3 normal = normalize(fragNormal); + vec3 viewD = normalize(viewPos - fragPosition); + vec3 specular = vec3(0.0); + + // NOTE: Implement here your fragment shader code + + for (int i = 0; i < MAX_LIGHTS; i++) + { + if (lights[i].enabled == 1) + { + vec3 light = vec3(0.0); + if (lights[i].type == LIGHT_DIRECTIONAL) { + light = -normalize(lights[i].target - lights[i].position); + } + if (lights[i].type == LIGHT_POINT) { + light = normalize(lights[i].position - fragPosition); + } + float NdotL = max(dot(normal, light), 0.0); + lightDot += lights[i].color.rgb * NdotL; + + float specCo = 0.0; + if(NdotL > 0.0) + specCo = pow(max(0.0, dot(viewD, reflect(-(light), normal))), 16);//16 =shine + specular += specCo; + + } + } + + finalColor = (texelColor * ((colDiffuse+vec4(specular,1)) * vec4(lightDot, 1.0))); + finalColor += texelColor * (ambient/10.0); + + // Gamma correction + finalColor = pow(finalColor, vec4(1.0/2.2)); + + // Fog calculation + float dist = length(viewPos - fragPosition); + + // these could be parameters... + const vec4 fogColor = vec4(0.5, 0.5, 0.5, 1.0); + //const float fogDensity = 0.16; + + // Exponential fog + float fogFactor = 1.0/exp((dist*fogDensity)*(dist*fogDensity)); + + // Linear fog (less nice) + //const float fogStart = 2.0; + //const float fogEnd = 10.0; + //float fogFactor = (fogEnd - dist)/(fogEnd - fogStart); + + fogFactor = clamp(fogFactor, 0.0, 1.0); + + finalColor = mix(fogColor, finalColor, fogFactor); +} diff --git a/examples/shaders/resources/shaders/glsl330/fog.vs b/examples/shaders/resources/shaders/glsl330/fog.vs new file mode 100644 index 000000000..00779cfa3 --- /dev/null +++ b/examples/shaders/resources/shaders/glsl330/fog.vs @@ -0,0 +1,32 @@ +#version 330 + +// Input vertex attributes +in vec3 vertexPosition; +in vec2 vertexTexCoord; +in vec3 vertexNormal; +in vec4 vertexColor; + +// Input uniform values +uniform mat4 mvp; +uniform mat4 matModel; + +// Output vertex attributes (to fragment shader) +out vec2 fragTexCoord; +out vec4 fragColor; +out vec3 fragPosition; +out vec3 fragNormal; + +// NOTE: Add here your custom variables + +void main() +{ + // Send vertex attributes to fragment shader + fragTexCoord = vertexTexCoord; + fragColor = vertexColor; + fragPosition = vec3(matModel*vec4(vertexPosition, 1.0f)); + mat3 normalMatrix = transpose(inverse(mat3(matModel))); + fragNormal = normalize(normalMatrix*vertexNormal); + + // Calculate final vertex position + gl_Position = mvp*vec4(vertexPosition, 1.0); +} diff --git a/examples/shaders/resources/shaders/glsl330/julia_set.fs b/examples/shaders/resources/shaders/glsl330/julia_set.fs new file mode 100644 index 000000000..f68367ea6 --- /dev/null +++ b/examples/shaders/resources/shaders/glsl330/julia_set.fs @@ -0,0 +1,81 @@ +#version 330 + +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; +in vec4 fragColor; + +// Output fragment color +out vec4 finalColor; + +uniform vec2 screenDims; // Dimensions of the screen +uniform vec2 c; // c.x = real, c.y = imaginary component. Equation done is z^2 + c +uniform vec2 offset; // Offset of the scale. +uniform float zoom; // Zoom of the scale. + +const int MAX_ITERATIONS = 255; // Max iterations to do. + +// Square a complex number +vec2 ComplexSquare(vec2 z) +{ + return vec2( + z.x * z.x - z.y * z.y, + z.x * z.y * 2.0 + ); +} + +// Convert Hue Saturation Value (HSV) color into RGB +vec3 Hsv2rgb(vec3 c) +{ + vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); + vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); + return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); +} + +void main() +{ + /********************************************************************************************** + Julia sets use a function z^2 + c, where c is a constant. + This function is iterated until the nature of the point is determined. + + If the magnitude of the number becomes greater than 2, then from that point onward + the number will get bigger and bigger, and will never get smaller (tends towards infinity). + 2^2 = 4, 4^2 = 8 and so on. + So at 2 we stop iterating. + + If the number is below 2, we keep iterating. + But when do we stop iterating if the number is always below 2 (it converges)? + That is what MAX_ITERATIONS is for. + Then we can divide the iterations by the MAX_ITERATIONS value to get a normalized value that we can + then map to a color. + + We use dot product (z.x * z.x + z.y * z.y) to determine the magnitude (length) squared. + And once the magnitude squared is > 4, then magnitude > 2 is also true (saves computational power). + *************************************************************************************************/ + + // The pixel coordinates are scaled so they are on the mandelbrot scale + // NOTE: fragTexCoord already comes as normalized screen coordinates but offset must be normalized before scaling and zoom + vec2 z = vec2((fragTexCoord.x + offset.x/screenDims.x)*2.5/zoom, (fragTexCoord.y + offset.y/screenDims.y)*1.5/zoom); + + int iterations = 0; + for (iterations = 0; iterations < MAX_ITERATIONS; iterations++) + { + z = ComplexSquare(z) + c; // Iterate function + + if (dot(z, z) > 4.0) break; + } + + // Another few iterations decreases errors in the smoothing calculation. + // See http://linas.org/art-gallery/escape/escape.html for more information. + z = ComplexSquare(z) + c; + z = ComplexSquare(z) + c; + + // This last part smooths the color (again see link above). + float smoothVal = float(iterations) + 1.0 - (log(log(length(z)))/log(2.0)); + + // Normalize the value so it is between 0 and 1. + float norm = smoothVal/float(MAX_ITERATIONS); + + // If in set, color black. 0.999 allows for some float accuracy error. + if (norm > 0.999) finalColor = vec4(0.0, 0.0, 0.0, 1.0); + else finalColor = vec4(Hsv2rgb(vec3(norm, 1.0, 1.0)), 1.0); +} diff --git a/examples/shaders/resources/shaders/glsl330/mask.fs b/examples/shaders/resources/shaders/glsl330/mask.fs new file mode 100644 index 000000000..a06279096 --- /dev/null +++ b/examples/shaders/resources/shaders/glsl330/mask.fs @@ -0,0 +1,21 @@ +#version 330 + +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; + +// Input uniform values +uniform sampler2D texture0; +uniform sampler2D mask; +uniform int frame; + +// Output fragment color +out vec4 finalColor; + +void main() +{ + vec4 maskColour = texture(mask, fragTexCoord+vec2(sin(-frame/150.0)/10.0,cos(-frame/170.0)/10.0)); + if (maskColour.r < 0.25) discard; + vec4 texelColor = texture(texture0, fragTexCoord+vec2(sin(frame/90.0)/8.0,cos(frame/60.0)/8.0)); + + finalColor = texelColor * maskColour; +} diff --git a/examples/shaders/resources/shaders/glsl330/mask.vs b/examples/shaders/resources/shaders/glsl330/mask.vs new file mode 100644 index 000000000..66a151617 --- /dev/null +++ b/examples/shaders/resources/shaders/glsl330/mask.vs @@ -0,0 +1,21 @@ +#version 330 + +// Input vertex attributes +in vec3 vertexPosition; +in vec2 vertexTexCoord; + +// Input uniform values +uniform mat4 mvp; +uniform mat4 matModel; + +// Output vertex attributes (to fragment shader) +out vec2 fragTexCoord; + +void main() +{ + // Send vertex attributes to fragment shader + fragTexCoord = vertexTexCoord; + + // Calculate final vertex position + gl_Position = mvp*vec4(vertexPosition, 1.0); +} diff --git a/examples/shaders/resources/shaders/glsl330/raymarching.fs b/examples/shaders/resources/shaders/glsl330/raymarching.fs index 5ec9a02a4..3cec58a2b 100644 --- a/examples/shaders/resources/shaders/glsl330/raymarching.fs +++ b/examples/shaders/resources/shaders/glsl330/raymarching.fs @@ -1,17 +1,36 @@ #version 330 +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; +in vec4 fragColor; + +// Output fragment color out vec4 finalColor; uniform vec3 viewEye; uniform vec3 viewCenter; -uniform vec3 viewUp; -uniform float deltaTime; uniform float runTime; uniform vec2 resolution; // The MIT License // Copyright © 2013 Inigo Quilez -// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. // A list of useful distance function to simple primitives, and an example on how to // do some interesting boolean operations, repetition and displacement. @@ -408,4 +427,4 @@ void main() #endif finalColor = vec4( tot, 1.0 ); -} \ No newline at end of file +} diff --git a/examples/shaders/resources/shaders/glsl330/wave.fs b/examples/shaders/resources/shaders/glsl330/wave.fs new file mode 100644 index 000000000..f139f3957 --- /dev/null +++ b/examples/shaders/resources/shaders/glsl330/wave.fs @@ -0,0 +1,37 @@ +#version 330 + +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; +in vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// Output fragment color +out vec4 finalColor; + +uniform float secondes; + +uniform vec2 size; + +uniform float freqX; +uniform float freqY; +uniform float ampX; +uniform float ampY; +uniform float speedX; +uniform float speedY; + +void main() { + float pixelWidth = 1.0 / size.x; + float pixelHeight = 1.0 / size.y; + float aspect = pixelHeight / pixelWidth; + float boxLeft = 0.0; + float boxTop = 0.0; + + vec2 p = fragTexCoord; + p.x += cos((fragTexCoord.y - boxTop) * freqX / ( pixelWidth * 750.0) + (secondes * speedX)) * ampX * pixelWidth; + p.y += sin((fragTexCoord.x - boxLeft) * freqY * aspect / ( pixelHeight * 750.0) + (secondes * speedY)) * ampY * pixelHeight; + + finalColor = texture(texture0, p)*colDiffuse*fragColor; +} diff --git a/examples/shaders/resources/space.png b/examples/shaders/resources/space.png new file mode 100644 index 000000000..411297390 Binary files /dev/null and b/examples/shaders/resources/space.png differ diff --git a/examples/shaders/resources/texel_checker.png b/examples/shaders/resources/texel_checker.png new file mode 100644 index 000000000..0e03e3ed6 Binary files /dev/null and b/examples/shaders/resources/texel_checker.png differ diff --git a/examples/shaders/rlights.h b/examples/shaders/rlights.h new file mode 100644 index 000000000..b564efc3c --- /dev/null +++ b/examples/shaders/rlights.h @@ -0,0 +1,187 @@ +/********************************************************************************************** +* +* raylib.lights - Some useful functions to deal with lights data +* +* CONFIGURATION: +* +* #define RLIGHTS_IMPLEMENTATION +* Generates the implementation of the library into the included file. +* If not defined, the library is in header only mode and can be included in other headers +* or source files without problems. But only ONE file should hold the implementation. +* +* LICENSE: zlib/libpng +* +* Copyright (c) 2017-2019 Victor Fisac (@victorfisac) and Ramon Santamaria (@raysan5) +* +* This software is provided "as-is", without any express or implied warranty. In no event +* will the authors be held liable for any damages arising from the use of this software. +* +* Permission is granted to anyone to use this software for any purpose, including commercial +* applications, and to alter it and redistribute it freely, subject to the following restrictions: +* +* 1. The origin of this software must not be misrepresented; you must not claim that you +* wrote the original software. If you use this software in a product, an acknowledgment +* in the product documentation would be appreciated but is not required. +* +* 2. Altered source versions must be plainly marked as such, and must not be misrepresented +* as being the original software. +* +* 3. This notice may not be removed or altered from any source distribution. +* +**********************************************************************************************/ + +#ifndef RLIGHTS_H +#define RLIGHTS_H + +//---------------------------------------------------------------------------------- +// Defines and Macros +//---------------------------------------------------------------------------------- +#define MAX_LIGHTS 4 // Max dynamic lights supported by shader + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- + +// Light data +typedef struct { + int type; + Vector3 position; + Vector3 target; + Color color; + bool enabled; + + // Shader locations + int enabledLoc; + int typeLoc; + int posLoc; + int targetLoc; + int colorLoc; +} Light; + +// Light type +typedef enum { + LIGHT_DIRECTIONAL, + LIGHT_POINT +} LightType; + +#ifdef __cplusplus +extern "C" { // Prevents name mangling of functions +#endif + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- +int lightsCount = 0; // Current amount of created lights + +//---------------------------------------------------------------------------------- +// Module Functions Declaration +//---------------------------------------------------------------------------------- +Light CreateLight(int type, Vector3 position, Vector3 target, Color color, Shader shader); // Create a light and get shader locations +void UpdateLightValues(Shader shader, Light light); // Send light properties to shader +//void InitLightLocations(Shader shader, Light *light); // Init light shader locations + +#ifdef __cplusplus +} +#endif + +#endif // RLIGHTS_H + + +/*********************************************************************************** +* +* RLIGHTS IMPLEMENTATION +* +************************************************************************************/ + +#if defined(RLIGHTS_IMPLEMENTATION) + +#include "raylib.h" + +//---------------------------------------------------------------------------------- +// Defines and Macros +//---------------------------------------------------------------------------------- +// ... + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +// ... + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- +// ... + +//---------------------------------------------------------------------------------- +// Module specific Functions Declaration +//---------------------------------------------------------------------------------- +// ... + +//---------------------------------------------------------------------------------- +// Module Functions Definition +//---------------------------------------------------------------------------------- + +// Create a light and get shader locations +Light CreateLight(int type, Vector3 position, Vector3 target, Color color, Shader shader) +{ + Light light = { 0 }; + + if (lightsCount < MAX_LIGHTS) + { + light.enabled = true; + light.type = type; + light.position = position; + light.target = target; + light.color = color; + + // TODO: Below code doesn't look good to me, + // it assumes a specific shader naming and structure + // Probably this implementation could be improved + char enabledName[32] = "lights[x].enabled\0"; + char typeName[32] = "lights[x].type\0"; + char posName[32] = "lights[x].position\0"; + char targetName[32] = "lights[x].target\0"; + char colorName[32] = "lights[x].color\0"; + enabledName[7] = '0' + lightsCount; + typeName[7] = '0' + lightsCount; + posName[7] = '0' + lightsCount; + targetName[7] = '0' + lightsCount; + colorName[7] = '0' + lightsCount; + + light.enabledLoc = GetShaderLocation(shader, enabledName); + light.typeLoc = GetShaderLocation(shader, typeName); + light.posLoc = GetShaderLocation(shader, posName); + light.targetLoc = GetShaderLocation(shader, targetName); + light.colorLoc = GetShaderLocation(shader, colorName); + + UpdateLightValues(shader, light); + + lightsCount++; + } + + return light; +} + +// Send light properties to shader +// NOTE: Light shader locations should be available +void UpdateLightValues(Shader shader, Light light) +{ + // Send to shader light enabled state and type + SetShaderValue(shader, light.enabledLoc, &light.enabled, UNIFORM_INT); + SetShaderValue(shader, light.typeLoc, &light.type, UNIFORM_INT); + + // Send to shader light position values + float position[3] = { light.position.x, light.position.y, light.position.z }; + SetShaderValue(shader, light.posLoc, position, UNIFORM_VEC3); + + // Send to shader light target position values + float target[3] = { light.target.x, light.target.y, light.target.z }; + SetShaderValue(shader, light.targetLoc, target, UNIFORM_VEC3); + + // Send to shader light color values + float color[4] = { (float)light.color.r/(float)255, (float)light.color.g/(float)255, + (float)light.color.b/(float)255, (float)light.color.a/(float)255 }; + SetShaderValue(shader, light.colorLoc, color, UNIFORM_VEC4); +} + +#endif // RLIGHTS_IMPLEMENTATION \ No newline at end of file diff --git a/examples/shaders/shaders_basic_lighting.c b/examples/shaders/shaders_basic_lighting.c new file mode 100644 index 000000000..74bf27759 --- /dev/null +++ b/examples/shaders/shaders_basic_lighting.c @@ -0,0 +1,184 @@ +/******************************************************************************************* +* +* raylib [shaders] example - basic lighting +* +* NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, +* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version. +* +* NOTE: Shaders used in this example are #version 330 (OpenGL 3.3). +* +* This example has been created using raylib 2.5 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Example contributed by Chris Camacho (@codifies) and reviewed by Ramon Santamaria (@raysan5) +* +* Chris Camacho (@codifies - http://bedroomcoders.co.uk/) notes: +* +* This is based on the PBR lighting example, but greatly simplified to aid learning... +* actually there is very little of the PBR example left! +* When I first looked at the bewildering complexity of the PBR example I feared +* I would never understand how I could do simple lighting with raylib however its +* a testement to the authors of raylib (including rlights.h) that the example +* came together fairly quickly. +* +* Copyright (c) 2019 Chris Camacho (@codifies) and Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#include "raymath.h" + +#define RLIGHTS_IMPLEMENTATION +#include "rlights.h" + +#if defined(PLATFORM_DESKTOP) + #define GLSL_VERSION 330 +#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB + #define GLSL_VERSION 100 +#endif + +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + SetConfigFlags(FLAG_MSAA_4X_HINT); // Enable Multi Sampling Anti Aliasing 4x (if available) + InitWindow(screenWidth, screenHeight, "raylib [shaders] example - basic lighting"); + + // Define the camera to look into our 3d world + Camera camera = { 0 }; + camera.position = (Vector3){ 2.0f, 2.0f, 6.0f }; // Camera position + camera.target = (Vector3){ 0.0f, 0.5f, 0.0f }; // Camera looking at point + camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target) + camera.fovy = 45.0f; // Camera field-of-view Y + camera.type = CAMERA_PERSPECTIVE; // Camera mode type + + // Load models + Model modelA = LoadModelFromMesh(GenMeshTorus(0.4f, 1.0f, 16, 32)); + Model modelB = LoadModelFromMesh(GenMeshCube(1.0f, 1.0f, 1.0f)); + Model modelC = LoadModelFromMesh(GenMeshSphere(0.5f, 32, 32)); + + // Load models texture + Texture texture = LoadTexture("resources/texel_checker.png"); + + // Assign texture to default model material + modelA.materials[0].maps[MAP_DIFFUSE].texture = texture; + modelB.materials[0].maps[MAP_DIFFUSE].texture = texture; + modelC.materials[0].maps[MAP_DIFFUSE].texture = texture; + + Shader shader = LoadShader("resources/shaders/glsl330/basic_lighting.vs", + "resources/shaders/glsl330/basic_lighting.fs"); + + // Get some shader loactions + shader.locs[LOC_MATRIX_MODEL] = GetShaderLocation(shader, "matModel"); + shader.locs[LOC_VECTOR_VIEW] = GetShaderLocation(shader, "viewPos"); + + // ambient light level + int ambientLoc = GetShaderLocation(shader, "ambient"); + SetShaderValue(shader, ambientLoc, (float[4]){ 0.2f, 0.2f, 0.2f, 1.0f }, UNIFORM_VEC4); + + float angle = 6.282f; + + // All models use the same shader + modelA.materials[0].shader = shader; + modelB.materials[0].shader = shader; + modelC.materials[0].shader = shader; + + // Using 4 point lights, white, red, green and blue + Light lights[MAX_LIGHTS] = { 0 }; + lights[0] = CreateLight(LIGHT_POINT, (Vector3){ 4, 2, 4 }, Vector3Zero(), WHITE, shader); + lights[1] = CreateLight(LIGHT_POINT, (Vector3){ 4, 2, 4 }, Vector3Zero(), RED, shader); + lights[2] = CreateLight(LIGHT_POINT, (Vector3){ 0, 4, 2 }, Vector3Zero(), GREEN, shader); + lights[3] = CreateLight(LIGHT_POINT, (Vector3){ 0, 4, 2 }, Vector3Zero(), BLUE, shader); + + SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + if (IsKeyPressed(KEY_W)) { lights[0].enabled = !lights[0].enabled; } + if (IsKeyPressed(KEY_R)) { lights[1].enabled = !lights[1].enabled; } + if (IsKeyPressed(KEY_G)) { lights[2].enabled = !lights[2].enabled; } + if (IsKeyPressed(KEY_B)) { lights[3].enabled = !lights[3].enabled; } + + UpdateCamera(&camera); // Update camera + + // Make the lights do differing orbits + angle -= 0.02; + lights[0].position.x = cosf(angle)*4.0f; + lights[0].position.z = sinf(angle)*4.0f; + lights[1].position.x = cosf(-angle*0.6f)*4.0f; + lights[1].position.z = sinf(-angle*0.6f)*4.0f; + lights[2].position.y = cosf(angle*0.2f)*4.0f; + lights[2].position.z = sinf(angle*0.2f)*4.0f; + lights[3].position.y = cosf(-angle*0.35f)*4.0f; + lights[3].position.z = sinf(-angle*0.35f)*4.0f; + + UpdateLightValues(shader, lights[0]); + UpdateLightValues(shader, lights[1]); + UpdateLightValues(shader, lights[2]); + UpdateLightValues(shader, lights[3]); + + // Rotate the torus + modelA.transform = MatrixMultiply(modelA.transform, MatrixRotateX(-0.025)); + modelA.transform = MatrixMultiply(modelA.transform, MatrixRotateZ(0.012)); + + // Update the light shader with the camera view position + float cameraPos[3] = { camera.position.x, camera.position.y, camera.position.z }; + SetShaderValue(shader, shader.locs[LOC_VECTOR_VIEW], cameraPos, UNIFORM_VEC3); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + BeginMode3D(camera); + + // Draw the three models + DrawModel(modelA, Vector3Zero(), 1.0f, WHITE); + DrawModel(modelB, (Vector3){-1.6,0,0}, 1.0f, WHITE); + DrawModel(modelC, (Vector3){ 1.6,0,0}, 1.0f, WHITE); + + // Draw markers to show where the lights are + if (lights[0].enabled) { DrawSphereEx(lights[0].position, 0.2f, 8, 8, WHITE); } + if (lights[1].enabled) { DrawSphereEx(lights[1].position, 0.2f, 8, 8, RED); } + if (lights[2].enabled) { DrawSphereEx(lights[2].position, 0.2f, 8, 8, GREEN); } + if (lights[3].enabled) { DrawSphereEx(lights[3].position, 0.2f, 8, 8, BLUE); } + + DrawGrid(10, 1.0f); + + EndMode3D(); + + DrawFPS(10, 10); + + DrawText("Keys RGB & W toggle lights", 10, 30, 20, DARKGRAY); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadModel(modelA); // Unload the modelA + UnloadModel(modelB); // Unload the modelB + UnloadModel(modelC); // Unload the modelC + + UnloadTexture(texture); // Unload the texture + UnloadShader(shader); // Unload shader + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + diff --git a/examples/shaders/shaders_basic_lighting.png b/examples/shaders/shaders_basic_lighting.png new file mode 100644 index 000000000..bae869a90 Binary files /dev/null and b/examples/shaders/shaders_basic_lighting.png differ diff --git a/examples/shaders/shaders_custom_uniform.c b/examples/shaders/shaders_custom_uniform.c index 74b9e7714..1c82bba2e 100644 --- a/examples/shaders/shaders_custom_uniform.c +++ b/examples/shaders/shaders_custom_uniform.c @@ -24,13 +24,13 @@ #define GLSL_VERSION 100 #endif -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; - + const int screenWidth = 800; + const int screenHeight = 450; + SetConfigFlags(FLAG_MSAA_4X_HINT); // Enable Multi Sampling Anti Aliasing 4x (if available) InitWindow(screenWidth, screenHeight, "raylib [shaders] example - custom uniform variable"); @@ -48,20 +48,20 @@ int main() model.materials[0].maps[MAP_DIFFUSE].texture = texture; // Set model diffuse texture Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position - + // Load postprocessing shader // NOTE: Defining 0 (NULL) for vertex shader forces usage of internal default vertex shader Shader shader = LoadShader(0, FormatText("resources/shaders/glsl%i/swirl.fs", GLSL_VERSION)); - + // Get variable (uniform) location on the shader to connect with the program // NOTE: If uniform variable could not be found in the shader, function returns -1 int swirlCenterLoc = GetShaderLocation(shader, "center"); - + float swirlCenter[2] = { (float)screenWidth/2, (float)screenHeight/2 }; - + // Create a RenderTexture2D to be used for render to texture RenderTexture2D target = LoadRenderTexture(screenWidth, screenHeight); - + // Setup orbital camera SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode @@ -80,7 +80,7 @@ int main() // Send new value to the shader to be used on drawing SetShaderValue(shader, swirlCenterLoc, swirlCenter, UNIFORM_VEC2); - + UpdateCamera(&camera); // Update camera //---------------------------------------------------------------------------------- @@ -89,9 +89,9 @@ int main() BeginDrawing(); ClearBackground(RAYWHITE); - + BeginTextureMode(target); // Enable drawing to texture - + ClearBackground(RAYWHITE); // Clear texture background BeginMode3D(camera); // Begin 3d mode drawing @@ -101,21 +101,21 @@ int main() DrawGrid(10, 1.0f); // Draw a grid EndMode3D(); // End 3d mode drawing, returns to orthographic 2d mode - + DrawText("TEXT DRAWN IN RENDER TEXTURE", 200, 10, 30, RED); - + EndTextureMode(); // End drawing to texture (now we have a texture available for next passes) - + BeginShaderMode(shader); - + // NOTE: Render texture must be y-flipped due to default OpenGL coordinates (left-bottom) DrawTextureRec(target.texture, (Rectangle){ 0, 0, target.texture.width, -target.texture.height }, (Vector2){ 0, 0 }, WHITE); - + EndShaderMode(); - + // Draw some 2d text over drawn texture DrawText("(c) Barracks 3D model by Alberto Cano", screenWidth - 220, screenHeight - 20, 10, GRAY); - + DrawFPS(10, 10); EndDrawing(); diff --git a/examples/shaders/shaders_eratosthenes.c b/examples/shaders/shaders_eratosthenes.c new file mode 100644 index 000000000..068fc26c2 --- /dev/null +++ b/examples/shaders/shaders_eratosthenes.c @@ -0,0 +1,94 @@ +/******************************************************************************************* +* +* raylib [shaders] example - Sieve of Eratosthenes +* +* Sieve of Eratosthenes, the earliest known (ancient Greek) prime number sieve. +* +* "Sift the twos and sift the threes, +* The Sieve of Eratosthenes. +* When the multiples sublime, +* the numbers that are left are prime." +* +* NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, +* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version. +* +* NOTE: Shaders used in this example are #version 330 (OpenGL 3.3). +* +* This example has been created using raylib 2.5 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Example contributed by ProfJski and reviewed by Ramon Santamaria (@raysan5) +* +* Copyright (c) 2019 ProfJski and Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#if defined(PLATFORM_DESKTOP) + #define GLSL_VERSION 330 +#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB + #define GLSL_VERSION 100 +#endif + +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [shaders] example - Sieve of Eratosthenes"); + + RenderTexture2D target = LoadRenderTexture(screenWidth, screenHeight); + + // Load Eratosthenes shader + // NOTE: Defining 0 (NULL) for vertex shader forces usage of internal default vertex shader + Shader shader = LoadShader(0, FormatText("resources/shaders/glsl%i/eratosthenes.fs", GLSL_VERSION)); + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + // Nothing to do here, everything is happening in the shader + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + BeginTextureMode(target); // Enable drawing to texture + ClearBackground(BLACK); // Clear the render texture + + // Draw a rectangle in shader mode to be used as shader canvas + // NOTE: Rectangle uses font white character texture coordinates, + // so shader can not be applied here directly because input vertexTexCoord + // do not represent full screen coordinates (space where want to apply shader) + DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), BLACK); + EndTextureMode(); // End drawing to texture (now we have a blank texture available for the shader) + + BeginShaderMode(shader); + // NOTE: Render texture must be y-flipped due to default OpenGL coordinates (left-bottom) + DrawTextureRec(target.texture, (Rectangle){ 0, 0, target.texture.width, -target.texture.height }, (Vector2){ 0.0f, 0.0f }, WHITE); + EndShaderMode(); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadShader(shader); // Unload shader + UnloadRenderTexture(target); // Unload texture + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} diff --git a/examples/shaders/shaders_eratosthenes.png b/examples/shaders/shaders_eratosthenes.png new file mode 100644 index 000000000..acd7fc75f Binary files /dev/null and b/examples/shaders/shaders_eratosthenes.png differ diff --git a/examples/shaders/shaders_fog.c b/examples/shaders/shaders_fog.c new file mode 100644 index 000000000..e8f2691d2 --- /dev/null +++ b/examples/shaders/shaders_fog.c @@ -0,0 +1,153 @@ +/******************************************************************************************* +* +* raylib [shaders] example - fog +* +* NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, +* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version. +* +* NOTE: Shaders used in this example are #version 330 (OpenGL 3.3). +* +* This example has been created using raylib 2.5 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Example contributed by Chris Camacho (@codifies) and reviewed by Ramon Santamaria (@raysan5) +* +* Chris Camacho (@codifies - http://bedroomcoders.co.uk/) notes: +* +* This is based on the PBR lighting example, but greatly simplified to aid learning... +* actually there is very little of the PBR example left! +* When I first looked at the bewildering complexity of the PBR example I feared +* I would never understand how I could do simple lighting with raylib however its +* a testement to the authors of raylib (including rlights.h) that the example +* came together fairly quickly. +* +* Copyright (c) 2019 Chris Camacho (@codifies) and Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#include "raymath.h" + +#define RLIGHTS_IMPLEMENTATION +#include "rlights.h" + +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + SetConfigFlags(FLAG_MSAA_4X_HINT); // Enable Multi Sampling Anti Aliasing 4x (if available) + InitWindow(screenWidth, screenHeight, "raylib [shaders] example - fog"); + + // Define the camera to look into our 3d world + Camera camera = { + (Vector3){ 2.0f, 2.0f, 6.0f }, // position + (Vector3){ 0.0f, 0.5f, 0.0f }, // target + (Vector3){ 0.0f, 1.0f, 0.0f }, // up + 45.0f, CAMERA_PERSPECTIVE }; // fov, type + + // Load models and texture + Model modelA = LoadModelFromMesh(GenMeshTorus(0.4f, 1.0f, 16, 32)); + Model modelB = LoadModelFromMesh(GenMeshCube(1.0f, 1.0f, 1.0f)); + Model modelC = LoadModelFromMesh(GenMeshSphere(0.5f, 32, 32)); + Texture texture = LoadTexture("resources/texel_checker.png"); + + // Assign texture to default model material + modelA.materials[0].maps[MAP_DIFFUSE].texture = texture; + modelB.materials[0].maps[MAP_DIFFUSE].texture = texture; + modelC.materials[0].maps[MAP_DIFFUSE].texture = texture; + + // Load shader and set up some uniforms + Shader shader = LoadShader("resources/shaders/glsl330/fog.vs", "resources/shaders/glsl330/fog.fs"); + shader.locs[LOC_MATRIX_MODEL] = GetShaderLocation(shader, "matModel"); + shader.locs[LOC_VECTOR_VIEW] = GetShaderLocation(shader, "viewPos"); + + // Ambient light level + int ambientLoc = GetShaderLocation(shader, "ambient"); + SetShaderValue(shader, ambientLoc, (float[4]){ 0.2f, 0.2f, 0.2f, 1.0f }, UNIFORM_VEC4); + + float fogDensity = 0.15f; + int fogDensityLoc = GetShaderLocation(shader, "fogDensity"); + SetShaderValue(shader, fogDensityLoc, &fogDensity, UNIFORM_FLOAT); + + // NOTE: All models share the same shader + modelA.materials[0].shader = shader; + modelB.materials[0].shader = shader; + modelC.materials[0].shader = shader; + + // Using just 1 point lights + CreateLight(LIGHT_POINT, (Vector3){ 0, 2, 6 }, Vector3Zero(), WHITE, shader); + + SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + UpdateCamera(&camera); // Update camera + + if (IsKeyDown(KEY_UP)) + { + fogDensity += 0.001; + if (fogDensity > 1.0) fogDensity = 1.0; + } + + if (IsKeyDown(KEY_DOWN)) + { + fogDensity -= 0.001; + if (fogDensity < 0.0) fogDensity = 0.0; + } + + SetShaderValue(shader, fogDensityLoc, &fogDensity, UNIFORM_FLOAT); + + // Rotate the torus + modelA.transform = MatrixMultiply(modelA.transform, MatrixRotateX(-0.025)); + modelA.transform = MatrixMultiply(modelA.transform, MatrixRotateZ(0.012)); + + // Update the light shader with the camera view position + SetShaderValue(shader, shader.locs[LOC_VECTOR_VIEW], &camera.position.x, UNIFORM_VEC3); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(GRAY); + + BeginMode3D(camera); + + // Draw the three models + DrawModel(modelA, Vector3Zero(), 1.0f, WHITE); + DrawModel(modelB, (Vector3){ -2.6, 0, 0 }, 1.0f, WHITE); + DrawModel(modelC, (Vector3){ 2.6, 0, 0 }, 1.0f, WHITE); + + for (int i = -20; i < 20; i += 2) DrawModel(modelA,(Vector3){ i, 0, 2 }, 1.0f, WHITE); + + EndMode3D(); + + DrawText(TextFormat("Use KEY_UP/KEY_DOWN to change fog density [%.2f]", fogDensity), 10, 10, 20, RAYWHITE); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadModel(modelA); // Unload the model A + UnloadModel(modelB); // Unload the model B + UnloadModel(modelC); // Unload the model C + UnloadTexture(texture); // Unload the texture + UnloadShader(shader); // Unload shader + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} diff --git a/examples/shaders/shaders_fog.png b/examples/shaders/shaders_fog.png new file mode 100644 index 000000000..52008e8a1 Binary files /dev/null and b/examples/shaders/shaders_fog.png differ diff --git a/examples/shaders/shaders_julia_set.c b/examples/shaders/shaders_julia_set.c new file mode 100644 index 000000000..e64b622be --- /dev/null +++ b/examples/shaders/shaders_julia_set.c @@ -0,0 +1,190 @@ +/******************************************************************************************* +* +* raylib [shaders] example - julia sets +* +* NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, +* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version. +* +* NOTE: Shaders used in this example are #version 330 (OpenGL 3.3). +* +* This example has been created using raylib 2.5 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Example contributed by eggmund (@eggmund) and reviewed by Ramon Santamaria (@raysan5) +* +* Copyright (c) 2019 eggmund (@eggmund) and Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#if defined(PLATFORM_DESKTOP) + #define GLSL_VERSION 330 +#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB + #define GLSL_VERSION 100 +#endif + +// A few good julia sets +const float POINTS_OF_INTEREST[6][2] = +{ + { -0.348827, 0.607167 }, + { -0.786268, 0.169728 }, + { -0.8, 0.156 }, + { 0.285, 0.0 }, + { -0.835, -0.2321 }, + { -0.70176, -0.3842 }, +}; + +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [shaders] example - julia sets"); + + // Load julia set shader + // NOTE: Defining 0 (NULL) for vertex shader forces usage of internal default vertex shader + Shader shader = LoadShader(0, FormatText("resources/shaders/glsl%i/julia_set.fs", GLSL_VERSION)); + + // c constant to use in z^2 + c + float c[2] = { POINTS_OF_INTEREST[0][0], POINTS_OF_INTEREST[0][1] }; + + // Offset and zoom to draw the julia set at. (centered on screen and default size) + float offset[2] = { -(float)screenWidth/2, -(float)screenHeight/2 }; + float zoom = 1.0f; + + Vector2 offsetSpeed = { 0.0f, 0.0f }; + + // Get variable (uniform) locations on the shader to connect with the program + // NOTE: If uniform variable could not be found in the shader, function returns -1 + int cLoc = GetShaderLocation(shader, "c"); + int zoomLoc = GetShaderLocation(shader, "zoom"); + int offsetLoc = GetShaderLocation(shader, "offset"); + + // Tell the shader what the screen dimensions, zoom, offset and c are + float screenDims[2] = { (float)screenWidth, (float)screenHeight }; + SetShaderValue(shader, GetShaderLocation(shader, "screenDims"), screenDims, UNIFORM_VEC2); + + SetShaderValue(shader, cLoc, c, UNIFORM_VEC2); + SetShaderValue(shader, zoomLoc, &zoom, UNIFORM_FLOAT); + SetShaderValue(shader, offsetLoc, offset, UNIFORM_VEC2); + + // Create a RenderTexture2D to be used for render to texture + RenderTexture2D target = LoadRenderTexture(screenWidth, screenHeight); + + int incrementSpeed = 0; // Multiplier of speed to change c value + bool showControls = true; // Show controls + bool pause = false; // Pause animation + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + // Press [1 - 6] to reset c to a point of interest + if (IsKeyPressed(KEY_ONE) || + IsKeyPressed(KEY_TWO) || + IsKeyPressed(KEY_THREE) || + IsKeyPressed(KEY_FOUR) || + IsKeyPressed(KEY_FIVE) || + IsKeyPressed(KEY_SIX)) + { + if (IsKeyPressed(KEY_ONE)) c[0] = POINTS_OF_INTEREST[0][0], c[1] = POINTS_OF_INTEREST[0][1]; + else if (IsKeyPressed(KEY_TWO)) c[0] = POINTS_OF_INTEREST[1][0], c[1] = POINTS_OF_INTEREST[1][1]; + else if (IsKeyPressed(KEY_THREE)) c[0] = POINTS_OF_INTEREST[2][0], c[1] = POINTS_OF_INTEREST[2][1]; + else if (IsKeyPressed(KEY_FOUR)) c[0] = POINTS_OF_INTEREST[3][0], c[1] = POINTS_OF_INTEREST[3][1]; + else if (IsKeyPressed(KEY_FIVE)) c[0] = POINTS_OF_INTEREST[4][0], c[1] = POINTS_OF_INTEREST[4][1]; + else if (IsKeyPressed(KEY_SIX)) c[0] = POINTS_OF_INTEREST[5][0], c[1] = POINTS_OF_INTEREST[5][1]; + + SetShaderValue(shader, cLoc, c, UNIFORM_VEC2); + } + + if (IsKeyPressed(KEY_SPACE)) pause = !pause; // Pause animation (c change) + if (IsKeyPressed(KEY_F1)) showControls = !showControls; // Toggle whether or not to show controls + + if (!pause) + { + if (IsKeyPressed(KEY_RIGHT)) incrementSpeed++; + else if (IsKeyPressed(KEY_LEFT)) incrementSpeed--; + + // TODO: The idea is to zoom and move around with mouse + // Probably offset movement should be proportional to zoom level + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON) || IsMouseButtonDown(MOUSE_RIGHT_BUTTON)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) zoom += zoom*0.003f; + if (IsMouseButtonDown(MOUSE_RIGHT_BUTTON)) zoom -= zoom*0.003f; + + Vector2 mousePos = GetMousePosition(); + + offsetSpeed.x = mousePos.x -(float)screenWidth/2; + offsetSpeed.y = mousePos.y -(float)screenHeight/2; + + // Slowly move camera to targetOffset + offset[0] += GetFrameTime()*offsetSpeed.x*0.8f; + offset[1] += GetFrameTime()*offsetSpeed.y*0.8f; + } + else offsetSpeed = (Vector2){ 0.0f, 0.0f }; + + SetShaderValue(shader, zoomLoc, &zoom, UNIFORM_FLOAT); + SetShaderValue(shader, offsetLoc, offset, UNIFORM_VEC2); + + // Increment c value with time + float amount = GetFrameTime()*incrementSpeed*0.0005f; + c[0] += amount; + c[1] += amount; + + SetShaderValue(shader, cLoc, c, UNIFORM_VEC2); + } + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(BLACK); // Clear the screen of the previous frame. + + // Using a render texture to draw Julia set + BeginTextureMode(target); // Enable drawing to texture + ClearBackground(BLACK); // Clear the render texture + + // Draw a rectangle in shader mode to be used as shader canvas + // NOTE: Rectangle uses font white character texture coordinates, + // so shader can not be applied here directly because input vertexTexCoord + // do not represent full screen coordinates (space where want to apply shader) + DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), BLACK); + EndTextureMode(); + + // Draw the saved texture and rendered julia set with shader + // NOTE: We do not invert texture on Y, already considered inside shader + BeginShaderMode(shader); + DrawTexture(target.texture, 0, 0, WHITE); + EndShaderMode(); + + if (showControls) + { + DrawText("Press Mouse buttons right/left to zoom in/out and move", 10, 15, 10, RAYWHITE); + DrawText("Press KEY_F1 to toggle these controls", 10, 30, 10, RAYWHITE); + DrawText("Press KEYS [1 - 6] to change point of interest", 10, 45, 10, RAYWHITE); + DrawText("Press KEY_LEFT | KEY_RIGHT to change speed", 10, 60, 10, RAYWHITE); + DrawText("Press KEY_SPACE to pause movement animation", 10, 75, 10, RAYWHITE); + } + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadShader(shader); // Unload shader + UnloadRenderTexture(target); // Unload render texture + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} diff --git a/examples/shaders/shaders_julia_set.png b/examples/shaders/shaders_julia_set.png new file mode 100644 index 000000000..b769c3f66 Binary files /dev/null and b/examples/shaders/shaders_julia_set.png differ diff --git a/examples/shaders/shaders_model_shader.c b/examples/shaders/shaders_model_shader.c index 2717c1927..8224a3373 100644 --- a/examples/shaders/shaders_model_shader.c +++ b/examples/shaders/shaders_model_shader.c @@ -24,13 +24,13 @@ #define GLSL_VERSION 100 #endif -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; - + const int screenWidth = 800; + const int screenHeight = 450; + SetConfigFlags(FLAG_MSAA_4X_HINT); // Enable Multi Sampling Anti Aliasing 4x (if available) InitWindow(screenWidth, screenHeight, "raylib [shaders] example - model shader"); @@ -45,16 +45,16 @@ int main() Model model = LoadModel("resources/models/watermill.obj"); // Load OBJ model Texture2D texture = LoadTexture("resources/models/watermill_diffuse.png"); // Load model texture - + // Load shader for model // NOTE: Defining 0 (NULL) for vertex shader forces usage of internal default vertex shader Shader shader = LoadShader(0, FormatText("resources/shaders/glsl%i/grayscale.fs", GLSL_VERSION)); model.materials[0].shader = shader; // Set shader effect to 3d model model.materials[0].maps[MAP_DIFFUSE].texture = texture; // Bind texture to model - + Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position - + SetCameraMode(camera, CAMERA_FREE); // Set an orbital camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second @@ -81,11 +81,8 @@ int main() DrawGrid(10, 1.0f); // Draw a grid EndMode3D(); - + DrawText("(c) Watermill 3D model by Alberto Cano", screenWidth - 210, screenHeight - 20, 10, GRAY); - - DrawText(FormatText("Camera position: (%.2f, %.2f, %.2f)", camera.position.x, camera.position.y, camera.position.z), 600, 20, 10, BLACK); - DrawText(FormatText("Camera target: (%.2f, %.2f, %.2f)", camera.target.x, camera.target.y, camera.target.z), 600, 40, 10, GRAY); DrawFPS(10, 10); diff --git a/examples/shaders/shaders_palette_switch.c b/examples/shaders/shaders_palette_switch.c index a2fa0b278..6bc27827a 100644 --- a/examples/shaders/shaders_palette_switch.c +++ b/examples/shaders/shaders_palette_switch.c @@ -12,7 +12,9 @@ * This example has been created using raylib 2.3 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * -* Copyright (c) 2019 Ramon Santamaria (@raysan5) +* Example contributed by Marco Lizza (@MarcoLizza) and reviewed by Ramon Santamaria (@raysan5) +* +* Copyright (c) 2019 Marco Lizza (@MarcoLizza) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ @@ -67,19 +69,19 @@ static const char *paletteText[] = { "RKBV (2-strip film)" }; -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [shaders] example - color palette switch"); // Load shader to be used on some parts drawing // NOTE 1: Using GLSL 330 shader version, on OpenGL ES 2.0 use GLSL 100 shader version // NOTE 2: Defining 0 (NULL) for vertex shader forces usage of internal default vertex shader - Shader shader = LoadShader(0, FormatText("resources/shaders/glsl%i/palette-switch.fs", GLSL_VERSION)); + Shader shader = LoadShader(0, FormatText("resources/shaders/glsl%i/palette_switch.fs", GLSL_VERSION)); // Get variable (uniform) location on the shader to connect with the program // NOTE: If uniform variable could not be found in the shader, function returns -1 @@ -115,7 +117,7 @@ int main() BeginShaderMode(shader); - for (int i = 0; i < COLORS_PER_PALETTE; i++) + for (int i = 0; i < COLORS_PER_PALETTE; i++) { // Draw horizontal screen-wide rectangles with increasing "palette index" // The used palette index is encoded in the RGB components of the pixel @@ -127,7 +129,7 @@ int main() DrawText("< >", 10, 10, 30, DARKBLUE); DrawText("CURRENT PALETTE:", 60, 15, 20, RAYWHITE); DrawText(paletteText[currentPalette], 300, 15, 20, RED); - + DrawFPS(700, 15); EndDrawing(); diff --git a/examples/shaders/shaders_palette_switch.png b/examples/shaders/shaders_palette_switch.png new file mode 100644 index 000000000..7eb3eaf39 Binary files /dev/null and b/examples/shaders/shaders_palette_switch.png differ diff --git a/examples/shaders/shaders_postprocessing.c b/examples/shaders/shaders_postprocessing.c index 7c1464193..ed9da8bb5 100644 --- a/examples/shaders/shaders_postprocessing.c +++ b/examples/shaders/shaders_postprocessing.c @@ -58,31 +58,31 @@ static const char *postproShaderText[] = { //"FXAA" }; -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; - + const int screenWidth = 800; + const int screenHeight = 450; + SetConfigFlags(FLAG_MSAA_4X_HINT); // Enable Multi Sampling Anti Aliasing 4x (if available) InitWindow(screenWidth, screenHeight, "raylib [shaders] example - postprocessing shader"); // Define the camera to look into our 3d world - Camera camera = {{ 2.0f, 3.0f, 2.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 }; - + Camera camera = { { 2.0f, 3.0f, 2.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 }; + Model model = LoadModel("resources/models/church.obj"); // Load OBJ model Texture2D texture = LoadTexture("resources/models/church_diffuse.png"); // Load model texture (diffuse map) model.materials[0].maps[MAP_DIFFUSE].texture = texture; // Set model diffuse texture Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position - + // Load all postpro shaders // NOTE 1: All postpro shader use the base vertex shader (DEFAULT_VERTEX_SHADER) // NOTE 2: We load the correct shader depending on GLSL version - Shader shaders[MAX_POSTPRO_SHADERS]; - + Shader shaders[MAX_POSTPRO_SHADERS] = { 0 }; + // NOTE: Defining 0 (NULL) for vertex shader forces usage of internal default vertex shader shaders[FX_GRAYSCALE] = LoadShader(0, FormatText("resources/shaders/glsl%i/grayscale.fs", GLSL_VERSION)); shaders[FX_POSTERIZATION] = LoadShader(0, FormatText("resources/shaders/glsl%i/posterization.fs", GLSL_VERSION)); @@ -96,12 +96,12 @@ int main() shaders[FX_SOBEL] = LoadShader(0, FormatText("resources/shaders/glsl%i/sobel.fs", GLSL_VERSION)); shaders[FX_BLOOM] = LoadShader(0, FormatText("resources/shaders/glsl%i/bloom.fs", GLSL_VERSION)); shaders[FX_BLUR] = LoadShader(0, FormatText("resources/shaders/glsl%i/blur.fs", GLSL_VERSION)); - + int currentShader = FX_GRAYSCALE; // Create a RenderTexture2D to be used for render to texture RenderTexture2D target = LoadRenderTexture(screenWidth, screenHeight); - + // Setup orbital camera SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode @@ -114,10 +114,10 @@ int main() // Update //---------------------------------------------------------------------------------- UpdateCamera(&camera); // Update camera - + if (IsKeyPressed(KEY_RIGHT)) currentShader++; else if (IsKeyPressed(KEY_LEFT)) currentShader--; - + if (currentShader >= MAX_POSTPRO_SHADERS) currentShader = 0; else if (currentShader < 0) currentShader = MAX_POSTPRO_SHADERS - 1; //---------------------------------------------------------------------------------- @@ -129,7 +129,7 @@ int main() ClearBackground(RAYWHITE); BeginTextureMode(target); // Enable drawing to texture - + ClearBackground(RAYWHITE); // Clear texture background BeginMode3D(camera); // Begin 3d mode drawing @@ -139,26 +139,26 @@ int main() DrawGrid(10, 1.0f); // Draw a grid EndMode3D(); // End 3d mode drawing, returns to orthographic 2d mode - + EndTextureMode(); // End drawing to texture (now we have a texture available for next passes) - + // Render previously generated texture using selected postpro shader BeginShaderMode(shaders[currentShader]); - + // NOTE: Render texture must be y-flipped due to default OpenGL coordinates (left-bottom) DrawTextureRec(target.texture, (Rectangle){ 0, 0, target.texture.width, -target.texture.height }, (Vector2){ 0, 0 }, WHITE); - + EndShaderMode(); - + // Draw 2d shapes and text over drawn texture DrawRectangle(0, 9, 580, 30, Fade(LIGHTGRAY, 0.7f)); - + DrawText("(c) Church 3D model by Alberto Cano", screenWidth - 200, screenHeight - 20, 10, GRAY); - + DrawText("CURRENT POSTPRO SHADER:", 10, 15, 20, BLACK); DrawText(postproShaderText[currentShader], 330, 15, 20, RED); DrawText("< >", 540, 10, 30, DARKBLUE); - + DrawFPS(700, 15); EndDrawing(); @@ -167,10 +167,10 @@ int main() // De-Initialization //-------------------------------------------------------------------------------------- - + // Unload all postpro shaders for (int i = 0; i < MAX_POSTPRO_SHADERS; i++) UnloadShader(shaders[i]); - + UnloadTexture(texture); // Unload texture UnloadModel(model); // Unload model UnloadRenderTexture(target); // Unload render texture diff --git a/examples/shaders/shaders_raymarching.c b/examples/shaders/shaders_raymarching.c index e5c58a1d2..06ad0f92e 100644 --- a/examples/shaders/shaders_raymarching.c +++ b/examples/shaders/shaders_raymarching.c @@ -18,13 +18,20 @@ #include "raylib.h" -int main() +#if defined(PLATFORM_DESKTOP) + #define GLSL_VERSION 330 +#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB + #define GLSL_VERSION 100 +#endif + +int main(void) { // Initialization //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; - + + SetConfigFlags(FLAG_WINDOW_RESIZABLE); InitWindow(screenWidth, screenHeight, "raylib [shaders] example - raymarching shapes"); Camera camera = { 0 }; @@ -37,17 +44,15 @@ int main() // Load raymarching shader // NOTE: Defining 0 (NULL) for vertex shader forces usage of internal default vertex shader - Shader shader = LoadShader(0, "resources/shaders/glsl330/raymarching.fs"); - + Shader shader = LoadShader(0, FormatText("resources/shaders/glsl%i/raymarching.fs", GLSL_VERSION)); + // Get shader locations for required uniforms int viewEyeLoc = GetShaderLocation(shader, "viewEye"); int viewCenterLoc = GetShaderLocation(shader, "viewCenter"); - int viewUpLoc = GetShaderLocation(shader, "viewUp"); - int deltaTimeLoc = GetShaderLocation(shader, "deltaTime"); int runTimeLoc = GetShaderLocation(shader, "runTime"); int resolutionLoc = GetShaderLocation(shader, "resolution"); - float resolution[2] = { screenWidth, screenHeight }; + float resolution[2] = { (float)screenWidth, (float)screenHeight }; SetShaderValue(shader, resolutionLoc, resolution, UNIFORM_VEC2); float runTime = 0.0f; @@ -58,22 +63,29 @@ int main() // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { + // Check if screen is resized + //---------------------------------------------------------------------------------- + if(IsWindowResized()) + { + screenWidth = GetScreenWidth(); + screenHeight = GetScreenHeight(); + float resolution[2] = { (float)screenWidth, (float)screenHeight }; + SetShaderValue(shader, resolutionLoc, resolution, UNIFORM_VEC2); + } + // Update //---------------------------------------------------------------------------------- UpdateCamera(&camera); // Update camera float cameraPos[3] = { camera.position.x, camera.position.y, camera.position.z }; float cameraTarget[3] = { camera.target.x, camera.target.y, camera.target.z }; - float cameraUp[3] = { camera.up.x, camera.up.y, camera.up.z }; - float deltaTime = GetFrameTime(); + float deltaTime = GetFrameTime(); runTime += deltaTime; // Set shader required uniform values SetShaderValue(shader, viewEyeLoc, cameraPos, UNIFORM_VEC3); SetShaderValue(shader, viewCenterLoc, cameraTarget, UNIFORM_VEC3); - SetShaderValue(shader, viewUpLoc, cameraUp, UNIFORM_VEC3); - SetShaderValue(shader, deltaTimeLoc, &deltaTime, UNIFORM_FLOAT); SetShaderValue(shader, runTimeLoc, &runTime, UNIFORM_FLOAT); //---------------------------------------------------------------------------------- @@ -89,7 +101,7 @@ int main() DrawRectangle(0, 0, screenWidth, screenHeight, WHITE); EndShaderMode(); - DrawText("(c) Raymarching shader by Iñigo Quilez. MIT License.", screenWidth - 280, screenHeight - 20, 10, GRAY); + DrawText("(c) Raymarching shader by Iñigo Quilez. MIT License.", screenWidth - 280, screenHeight - 20, 10, BLACK); EndDrawing(); //---------------------------------------------------------------------------------- @@ -103,4 +115,4 @@ int main() //-------------------------------------------------------------------------------------- return 0; -} \ No newline at end of file +} diff --git a/examples/shaders/shaders_shapes_textures.c b/examples/shaders/shaders_shapes_textures.c index 5ee5d5605..cf53bf99c 100644 --- a/examples/shaders/shaders_shapes_textures.c +++ b/examples/shaders/shaders_shapes_textures.c @@ -24,23 +24,23 @@ #define GLSL_VERSION 100 #endif -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [shaders] example - shapes and texture shaders"); - + Texture2D fudesumi = LoadTexture("resources/fudesumi.png"); // Load shader to be used on some parts drawing - // NOTE 1: Using GLSL 330 shader version, on OpenGL ES 2.0 use GLSL 100 shader version + // NOTE 1: Using GLSL 330 shader version, on OpenGL ES 2.0 use GLSL 100 shader version // NOTE 2: Defining 0 (NULL) for vertex shader forces usage of internal default vertex shader Shader shader = LoadShader(0, FormatText("resources/shaders/glsl%i/grayscale.fs", GLSL_VERSION)); - SetTargetFPS(60); + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop @@ -56,19 +56,19 @@ int main() BeginDrawing(); ClearBackground(RAYWHITE); - + // Start drawing with default shader DrawText("USING DEFAULT SHADER", 20, 40, 10, RED); - + DrawCircle(80, 120, 35, DARKBLUE); DrawCircleGradient(80, 220, 60, GREEN, SKYBLUE); DrawCircleLines(80, 340, 80, DARKBLUE); - + // Activate our custom shader to be applied on next shapes/textures drawings BeginShaderMode(shader); - + DrawText("USING CUSTOM SHADER", 190, 40, 10, RED); DrawRectangle(250 - 60, 90, 120, 60, RED); @@ -77,29 +77,29 @@ int main() // Activate our default shader for next drawings EndShaderMode(); - + DrawText("USING DEFAULT SHADER", 370, 40, 10, RED); - + DrawTriangle((Vector2){430, 80}, (Vector2){430 - 60, 150}, (Vector2){430 + 60, 150}, VIOLET); - + DrawTriangleLines((Vector2){430, 160}, (Vector2){430 - 20, 230}, (Vector2){430 + 20, 230}, DARKBLUE); DrawPoly((Vector2){430, 320}, 6, 80, 0, BROWN); - + // Activate our custom shader to be applied on next shapes/textures drawings BeginShaderMode(shader); DrawTexture(fudesumi, 500, -30, WHITE); // Using custom shader - + // Activate our default shader for next drawings EndShaderMode(); - + DrawText("(c) Fudesumi sprite by Eiden Marsal", 380, screenHeight - 20, 10, GRAY); - + EndDrawing(); //---------------------------------------------------------------------------------- } @@ -108,7 +108,7 @@ int main() //-------------------------------------------------------------------------------------- UnloadShader(shader); // Unload shader UnloadTexture(fudesumi); // Unload texture - + CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/shaders/shaders_simple_mask.c b/examples/shaders/shaders_simple_mask.c new file mode 100644 index 000000000..c8762be3a --- /dev/null +++ b/examples/shaders/shaders_simple_mask.c @@ -0,0 +1,139 @@ +/******************************************************************************************* +* +* raylib [shaders] example - Simple shader mask +* +* This example has been created using raylib 2.5 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Example contributed by Chris Camacho (@codifies) and reviewed by Ramon Santamaria (@raysan5) +* +* Copyright (c) 2019 Chris Camacho (@codifies) and Ramon Santamaria (@raysan5) +* +******************************************************************************************** +* +* After a model is loaded it has a default material, this material can be +* modified in place rather than creating one from scratch... +* While all of the maps have particular names, they can be used for any purpose +* except for three maps that are applied as cubic maps (see below) +* +********************************************************************************************/ + +#include "raylib.h" +#include "raymath.h" + +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib - simple shader mask"); + + // Define the camera to look into our 3d world + Camera camera = { 0 }; + camera.position = (Vector3){ 0.0f, 1.0f, 2.0f }; + camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; + camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; + camera.fovy = 45.0f; + camera.type = CAMERA_PERSPECTIVE; + + // Define our three models to show the shader on + Mesh torus = GenMeshTorus(.3, 1, 16, 32); + Model model1 = LoadModelFromMesh(torus); + + Mesh cube = GenMeshCube(.8,.8,.8); + Model model2 = LoadModelFromMesh(cube); + + // Generate model to be shaded just to see the gaps in the other two + Mesh sphere = GenMeshSphere(1, 16, 16); + Model model3 = LoadModelFromMesh(sphere); + + // Load the shader + Shader shader = LoadShader("resources/shaders/glsl330/mask.vs", "resources/shaders/glsl330/mask.fs"); + + // Load and apply the diffuse texture (colour map) + Texture texDiffuse = LoadTexture("resources/plasma.png"); + model1.materials[0].maps[MAP_DIFFUSE].texture = texDiffuse; + model2.materials[0].maps[MAP_DIFFUSE].texture = texDiffuse; + + // Using MAP_EMISSION as a spare slot to use for 2nd texture + // NOTE: Don't use MAP_IRRADIANCE, MAP_PREFILTER or MAP_CUBEMAP + // as they are bound as cube maps + Texture texMask = LoadTexture("resources/mask.png"); + model1.materials[0].maps[MAP_EMISSION].texture = texMask; + model2.materials[0].maps[MAP_EMISSION].texture = texMask; + shader.locs[LOC_MAP_EMISSION] = GetShaderLocation(shader, "mask"); + + // Frame is incremented each frame to animate the shader + int shaderFrame = GetShaderLocation(shader, "framesCounter"); + + // Apply the shader to the two models + model1.materials[0].shader = shader; + model2.materials[0].shader = shader; + + int framesCounter = 0; + Vector3 rotation = { 0 }; // Model rotation angles + + SetTargetFPS(60); // Set to run at 60 frames-per-second + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + framesCounter++; + rotation.x += 0.01f; + rotation.y += 0.005f; + rotation.z -= 0.0025f; + + // Send frames counter to shader for animation + SetShaderValue(shader, shaderFrame, &framesCounter, UNIFORM_INT); + + // Rotate one of the models + model1.transform = MatrixRotateXYZ(rotation); + + UpdateCamera(&camera); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(DARKBLUE); + + BeginMode3D(camera); + + DrawModel(model1, (Vector3){0.5,0,0}, 1, WHITE); + DrawModelEx(model2, (Vector3){-.5,0,0}, (Vector3){1,1,0}, 50, (Vector3){1,1,1}, WHITE); + DrawModel(model3,(Vector3){0,0,-1.5}, 1, WHITE); + DrawGrid(10, 1.0f); // Draw a grid + + EndMode3D(); + + DrawRectangle(16, 698, MeasureText(FormatText("Frame: %i", framesCounter), 20) + 8, 42, BLUE); + DrawText(FormatText("Frame: %i", framesCounter), 20, 700, 20, WHITE); + + DrawFPS(10, 10); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadModel(model1); + UnloadModel(model2); + UnloadModel(model3); + + UnloadTexture(texDiffuse); // Unload default diffuse texture + UnloadTexture(texMask); // Unload texture mask + + UnloadShader(shader); // Unload shader + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} diff --git a/examples/shaders/shaders_texture_drawing.c b/examples/shaders/shaders_texture_drawing.c index cb8a9c1eb..697000bcd 100644 --- a/examples/shaders/shaders_texture_drawing.c +++ b/examples/shaders/shaders_texture_drawing.c @@ -1,49 +1,58 @@ /******************************************************************************************* * -* raylib [textures] example - Shader texture drawing +* raylib [textures] example - Texture drawing * * This example illustrates how to draw on a blank texture using a shader * * This example has been created using raylib 2.0 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * +* Example contributed by Michał Ciesielski and reviewed by Ramon Santamaria (@raysan5) +* * Copyright (c) 2019 Michał Ciesielski and Ramon Santamaria (@raysan5) * ********************************************************************************************/ #include "raylib.h" -int main() +#if defined(PLATFORM_DESKTOP) + #define GLSL_VERSION 330 +#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB + #define GLSL_VERSION 100 +#endif + +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; - InitWindow(screenWidth, screenHeight, "raylib [shaders] example - shader texture drawing"); + InitWindow(screenWidth, screenHeight, "raylib [shaders] example - texture drawing"); Image imBlank = GenImageColor(1024, 1024, BLANK); Texture2D texture = LoadTextureFromImage(imBlank); // Load blank texture to fill on shader UnloadImage(imBlank); // NOTE: Using GLSL 330 shader version, on OpenGL ES 2.0 use GLSL 100 shader version - Shader shader = LoadShader(0, "resources/shaders/glsl330/cubes_panning.fs"); + Shader shader = LoadShader(0, FormatText("resources/shaders/glsl%i/cubes_panning.fs", GLSL_VERSION)); float time = 0.0f; int timeLoc = GetShaderLocation(shader, "uTime"); SetShaderValue(shader, timeLoc, &time, UNIFORM_FLOAT); - SetTargetFPS(60); - //-------------------------------------------------------------------------------------- + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + // ------------------------------------------------------------------------------------------------------------- - while (!WindowShouldClose()) + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- time = GetTime(); SetShaderValue(shader, timeLoc, &time, UNIFORM_FLOAT); //---------------------------------------------------------------------------------- - + // Draw //---------------------------------------------------------------------------------- BeginDrawing(); @@ -53,13 +62,13 @@ int main() BeginShaderMode(shader); // Enable our custom shader for next shapes/textures drawings DrawTexture(texture, 0, 0, WHITE); // Drawing BLANK texture, all magic happens on shader EndShaderMode(); // Disable our custom shader, return to default shader - + DrawText("BACKGROUND is PAINTED and ANIMATED on SHADER!", 10, 10, 20, MAROON); EndDrawing(); //---------------------------------------------------------------------------------- } - + // De-Initialization //-------------------------------------------------------------------------------------- UnloadShader(shader); diff --git a/examples/shaders/shaders_texture_waves.c b/examples/shaders/shaders_texture_waves.c new file mode 100644 index 000000000..c04503614 --- /dev/null +++ b/examples/shaders/shaders_texture_waves.c @@ -0,0 +1,110 @@ +/******************************************************************************************* +* +* raylib [shaders] example - Texture Waves +* +* NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, +* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version. +* +* NOTE: Shaders used in this example are #version 330 (OpenGL 3.3), to test this example +* on OpenGL ES 2.0 platforms (Android, Raspberry Pi, HTML5), use #version 100 shaders +* raylib comes with shaders ready for both versions, check raylib/shaders install folder +* +* This example has been created using raylib 2.5 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Example contributed by Anata (@anatagawa) and reviewed by Ramon Santamaria (@raysan5) +* +* Copyright (c) 2019 Anata (@anatagawa) and Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#if defined(PLATFORM_DESKTOP) + #define GLSL_VERSION 330 +#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB + #define GLSL_VERSION 100 +#endif + +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [shaders] example - texture waves"); + + // Load texture texture to apply shaders + Texture2D texture = LoadTexture("resources/space.png"); + + // Load shader and setup location points and values + Shader shader = LoadShader(0, FormatText("resources/shaders/glsl%i/wave.fs", GLSL_VERSION)); + + int secondsLoc = GetShaderLocation(shader, "secondes"); + int freqXLoc = GetShaderLocation(shader, "freqX"); + int freqYLoc = GetShaderLocation(shader, "freqY"); + int ampXLoc = GetShaderLocation(shader, "ampX"); + int ampYLoc = GetShaderLocation(shader, "ampY"); + int speedXLoc = GetShaderLocation(shader, "speedX"); + int speedYLoc = GetShaderLocation(shader, "speedY"); + + // Shader uniform values that can be updated at any time + float freqX = 25.0f; + float freqY = 25.0f; + float ampX = 5.0f; + float ampY = 5.0f; + float speedX = 8.0f; + float speedY = 8.0f; + + float screenSize[2] = { (float)GetScreenWidth(), (float)GetScreenHeight() }; + SetShaderValue(shader, GetShaderLocation(shader, "size"), &screenSize, UNIFORM_VEC2); + SetShaderValue(shader, freqXLoc, &freqX, UNIFORM_FLOAT); + SetShaderValue(shader, freqYLoc, &freqY, UNIFORM_FLOAT); + SetShaderValue(shader, ampXLoc, &X, UNIFORM_FLOAT); + SetShaderValue(shader, ampYLoc, &Y, UNIFORM_FLOAT); + SetShaderValue(shader, speedXLoc, &speedX, UNIFORM_FLOAT); + SetShaderValue(shader, speedYLoc, &speedY, UNIFORM_FLOAT); + + float seconds = 0.0f; + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + // ------------------------------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + seconds += GetFrameTime(); + + SetShaderValue(shader, secondsLoc, &seconds, UNIFORM_FLOAT); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + BeginShaderMode(shader); + + DrawTexture(texture, 0, 0, WHITE); + DrawTexture(texture, texture.width, 0, WHITE); + + EndShaderMode(); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadShader(shader); // Unload shader + UnloadTexture(texture); // Unload texture + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} diff --git a/examples/shaders/shaders_texture_waves.png b/examples/shaders/shaders_texture_waves.png new file mode 100644 index 000000000..99781a172 Binary files /dev/null and b/examples/shaders/shaders_texture_waves.png differ diff --git a/examples/shapes/raygui.h b/examples/shapes/raygui.h index 3277d7eaa..226ce8f2c 100644 --- a/examples/shapes/raygui.h +++ b/examples/shapes/raygui.h @@ -1,18 +1,21 @@ /******************************************************************************************* * -* raygui v2.0-dev - A simple and easy-to-use immedite-mode-gui library +* raygui v2.5 - A simple and easy-to-use immediate-mode-gui library * * DESCRIPTION: * * raygui is a tools-dev-focused immediate-mode-gui library based on raylib but also possible * to be used as a standalone library, as long as input and drawing functions are provided. * -* Basic controls provided: +* Controls provided: * +* # Container/separators Controls * - WindowBox * - GroupBox * - Line * - Panel +* +* # Basic Controls * - Label * - Button * - LabelButton --> Label @@ -31,13 +34,16 @@ * - SliderBar --> Slider * - ProgressBar * - StatusBar +* - ScrollBar * - ScrollPanel +* - DummyRec +* - Grid +* +* # Advance Controls * - ListView --> ListElement * - ColorPicker --> ColorPanel, ColorBarHue -* - MessageBox -* - DummyRec -* - ScrollBar -* - Grid +* - MessageBox --> Label, Button +* - TextInputBox --> Label, TextBox, Button * * It also provides a set of functions for styling the controls based on its properties (size, color). * @@ -61,9 +67,20 @@ * Includes ricons.h header defining a set of 128 icons (binary format) to be used on * multiple controls and following raygui styles * +* #define RAYGUI_TEXTBOX_EXTENDED +* Enables the advance GuiTextBox()/GuiValueBox()/GuiSpinner() implementation with +* text selection support and text copy/cut/paste support +* * VERSIONS HISTORY: -* 2.0 (xx-Dec-2018) Complete review of new controls, redesigned style system -* 1.9 (01-May-2018) Lot of rework and redesign! Lots of new controls! +* 2.5 (28-May-2019) Implemented extended GuiTextBox(), GuiValueBox(), GuiSpinner() +* 2.3 (29-Apr-2019) Added rIcons auxiliar library and support for it, multiple controls reviewed +* Refactor all controls drawing mechanism to use control state +* 2.2 (05-Feb-2019) Added GuiScrollBar(), GuiScrollPanel(), reviewed GuiListView(), removed Gui*Ex() controls +* 2.1 (26-Dec-2018) Redesign of GuiCheckBox(), GuiComboBox(), GuiDropdownBox(), GuiToggleGroup() > Use combined text string +* Complete redesign of style system (breaking change) +* 2.0 (08-Nov-2018) Support controls guiLock and custom fonts, reviewed GuiComboBox(), GuiListView()... +* 1.9 (09-Oct-2018) Controls review: GuiGrid(), GuiTextBox(), GuiTextBoxMulti(), GuiValueBox()... +* 1.8 (01-May-2018) Lot of rework and redesign to align with rGuiStyler and rGuiLayout * 1.5 (21-Jun-2017) Working in an improved styles system * 1.4 (15-Jun-2017) Rewritten all GUI functions (removed useless ones) * 1.3 (12-Jun-2017) Redesigned styles system @@ -74,6 +91,7 @@ * * CONTRIBUTORS: * Ramon Santamaria: Supervision, review, redesign, update and maintenance... +* Vlad Adrian: Complete rewrite of GuiTextBox() to support extended features (2019) * Sergio Martinez: Review, testing (2015) and redesign of multiple controls (2018) * Adria Arranz: Testing and Implementation of additional controls (2018) * Jordi Jorba: Testing and Implementation of additional controls (2018) @@ -85,7 +103,7 @@ * * LICENSE: zlib/libpng * -* Copyright (c) 2014-2018 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2019 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. @@ -107,7 +125,7 @@ #ifndef RAYGUI_H #define RAYGUI_H -#define RAYGUI_VERSION "2.0-dev" +#define RAYGUI_VERSION "2.5-dev" #if !defined(RAYGUI_STANDALONE) #include "raylib.h" @@ -134,11 +152,9 @@ //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- -#define VALIGN_OFFSET(h) ((int)h%2) // Vertical alignment for pixel perfect - #define TEXTEDIT_CURSOR_BLINK_FRAMES 20 // Text edit controls cursor blink timming -#define NUM_CONTROLS 13 // Number of standard controls +#define NUM_CONTROLS 16 // Number of standard controls #define NUM_PROPS_DEFAULT 16 // Number of standard properties #define NUM_PROPS_EXTENDED 8 // Number of extended properties @@ -182,15 +198,27 @@ int width; int height; } Rectangle; - + // Texture2D type - typedef struct Texture2D { } Texture2D; - + // NOTE: It should be provided by user + typedef struct Texture2D Texture2D; + // Font type - typedef struct Font { } Font; + // NOTE: It should be provided by user + typedef struct Font Font; #endif -// Gui global state enum +#if defined(RAYGUI_TEXTBOX_EXTENDED) +// Gui text box state data +typedef struct GuiTextBoxState { + int cursor; // Cursor position in text + int start; // Text start position (from where we begin drawing the text) + int index; // Text start index (index inside the text of `start` always in sync) + int select; // Marks position of cursor when selection has started +} GuiTextBoxState; +#endif + +// Gui control state typedef enum { GUI_STATE_NORMAL = 0, GUI_STATE_FOCUSED, @@ -198,14 +226,14 @@ typedef enum { GUI_STATE_DISABLED, } GuiControlState; -// Gui global text alignment +// Gui control text alignment typedef enum { GUI_TEXT_ALIGN_LEFT = 0, GUI_TEXT_ALIGN_CENTER, GUI_TEXT_ALIGN_RIGHT, } GuiTextAlignment; -// Gui standard controls +// Gui controls typedef enum { DEFAULT = 0, LABEL, // LABELBUTTON @@ -216,13 +244,16 @@ typedef enum { CHECKBOX, COMBOBOX, DROPDOWNBOX, - TEXTBOX, // VALUEBOX, SPINNER, TEXTBOXMULTI -> TODO: Probably they should not be dependant on TEXTBOX style! + TEXTBOX, // TEXTBOXMULTI + VALUEBOX, + SPINNER, LISTVIEW, COLORPICKER, - SCROLLBAR -} GuiControlStandard; + SCROLLBAR, + RESERVED +} GuiControl; -// Gui default properties for every control +// Gui base properties for every control typedef enum { BORDER_COLOR_NORMAL = 0, BASE_COLOR_NORMAL, @@ -242,15 +273,14 @@ typedef enum { RESERVED02 } GuiControlProperty; -// Gui extended properties depending on control type -// NOTE: We reserve a fixed size of additional properties per control (8) +// Gui extended properties depend on control +// NOTE: We reserve a fixed size of additional properties per control -// Default properties +// DEFAULT properties typedef enum { TEXT_SIZE = 16, TEXT_SPACING, LINE_COLOR, - //LINE_THICK, BACKGROUND_COLOR, } GuiDefaultProperty; @@ -274,14 +304,6 @@ typedef enum { // ProgressBar //typedef enum { } GuiProgressBarProperty; -// TextBox / TextBoxMulti / ValueBox / Spinner -typedef enum { - MULTILINE_PADDING = 16, - SPINNER_BUTTON_WIDTH, - SPINNER_BUTTON_PADDING, - SPINNER_BUTTON_BORDER_WIDTH -} GuiTextBoxProperty; - // CheckBox typedef enum { CHECK_TEXT_PADDING = 16 @@ -298,14 +320,33 @@ typedef enum { ARROW_RIGHT_PADDING = 16, } GuiDropdownBoxProperty; -// ColorPicker +// TextBox / TextBoxMulti / ValueBox / Spinner typedef enum { - COLOR_SELECTOR_SIZE = 16, - BAR_WIDTH, // Lateral bar width - BAR_PADDING, // Lateral bar separation from panel - BAR_SELECTOR_HEIGHT, // Lateral bar selector height - BAR_SELECTOR_PADDING // Lateral bar selector outer padding -} GuiColorPickerProperty; + MULTILINE_PADDING = 16, + COLOR_SELECTED_FG, + COLOR_SELECTED_BG +} GuiTextBoxProperty; + +typedef enum { + SELECT_BUTTON_WIDTH = 16, + SELECT_BUTTON_PADDING, + SELECT_BUTTON_BORDER_WIDTH +} GuiSpinnerProperty; + +// ScrollBar +typedef enum { + ARROWS_SIZE = 16, + SLIDER_PADDING, + SLIDER_SIZE, + SCROLL_SPEED, + ARROWS_VISIBLE +} GuiScrollBarProperty; + +// ScrollBar side +typedef enum { + SCROLLBAR_LEFT_SIDE = 0, + SCROLLBAR_RIGHT_SIDE +} GuiScrollBarSide; // ListView typedef enum { @@ -315,20 +356,14 @@ typedef enum { SCROLLBAR_SIDE, // This property defines vertical scrollbar side (SCROLLBAR_LEFT_SIDE or SCROLLBAR_RIGHT_SIDE) } GuiListViewProperty; -// ScrollBar +// ColorPicker typedef enum { - ARROWS_SIZE = 16, - SLIDER_PADDING, - SLIDER_SIZE, - SCROLL_SPEED, - SHOW_SPINNER_BUTTONS -} GuiScrollBarProperty; - -// ScrollBar side -typedef enum { - SCROLLBAR_LEFT_SIDE = 0, - SCROLLBAR_RIGHT_SIDE -} GuiScrollBarSide; + COLOR_SELECTOR_SIZE = 16, + BAR_WIDTH, // Lateral bar width + BAR_PADDING, // Lateral bar separation from panel + BAR_SELECTOR_HEIGHT, // Lateral bar selector height + BAR_SELECTOR_PADDING // Lateral bar selector outer padding +} GuiColorPickerProperty; //---------------------------------------------------------------------------------- // Global Variables Definition @@ -352,6 +387,25 @@ RAYGUIDEF void GuiFade(float alpha); // Set g RAYGUIDEF void GuiSetStyle(int control, int property, int value); // Set one style property RAYGUIDEF int GuiGetStyle(int control, int property); // Get one style property +#if defined(RAYGUI_TEXTBOX_EXTENDED) +// GuiTextBox() extended functions +RAYGUIDEF void GuiTextBoxSetActive(Rectangle bounds); // Sets the active textbox +RAYGUIDEF Rectangle GuiTextBoxGetActive(void); // Get bounds of active textbox +RAYGUIDEF void GuiTextBoxSetCursor(int cursor); // Set cursor position of active textbox +RAYGUIDEF int GuiTextBoxGetCursor(void); // Get cursor position of active textbox +RAYGUIDEF void GuiTextBoxSetSelection(int start, int length); // Set selection of active textbox +RAYGUIDEF Vector2 GuiTextBoxGetSelection(void); // Get selection of active textbox (x - selection start y - selection length) +RAYGUIDEF bool GuiTextBoxIsActive(Rectangle bounds); // Returns true if a textbox control with specified `bounds` is the active textbox +RAYGUIDEF GuiTextBoxState GuiTextBoxGetState(void); // Get state for the active textbox +RAYGUIDEF void GuiTextBoxSetState(GuiTextBoxState state); // Set state for the active textbox (state must be valid else things will break) +RAYGUIDEF void GuiTextBoxSelectAll(const char *text); // Select all characters in the active textbox (same as pressing `CTRL` + `A`) +RAYGUIDEF void GuiTextBoxCopy(const char *text); // Copy selected text to clipboard from the active textbox (same as pressing `CTRL` + `C`) +RAYGUIDEF void GuiTextBoxPaste(char *text, int textSize); // Paste text from clipboard into the textbox (same as pressing `CTRL` + `V`) +RAYGUIDEF void GuiTextBoxCut(char *text); // Cut selected text in the active textbox and copy it to clipboard (same as pressing `CTRL` + `X`) +RAYGUIDEF int GuiTextBoxDelete(char *text, int length, bool before); // Deletes a character or selection before from the active textbox (depending on `before`). Returns bytes deleted. +RAYGUIDEF int GuiTextBoxGetByteIndex(const char *text, int start, int from, int to); // Get the byte index for a character starting at position `from` with index `start` until position `to`. +#endif + // Container/separator controls, useful for controls organization RAYGUIDEF bool GuiWindowBox(Rectangle bounds, const char *text); // Window Box control, shows a window that can be closed RAYGUIDEF void GuiGroupBox(Rectangle bounds, const char *text); // Group Box control with title name @@ -380,13 +434,14 @@ RAYGUIDEF float GuiProgressBar(Rectangle bounds, const char *text, float value, RAYGUIDEF void GuiStatusBar(Rectangle bounds, const char *text); // Status Bar control, shows info text RAYGUIDEF void GuiDummyRec(Rectangle bounds, const char *text); // Dummy control for placeholders RAYGUIDEF int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxValue); // Scroll Bar control +RAYGUIDEF Vector2 GuiGrid(Rectangle bounds, float spacing, int subdivs); // Grid control // Advance controls set RAYGUIDEF bool GuiListView(Rectangle bounds, const char *text, int *active, int *scrollIndex, bool editMode); // List View control, returns selected list element index RAYGUIDEF bool GuiListViewEx(Rectangle bounds, const char **text, int count, int *enabled, int *active, int *focus, int *scrollIndex, bool editMode); // List View with extended parameters RAYGUIDEF int GuiMessageBox(Rectangle bounds, const char *windowTitle, const char *message, const char *buttons); // Message Box control, displays a message +RAYGUIDEF int GuiTextInputBox(Rectangle bounds, const char *windowTitle, const char *message, char *text, const char *buttons); // Text Input Box control, ask for text RAYGUIDEF Color GuiColorPicker(Rectangle bounds, Color color); // Color Picker control -RAYGUIDEF Vector2 GuiGrid(Rectangle bounds, float spacing, int subdivs); // Grid // Styles loading functions RAYGUIDEF void GuiLoadStyle(const char *fileName); // Load style file (.rgs) @@ -417,7 +472,7 @@ RAYGUIDEF const char *GuiIconText(int iconId, const char *text); // Get text wit #if defined(RAYGUI_STANDALONE) #define RICONS_STANDALONE #endif - + #define RICONS_IMPLEMENTATION #include "ricons.h" // Required for: raygui icons #endif @@ -429,6 +484,12 @@ RAYGUIDEF const char *GuiIconText(int iconId, const char *text); // Get text wit #include // Required for: va_list, va_start(), vfprintf(), va_end() #endif +#ifdef __cplusplus + #define RAYGUI_CLITERAL(name) name +#else + #define RAYGUI_CLITERAL(name) (name) +#endif + //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- @@ -456,6 +517,11 @@ static float guiAlpha = 1.0f; static unsigned int guiStyle[NUM_CONTROLS*(NUM_PROPS_DEFAULT + NUM_PROPS_EXTENDED)] = { 0 }; static bool guiStyleLoaded = false; +#if defined(RAYGUI_TEXTBOX_EXTENDED) +static Rectangle guiTextBoxActive = { 0 }; // Area of the currently active textbox +static GuiTextBoxState guiTextBoxState = { .cursor = -1, .start = 0, .index = 0, .select = -1 }; // Keeps state of the active textbox +#endif + //---------------------------------------------------------------------------------- // Standalone Mode Functions Declaration // @@ -472,63 +538,47 @@ static bool guiStyleLoaded = false; #define KEY_ENTER 257 #define MOUSE_LEFT_BUTTON 0 -#ifdef __cplusplus - #define CLITERAL -#else - #define CLITERAL (Color) -#endif +// Input required functions +//------------------------------------------------------------------------------- +static Vector2 GetMousePosition(void); +static int GetMouseWheelMove(void); +static bool IsMouseButtonDown(int button); +static bool IsMouseButtonPressed(int button); +static bool IsMouseButtonReleased(int button); -#define WHITE CLITERAL{ 255, 255, 255, 255 } // White -#define BLACK CLITERAL{ 0, 0, 0, 255 } // Black -#define RAYWHITE CLITERAL{ 245, 245, 245, 255 } // My own White (raylib logo) -#define GRAY CLITERAL{ 130, 130, 130, 255 } // Gray -- GuiColorBarAlpha() +static bool IsKeyDown(int key); +static bool IsKeyPressed(int key); +static int GetKeyPressed(void); // -- GuiTextBox(), GuiTextBoxMulti(), GuiValueBox() +//------------------------------------------------------------------------------- -// raylib functions are already implemented in raygui +// Drawing required functions +//------------------------------------------------------------------------------- +static void DrawRectangle(int x, int y, int width, int height, Color color); +static void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4); // -- GuiColorPicker() +static void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // -- GuiDropdownBox(), GuiScrollBar() +static void DrawTextureRec(Texture2D texture, Rectangle sourceRec, Vector2 position, Color tint); // -- GuiImageButtonEx() +//------------------------------------------------------------------------------- + +// Text required functions +//------------------------------------------------------------------------------- +static Font GetFontDefault(void); // -- GuiLoadStyleDefault() +static Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing); // -- GetTextWidth(), GuiTextBoxMulti() +static void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // -- GuiDrawText() + +static Font LoadFontEx(const char *fileName, int fontSize, int *fontChars, int charsCount); // -- GuiLoadStyle() +//------------------------------------------------------------------------------- + +// raylib functions already implemented in raygui //------------------------------------------------------------------------------- static Color GetColor(int hexValue); // Returns a Color struct from hexadecimal value static int ColorToInt(Color color); // Returns hexadecimal value for a Color static Color Fade(Color color, float alpha); // Color fade-in or fade-out, alpha goes from 0.0f to 1.0f static bool CheckCollisionPointRec(Vector2 point, Rectangle rec); // Check if point is inside rectangle static const char *TextFormat(const char *text, ...); // Formatting of text with variables to 'embed' -//------------------------------------------------------------------------------- -// Input required functions -//------------------------------------------------------------------------------- -static Vector2 GetMousePosition(void) { return (Vector2){ 0, 0 }; } -static int GetMouseWheelMove(void) { return 0; } -static bool IsMouseButtonDown(int button) { return false; } -static bool IsMouseButtonPressed(int button) { return false; } -static bool IsMouseButtonReleased(int button) { return false; } - -static bool IsKeyDown(int key) { return false; } -static bool IsKeyPressed(int key) { return false; } -static int GetKeyPressed(void) { return 0; } // -- GuiTextBox() -//------------------------------------------------------------------------------- - -// Drawing required functions -//------------------------------------------------------------------------------- -static void DrawRectangle(int x, int y, int width, int height, Color color) { /* TODO */ } -static void DrawRectangleRec(Rectangle rec, Color color) { DrawRectangle(rec.x, rec.y, rec.width, rec.height, color); } - -static void DrawRectangleLinesEx(Rectangle rec, int lineThick, Color color) { /* TODO */ } - -static void DrawRectangleLines(int x, int y, int width, int height, Color color) { /* TODO */ } // -- GuiColorPicker() -static void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2); // -- GuiColorPicker() -static void DrawRectangleGradientH(int posX, int posY, int width, int height, Color color1, Color color2); // -- GuiColorPicker() -static void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4); // -- GuiColorPicker() - -static void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color) { /* TODO */ } // -- GuiDropdownBox() -static void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color) { /* TODO */ } // -- GuiScrollBar() - -static void DrawTextureRec(Texture2D texture, Rectangle sourceRec, Vector2 position, Color tint) { } // -- GuiImageButtonEx() -//------------------------------------------------------------------------------- - -// Text required functions -//------------------------------------------------------------------------------- -static Font GetFontDefault(void); // -- GetTextWidth() - -static Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing) { return (Vector2){ 0.0f }; } // Measure text size depending on font -static void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint) { } // Draw text using font and additional parameters +static void DrawRectangleRec(Rectangle rec, Color color); // Draw rectangle filled with color +static void DrawRectangleLinesEx(Rectangle rec, int lineThick, Color color); // Draw rectangle outlines +static void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2); // Draw rectangle vertical gradient //------------------------------------------------------------------------------- #endif // RAYGUI_STANDALONE @@ -548,8 +598,6 @@ static int GetTextWidth(const char *text) // TODO: GetTextSize() { Vector2 size = { 0 }; - if (guiFont.texture.id == 0) guiFont = GetFontDefault(); - if ((text != NULL) && (text[0] != '\0')) size = MeasureTextEx(guiFont, text, GuiGetStyle(DEFAULT, TEXT_SIZE), GuiGetStyle(DEFAULT, TEXT_SPACING)); // TODO: Consider text icon width here??? @@ -573,8 +621,9 @@ static Rectangle GetTextBounds(int control, Rectangle bounds) case CHECKBOX: bounds.x += (bounds.width + GuiGetStyle(control, CHECK_TEXT_PADDING)); break; default: break; } - // TODO: Special cases: COMBOBOX, DROPDOWNBOX, SPINNER, LISTVIEW (scrollbar?) - // More special cases: CHECKBOX, SLIDER + + // TODO: Special cases (no label): COMBOBOX, DROPDOWNBOX, SPINNER, LISTVIEW (scrollbar?) + // More special cases (label side): CHECKBOX, SLIDER return textBounds; } @@ -609,7 +658,7 @@ static const char *GetTextIcon(const char *text, int *iconId) // Gui draw text using default font static void GuiDrawText(const char *text, Rectangle bounds, int alignment, Color tint) { - if (guiFont.texture.id == 0) guiFont = GetFontDefault(); + #define VALIGN_OFFSET(h) ((int)h%2) // Vertical alignment for pixel perfect if ((text != NULL) && (text[0] != '\0')) { @@ -635,7 +684,6 @@ static void GuiDrawText(const char *text, Rectangle bounds, int alignment, Color if ((text != NULL) && (text[0] != '\0')) textWidth += ICON_TEXT_PADDING; } #endif - // Check guiTextAlign global variables switch (alignment) { @@ -666,7 +714,7 @@ static void GuiDrawText(const char *text, Rectangle bounds, int alignment, Color if (iconId > 0) { // NOTE: We consider icon height, probably different than text size - DrawIcon(iconId, (Vector2){ position.x, bounds.y + bounds.height/2 - RICONS_SIZE/2 + VALIGN_OFFSET(bounds.height) }, 1, tint); + DrawIcon(iconId, RAYGUI_CLITERAL(Vector2){ position.x, bounds.y + bounds.height/2 - RICONS_SIZE/2 + VALIGN_OFFSET(bounds.height) }, 1, tint); position.x += (RICONS_SIZE + ICON_TEXT_PADDING); } #endif @@ -705,12 +753,6 @@ RAYGUIDEF void GuiFont(Font font) { guiFont = font; GuiSetStyle(DEFAULT, TEXT_SIZE, font.baseSize); - - // Populate all controls with new font size - for (int i = 1; i < NUM_CONTROLS; i++) GuiSetStyle(i, TEXT_SIZE, GuiGetStyle(DEFAULT, TEXT_SIZE)); - - // NOTE: Loaded font spacing must be set manually - //GuiSetStyle(DEFAULT, TEXT_SPACING, 1); } } @@ -737,6 +779,61 @@ RAYGUIDEF int GuiGetStyle(int control, int property) return guiStyle[control*(NUM_PROPS_DEFAULT + NUM_PROPS_EXTENDED) + property]; } +#if defined(RAYGUI_TEXTBOX_EXTENDED) +// Sets the active textbox (reseting state of the previous active textbox) +RAYGUIDEF void GuiTextBoxSetActive(Rectangle bounds) +{ + guiTextBoxActive = bounds; + guiTextBoxState = (GuiTextBoxState){ .cursor = -1, .start = 0, .index = 0, .select = -1 }; +} + +// Gets bounds of active textbox +RAYGUIDEF Rectangle GuiTextBoxGetActive(void) { return guiTextBoxActive; } + +// Set cursor position of active textbox +RAYGUIDEF void GuiTextBoxSetCursor(int cursor) +{ + guiTextBoxState.cursor = (cursor < 0) ? -1 : cursor; + guiTextBoxState.start = -1; // Mark this to be recalculated +} + +// Get cursor position of active textbox +RAYGUIDEF int GuiTextBoxGetCursor(void) { return guiTextBoxState.cursor; } + +// Set selection of active textbox +RAYGUIDEF void GuiTextBoxSetSelection(int start, int length) +{ + if(start < 0) start = 0; + if(length < 0) length = 0; + GuiTextBoxSetCursor(start + length); + guiTextBoxState.select = start; +} + +// Get selection of active textbox +RAYGUIDEF Vector2 GuiTextBoxGetSelection(void) +{ + if(guiTextBoxState.select == -1 || guiTextBoxState.select == guiTextBoxState.cursor) + return RAYGUI_CLITERAL(Vector2){ 0 }; + else if(guiTextBoxState.cursor > guiTextBoxState.select) + return RAYGUI_CLITERAL(Vector2){ guiTextBoxState.select, guiTextBoxState.cursor - guiTextBoxState.select }; + + return RAYGUI_CLITERAL(Vector2){ guiTextBoxState.cursor, guiTextBoxState.select - guiTextBoxState.cursor }; +} + +// Returns true if a textbox control with specified `bounds` is the active textbox +RAYGUIDEF bool GuiTextBoxIsActive(Rectangle bounds) +{ + return (bounds.x == guiTextBoxActive.x && bounds.y == guiTextBoxActive.y && + bounds.width == guiTextBoxActive.width && bounds.height == guiTextBoxActive.height); +} +RAYGUIDEF GuiTextBoxState GuiTextBoxGetState(void) { return guiTextBoxState; } +RAYGUIDEF void GuiTextBoxSetState(GuiTextBoxState state) +{ + // NOTE: should we check if state values are valid ?!? + guiTextBoxState = state; +} +#endif + // Window Box control RAYGUIDEF bool GuiWindowBox(Rectangle bounds, const char *text) { @@ -761,7 +858,7 @@ RAYGUIDEF bool GuiWindowBox(Rectangle bounds, const char *text) // Draw window base DrawRectangleLinesEx(bounds, GuiGetStyle(DEFAULT, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(DEFAULT, BORDER + (state*3))), guiAlpha)); - DrawRectangleRec((Rectangle){ bounds.x + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), + DrawRectangleRec(RAYGUI_CLITERAL(Rectangle){ bounds.x + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.width - GuiGetStyle(DEFAULT, BORDER_WIDTH)*2, bounds.height - GuiGetStyle(DEFAULT, BORDER_WIDTH)*2 }, Fade(GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)), guiAlpha)); @@ -775,8 +872,8 @@ RAYGUIDEF bool GuiWindowBox(Rectangle bounds, const char *text) GuiSetStyle(DEFAULT, TEXT_ALIGNMENT, defaultTextAlign); // Draw window close button - int buttonBorder = GuiGetStyle(BUTTON, BORDER_WIDTH); - int buttonTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT); + int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH); + int tempTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT); GuiSetStyle(BUTTON, BORDER_WIDTH, 1); GuiSetStyle(BUTTON, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_CENTER); #if defined(RAYGUI_RICONS_SUPPORT) @@ -784,8 +881,8 @@ RAYGUIDEF bool GuiWindowBox(Rectangle bounds, const char *text) #else clicked = GuiButton(buttonRec, "x"); #endif - GuiSetStyle(BUTTON, BORDER_WIDTH, buttonBorder); - GuiSetStyle(BUTTON, TEXT_ALIGNMENT, buttonTextAlignment); + GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlignment); //-------------------------------------------------------------------- return clicked; @@ -806,7 +903,7 @@ RAYGUIDEF void GuiGroupBox(Rectangle bounds, const char *text) DrawRectangle(bounds.x, bounds.y + bounds.height - 1, bounds.width, GROUPBOX_LINE_THICK, Fade(GetColor(GuiGetStyle(DEFAULT, (state == GUI_STATE_DISABLED)? BORDER_COLOR_DISABLED : LINE_COLOR)), guiAlpha)); DrawRectangle(bounds.x + bounds.width - 1, bounds.y, GROUPBOX_LINE_THICK, bounds.height, Fade(GetColor(GuiGetStyle(DEFAULT, (state == GUI_STATE_DISABLED)? BORDER_COLOR_DISABLED : LINE_COLOR)), guiAlpha)); - GuiLine((Rectangle){ bounds.x, bounds.y, bounds.width, 1 }, text); + GuiLine(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, bounds.width, 1 }, text); //-------------------------------------------------------------------- } @@ -871,13 +968,13 @@ RAYGUIDEF Rectangle GuiScrollPanel(Rectangle bounds, Rectangle content, Vector2 const int horizontalScrollBarWidth = hasHorizontalScrollBar? GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH) : 0; const int verticalScrollBarWidth = hasVerticalScrollBar? GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH) : 0; - const Rectangle horizontalScrollBar = { ((GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? bounds.x + verticalScrollBarWidth : bounds.x) + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.y + bounds.height - horizontalScrollBarWidth - GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.width - verticalScrollBarWidth - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH), horizontalScrollBarWidth }; - const Rectangle verticalScrollBar = { ((GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? bounds.x + GuiGetStyle(DEFAULT, BORDER_WIDTH) : bounds.x + bounds.width - verticalScrollBarWidth - GuiGetStyle(DEFAULT, BORDER_WIDTH)), bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), verticalScrollBarWidth, bounds.height - horizontalScrollBarWidth - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) }; + const Rectangle horizontalScrollBar = { (float)((GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE) ? (float)bounds.x + verticalScrollBarWidth : (float)bounds.x) + GuiGetStyle(DEFAULT, BORDER_WIDTH), (float)bounds.y + bounds.height - horizontalScrollBarWidth - GuiGetStyle(DEFAULT, BORDER_WIDTH), (float)bounds.width - verticalScrollBarWidth - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH), (float)horizontalScrollBarWidth }; + const Rectangle verticalScrollBar = { (float)((GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE) ? (float)bounds.x + GuiGetStyle(DEFAULT, BORDER_WIDTH) : (float)bounds.x + bounds.width - verticalScrollBarWidth - GuiGetStyle(DEFAULT, BORDER_WIDTH)), (float)bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), (float)verticalScrollBarWidth, (float)bounds.height - horizontalScrollBarWidth - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) }; // Calculate view area (area without the scrollbars) Rectangle view = (GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? - (Rectangle){ bounds.x + verticalScrollBarWidth + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - verticalScrollBarWidth, bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - horizontalScrollBarWidth } : - (Rectangle){ bounds.x + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - verticalScrollBarWidth, bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - horizontalScrollBarWidth }; + RAYGUI_CLITERAL(Rectangle){ bounds.x + verticalScrollBarWidth + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - verticalScrollBarWidth, bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - horizontalScrollBarWidth } : + RAYGUI_CLITERAL(Rectangle){ bounds.x + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - verticalScrollBarWidth, bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - horizontalScrollBarWidth }; // Clip view area to the actual content size if (view.width > content.width) view.width = content.width; @@ -912,7 +1009,7 @@ RAYGUIDEF Rectangle GuiScrollPanel(Rectangle bounds, Rectangle content, Vector2 if (IsKeyDown(KEY_DOWN)) scrollPos.y -= GuiGetStyle(SCROLLBAR, SCROLL_SPEED); if (IsKeyDown(KEY_UP)) scrollPos.y += GuiGetStyle(SCROLLBAR, SCROLL_SPEED); } - + scrollPos.y += GetMouseWheelMove()*20; } } @@ -946,22 +1043,22 @@ RAYGUIDEF Rectangle GuiScrollPanel(Rectangle bounds, Rectangle content, Vector2 GuiSetStyle(SCROLLBAR, SLIDER_SIZE, ((bounds.height - 2 * GuiGetStyle(DEFAULT, BORDER_WIDTH) - horizontalScrollBarWidth)/content.height)* (bounds.height - 2 * GuiGetStyle(DEFAULT, BORDER_WIDTH) - horizontalScrollBarWidth)); scrollPos.y = -GuiScrollBar(verticalScrollBar, -scrollPos.y, verticalMin, verticalMax); } - + // Draw detail corner rectangle if both scroll bars are visible - if (hasHorizontalScrollBar && hasVerticalScrollBar) + if (hasHorizontalScrollBar && hasVerticalScrollBar) { // TODO: Consider scroll bars side - DrawRectangle(horizontalScrollBar.x + horizontalScrollBar.width + 2, - verticalScrollBar.y + verticalScrollBar.height + 2, - horizontalScrollBarWidth - 4, verticalScrollBarWidth - 4, - Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT + (state*3))), guiAlpha)); + DrawRectangle(horizontalScrollBar.x + horizontalScrollBar.width + 2, + verticalScrollBar.y + verticalScrollBar.height + 2, + horizontalScrollBarWidth - 4, verticalScrollBarWidth - 4, + Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT + (state * 3))), guiAlpha)); } // Set scrollbar slider size back to the way it was before GuiSetStyle(SCROLLBAR, SLIDER_SIZE, slider); // Draw scrollbar lines depending on current state - DrawRectangleLinesEx(bounds, GuiGetStyle(DEFAULT, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER + (state*3))), guiAlpha)); + DrawRectangleLinesEx(bounds, GuiGetStyle(DEFAULT, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, (float)BORDER + (state*3))), guiAlpha)); //-------------------------------------------------------------------- if (scroll != NULL) *scroll = scrollPos; @@ -1053,7 +1150,7 @@ RAYGUIDEF bool GuiLabelButton(Rectangle bounds, const char *text) // Image button control, returns true when clicked RAYGUIDEF bool GuiImageButton(Rectangle bounds, Texture2D texture) { - return GuiImageButtonEx(bounds, texture, (Rectangle){ 0, 0, texture.width, texture.height }, NULL); + return GuiImageButtonEx(bounds, texture, RAYGUI_CLITERAL(Rectangle){ 0, 0, (float)texture.width, (float)texture.height }, NULL); } // Image button control, returns true when clicked @@ -1084,7 +1181,7 @@ RAYGUIDEF bool GuiImageButtonEx(Rectangle bounds, Texture2D texture, Rectangle t DrawRectangle(bounds.x + GuiGetStyle(BUTTON, BORDER_WIDTH), bounds.y + GuiGetStyle(BUTTON, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(BUTTON, BORDER_WIDTH), bounds.height - 2*GuiGetStyle(BUTTON, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(BUTTON, BASE + (state*3))), guiAlpha)); if (text != NULL) GuiDrawText(text, GetTextBounds(BUTTON, bounds), GuiGetStyle(BUTTON, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(BUTTON, TEXT + (state*3))), guiAlpha)); - if (texture.id > 0) DrawTextureRec(texture, texSource, (Vector2){ bounds.x + bounds.width/2 - (texSource.width + GuiGetStyle(BUTTON, INNER_PADDING)/2)/2, bounds.y + bounds.height/2 - texSource.height/2 }, Fade(GetColor(GuiGetStyle(BUTTON, TEXT + (state*3))), guiAlpha)); + if (texture.id > 0) DrawTextureRec(texture, texSource, RAYGUI_CLITERAL(Vector2){ bounds.x + bounds.width/2 - (texSource.width + GuiGetStyle(BUTTON, INNER_PADDING)/2)/2, bounds.y + bounds.height/2 - texSource.height/2 }, Fade(GetColor(GuiGetStyle(BUTTON, TEXT + (state*3))), guiAlpha)); //------------------------------------------------------------------ return clicked; @@ -1184,7 +1281,7 @@ RAYGUIDEF bool GuiCheckBox(Rectangle bounds, const char *text, bool checked) Vector2 mousePoint = GetMousePosition(); // Check checkbox state - if (CheckCollisionPointRec(mousePoint, (Rectangle){ bounds.x, bounds.y, bounds.width + textBounds.width + GuiGetStyle(CHECKBOX, CHECK_TEXT_PADDING), bounds.height })) + if (CheckCollisionPointRec(mousePoint, RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, bounds.width + textBounds.width + GuiGetStyle(CHECKBOX, CHECK_TEXT_PADDING), bounds.height })) { if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = GUI_STATE_PRESSED; else state = GUI_STATE_FOCUSED; @@ -1217,8 +1314,8 @@ RAYGUIDEF int GuiComboBox(Rectangle bounds, const char *text, int active) bounds.width -= (GuiGetStyle(COMBOBOX, SELECTOR_WIDTH) + GuiGetStyle(COMBOBOX, SELECTOR_PADDING)); - Rectangle selector = { bounds.x + bounds.width + GuiGetStyle(COMBOBOX, SELECTOR_PADDING), - bounds.y, GuiGetStyle(COMBOBOX, SELECTOR_WIDTH), bounds.height }; + Rectangle selector = { (float)bounds.x + bounds.width + GuiGetStyle(COMBOBOX, SELECTOR_PADDING), + (float)bounds.y, (float)GuiGetStyle(COMBOBOX, SELECTOR_WIDTH), (float)bounds.height }; // Get substrings elements from text (elements pointers, lengths and count) int elementsCount = 0; @@ -1258,14 +1355,15 @@ RAYGUIDEF int GuiComboBox(Rectangle bounds, const char *text, int active) // Draw selector using a custom button // NOTE: BORDER_WIDTH and TEXT_ALIGNMENT forced values - GuiSetStyle(BUTTON, BORDER_WIDTH, 1); + int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH); int tempTextAlign = GuiGetStyle(BUTTON, TEXT_ALIGNMENT); + GuiSetStyle(BUTTON, BORDER_WIDTH, 1); GuiSetStyle(BUTTON, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_CENTER); GuiButton(selector, TextFormat("%i/%i", active + 1, elementsCount)); GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlign); - GuiSetStyle(BUTTON, BORDER_WIDTH, 2); + GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth); //-------------------------------------------------------------------- return active; @@ -1325,7 +1423,7 @@ RAYGUIDEF bool GuiDropdownBox(Rectangle bounds, const char *text, int *active, b // Draw control //-------------------------------------------------------------------- - // TODO: Review this ugly hack... DROPDOWNBOX depends on GiListElement() that uses DEFAULT_TEXT_ALIGNMENT + // TODO: Review this ugly hack... DROPDOWNBOX depends on GuiListElement() that uses DEFAULT_TEXT_ALIGNMENT int tempTextAlign = GuiGetStyle(DEFAULT, TEXT_ALIGNMENT); GuiSetStyle(DEFAULT, TEXT_ALIGNMENT, GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT)); @@ -1336,33 +1434,33 @@ RAYGUIDEF bool GuiDropdownBox(Rectangle bounds, const char *text, int *active, b DrawRectangle(bounds.x, bounds.y, bounds.width, bounds.height, Fade(GetColor(GuiGetStyle(DROPDOWNBOX, BASE_COLOR_NORMAL)), guiAlpha)); DrawRectangleLinesEx(bounds, GuiGetStyle(DROPDOWNBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(DROPDOWNBOX, BORDER_COLOR_NORMAL)), guiAlpha)); - GuiListElement((Rectangle){ bounds.x, bounds.y, bounds.width, bounds.height }, elementsPtrs[auxActive], false, false); + GuiListElement(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, bounds.width, bounds.height }, elementsPtrs[auxActive], false, false); } break; case GUI_STATE_FOCUSED: { - GuiListElement((Rectangle){ bounds.x, bounds.y, bounds.width, bounds.height }, elementsPtrs[auxActive], false, editMode); + GuiListElement(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, bounds.width, bounds.height }, elementsPtrs[auxActive], false, editMode); } break; case GUI_STATE_PRESSED: { - if (!editMode) GuiListElement((Rectangle){ bounds.x, bounds.y, bounds.width, bounds.height }, elementsPtrs[auxActive], true, true); + if (!editMode) GuiListElement(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, bounds.width, bounds.height }, elementsPtrs[auxActive], true, true); if (editMode) { GuiPanel(openBounds); - GuiListElement((Rectangle){ bounds.x, bounds.y, bounds.width, bounds.height }, elementsPtrs[auxActive], true, true); + GuiListElement(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, bounds.width, bounds.height }, elementsPtrs[auxActive], true, true); for (int i = 0; i < elementsCount; i++) { if (i == auxActive && editMode) { - if (GuiListElement((Rectangle){ bounds.x, bounds.y + bounds.height*(i + 1) + GuiGetStyle(DROPDOWNBOX, INNER_PADDING), - bounds.width, bounds.height - GuiGetStyle(DROPDOWNBOX, INNER_PADDING) }, + if (GuiListElement(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height*(i + 1) + GuiGetStyle(DROPDOWNBOX, INNER_PADDING), + bounds.width, bounds.height - GuiGetStyle(DROPDOWNBOX, INNER_PADDING) }, elementsPtrs[i], true, true) == false) pressed = true; } else { - if (GuiListElement((Rectangle){ bounds.x, bounds.y + bounds.height*(i+1) + GuiGetStyle(DROPDOWNBOX, INNER_PADDING), - bounds.width, bounds.height - GuiGetStyle(DROPDOWNBOX, INNER_PADDING) }, + if (GuiListElement(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height*(i+1) + GuiGetStyle(DROPDOWNBOX, INNER_PADDING), + bounds.width, bounds.height - GuiGetStyle(DROPDOWNBOX, INNER_PADDING) }, elementsPtrs[i], false, true)) { auxActive = i; @@ -1377,23 +1475,1035 @@ RAYGUIDEF bool GuiDropdownBox(Rectangle bounds, const char *text, int *active, b DrawRectangle(bounds.x, bounds.y, bounds.width, bounds.height, Fade(GetColor(GuiGetStyle(DROPDOWNBOX, BASE_COLOR_DISABLED)), guiAlpha)); DrawRectangleLinesEx(bounds, GuiGetStyle(DROPDOWNBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(DROPDOWNBOX, BORDER_COLOR_DISABLED)), guiAlpha)); - GuiListElement((Rectangle){ bounds.x, bounds.y, bounds.width, bounds.height }, elementsPtrs[auxActive], false, false); + GuiListElement(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, bounds.width, bounds.height }, elementsPtrs[auxActive], false, false); } break; default: break; } GuiSetStyle(DEFAULT, TEXT_ALIGNMENT, tempTextAlign); - DrawTriangle((Vector2){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_RIGHT_PADDING), bounds.y + bounds.height/2 - 2 }, - (Vector2){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_RIGHT_PADDING) + 5, bounds.y + bounds.height/2 - 2 + 5 }, - (Vector2){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_RIGHT_PADDING) + 10, bounds.y + bounds.height/2 - 2 }, + // TODO: Avoid this function, use icon instead or 'v' + DrawTriangle(RAYGUI_CLITERAL(Vector2){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_RIGHT_PADDING), bounds.y + bounds.height/2 - 2 }, + RAYGUI_CLITERAL(Vector2){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_RIGHT_PADDING) + 5, bounds.y + bounds.height/2 - 2 + 5 }, + RAYGUI_CLITERAL(Vector2){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_RIGHT_PADDING) + 10, bounds.y + bounds.height/2 - 2 }, Fade(GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3))), guiAlpha)); + + //GuiDrawText("v", RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_RIGHT_PADDING), bounds.y + bounds.height/2 - 2, 10, 10 }, + // GUI_TEXT_ALIGN_CENTER, Fade(GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3))), guiAlpha)); //-------------------------------------------------------------------- *active = auxActive; return pressed; } +#if defined(RAYGUI_TEXTBOX_EXTENDED) +// Spinner control, returns selected value +// NOTE: Requires static variables: timer, valueSpeed - ERROR! +RAYGUIDEF bool GuiSpinner(Rectangle bounds, int *value, int minValue, int maxValue, bool editMode) +{ + #define GUI_SPINNER_HOLD_SPEED 0.2f // Min 200ms delay + + static float timer = 0.0f; + + int tempValue = *value; + const float time = GetTime(); // Get current time + bool pressed = false, active = GuiTextBoxIsActive(bounds); + + Rectangle spinner = { bounds.x + GuiGetStyle(SPINNER, SELECT_BUTTON_WIDTH) + GuiGetStyle(SPINNER, SELECT_BUTTON_PADDING), bounds.y, + bounds.width - 2*(GuiGetStyle(SPINNER, SELECT_BUTTON_WIDTH) + GuiGetStyle(SPINNER, SELECT_BUTTON_PADDING)), bounds.height }; + Rectangle leftButtonBound = { bounds.x, bounds.y, GuiGetStyle(SPINNER, SELECT_BUTTON_WIDTH), bounds.height }; + Rectangle rightButtonBound = { bounds.x + bounds.width - GuiGetStyle(SPINNER, SELECT_BUTTON_WIDTH), bounds.y, GuiGetStyle(SPINNER, SELECT_BUTTON_WIDTH), bounds.height }; + + // Update control + //-------------------------------------------------------------------- + Vector2 mouse = GetMousePosition(); + if (tempValue < minValue) tempValue = minValue; + if (tempValue > maxValue) tempValue = maxValue; + + if (editMode) + { + if (!active) + { + // This becomes the active textbox when mouse is pressed or held inside bounds + if ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON) || IsMouseButtonDown(MOUSE_LEFT_BUTTON)) && + CheckCollisionPointRec(mouse, bounds)) + { + GuiTextBoxSetActive(bounds); + active = true; + } + } + } + + // Reset timer when one of the buttons is clicked (without this, holding the button down will not behave correctly) + if ((CheckCollisionPointRec(mouse, leftButtonBound) || CheckCollisionPointRec(mouse, rightButtonBound)) && + IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + timer = time; + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + if (GuiTextBoxIsActive(bounds)) guiTextBoxActive = spinner; // Set our spinner as the active textbox + pressed = GuiValueBox(spinner, &tempValue, minValue, maxValue, editMode); + if (GuiTextBoxIsActive(spinner)) guiTextBoxActive = bounds; // Revert change + + // Draw value selector custom buttons + // NOTE: BORDER_WIDTH and TEXT_ALIGNMENT forced values + int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH); + GuiSetStyle(BUTTON, BORDER_WIDTH, GuiGetStyle(SPINNER, BORDER_WIDTH)); + + int tempTextAlign = GuiGetStyle(BUTTON, TEXT_ALIGNMENT); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_CENTER); + + char *icon = "<"; +#if defined(RAYGUI_RICONS_SUPPORT) + icon = (char *)GuiIconText(RICON_ARROW_LEFT_FILL, NULL); +#endif + if (GuiButton(leftButtonBound, icon) || // NOTE: also decrease value when the button is held down + (IsMouseButtonDown(MOUSE_LEFT_BUTTON) && + CheckCollisionPointRec(mouse, leftButtonBound) && + (time - timer) > GUI_SPINNER_HOLD_SPEED)) + { + tempValue--; + } + + icon = ">"; +#if defined(RAYGUI_RICONS_SUPPORT) + icon = (char *)GuiIconText(RICON_ARROW_RIGHT_FILL, NULL); +#endif + if (GuiButton(rightButtonBound, icon) || // NOTE: also increase value when the button is held down + (IsMouseButtonDown(MOUSE_LEFT_BUTTON) && + CheckCollisionPointRec(mouse, rightButtonBound) && + (time - timer) > GUI_SPINNER_HOLD_SPEED)) + { + tempValue++; + } + + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlign); + GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth); + //-------------------------------------------------------------------- + + if (tempValue < minValue) tempValue = minValue; + if (tempValue > maxValue) tempValue = maxValue; + + // Reset timer + if (active && (((time - timer) > GUI_SPINNER_HOLD_SPEED) || (timer == 0.0f) || (timer > time))) timer = time; + + *value = tempValue; + + return pressed; +} + +// Value Box control, updates input text with numbers +RAYGUIDEF bool GuiValueBox(Rectangle bounds, int *value, int minValue, int maxValue, bool editMode) +{ + #define VALUEBOX_MAX_CHARS 32 + + char text[VALUEBOX_MAX_CHARS + 1] = { 0 }; + sprintf(text, "%i", *value); + + bool pressed = GuiTextBox(bounds, text, VALUEBOX_MAX_CHARS, editMode); + *value = atoi(text); + + if (*value > maxValue) *value = maxValue; + else if (*value < minValue) *value = minValue; + + return pressed; +} + +enum { + GUI_MEASURE_MODE_CURSOR_END = 0xA, + GUI_MEASURE_MODE_CURSOR_POS, + GUI_MEASURE_MODE_CURSOR_COORDS, +}; + +// Required by GuiTextBox() +// Highly synchronized with calculations in DrawTextRecEx() +static int GuiMeasureTextBox(const char *text, int length, Rectangle rec, int *pos, int mode) +{ + // Get gui font properties + const Font font = guiFont; + const float fontSize = GuiGetStyle(DEFAULT, TEXT_SIZE); + const float spacing = GuiGetStyle(DEFAULT, TEXT_SPACING); + + int textOffsetX = 0; // Offset between characters + float scaleFactor = 0.0f; + + int letter = 0; // Current character + int index = 0; // Index position in sprite font + + scaleFactor = fontSize/font.baseSize; + + int i = 0, k = 0; + int glyphWidth = 0; + for (i = 0; i < length; i++, k++) + { + glyphWidth = 0; + int next = 1; + letter = GetNextCodepoint(&text[i], &next); + if (letter == 0x3f) next = 1; + index = GetGlyphIndex(font, letter); + i += next - 1; + + if (letter != '\n') + { + glyphWidth = (font.chars[index].advanceX == 0)? + (int)(font.chars[index].rec.width*scaleFactor + spacing): + (int)(font.chars[index].advanceX*scaleFactor + spacing); + + if ((textOffsetX + glyphWidth + 1) >= rec.width) break; + + if ((mode == GUI_MEASURE_MODE_CURSOR_POS) && (*pos == k)) break; + else if (mode == GUI_MEASURE_MODE_CURSOR_COORDS) + { + // Check if the mouse pointer is inside the glyph rect + Rectangle grec = {rec.x + textOffsetX - 1, rec.y, glyphWidth, (font.baseSize + font.baseSize/2)*scaleFactor - 1 }; + Vector2 mouse = GetMousePosition(); + + if (CheckCollisionPointRec(mouse, grec)) + { + // Smooth selection by dividing the glyph rectangle into 2 equal parts and checking where the mouse resides + if (mouse.x > (grec.x + glyphWidth/2)) + { + textOffsetX += glyphWidth; + k++; + } + + break; + } + } + } + else break; + + textOffsetX += glyphWidth; + } + + *pos = k; + + return (rec.x + textOffsetX - 1); +} + +static int GetPrevCodepoint(const char *text, const char *start, int *prev) +{ + int c = 0x3f; + char *p = (char *)text; + *prev = 1; + + for (int i = 0; (p >= start) && (i < 4); p--, i++) + { + if ((((unsigned char)*p) >> 6) != 2) + { + c = GetNextCodepoint(p, prev); + break; + } + } + + return c; +} + +// Required by GuiTextBoxEx() +// Highly synchronized with calculations in DrawTextRecEx() +static int GuiMeasureTextBoxRev(const char *text, int length, Rectangle rec, int *pos) +{ + // Get gui font properties + const Font font = guiFont; + const float fontSize = GuiGetStyle(DEFAULT, TEXT_SIZE); + const float spacing = GuiGetStyle(DEFAULT, TEXT_SPACING); + + int textOffsetX = 0; // Offset between characters + float scaleFactor = 0.0f; + + int letter = 0; // Current character + int index = 0; // Index position in sprite font + + scaleFactor = fontSize/font.baseSize; + + int i = 0, k = 0; + int glyphWidth = 0, prev = 1; + for (i = length; i >= 0; i--, k++) + { + glyphWidth = 0; + letter = GetPrevCodepoint(&text[i], &text[0], &prev); + + if (letter == 0x3f) prev = 1; + index = GetGlyphIndex(font, letter); + i -= prev - 1; + + if (letter != '\n') + { + glyphWidth = (font.chars[index].advanceX == 0)? + (int)(font.chars[index].rec.width*scaleFactor + spacing): + (int)(font.chars[index].advanceX*scaleFactor + spacing); + + if ((textOffsetX + glyphWidth + 1) >= rec.width) break; + } + else break; + + textOffsetX += glyphWidth; + } + + *pos = k; + + return (i + prev); +} + + +// Calculate cursor coordinates based on the cursor position `pos` inside the `text`. +static inline int GuiTextBoxGetCursorCoordinates(const char *text, int length, Rectangle rec, int pos) +{ + return GuiMeasureTextBox(text, length, rec, &pos, GUI_MEASURE_MODE_CURSOR_POS); +} + +// Calculate cursor position in textbox based on mouse coordinates. +static inline int GuiTextBoxGetCursorFromMouse(const char *text, int length, Rectangle rec, int* pos) +{ + return GuiMeasureTextBox(text, length, rec, pos, GUI_MEASURE_MODE_CURSOR_COORDS); +} + +// Calculates how many characters is the textbox able to draw inside rec +static inline int GuiTextBoxMaxCharacters(const char *text, int length, Rectangle rec) +{ + int pos = -1; + GuiMeasureTextBox(text, length, rec, &pos, GUI_MEASURE_MODE_CURSOR_END); + return pos; +} + +// Returns total number of characters(codepoints) in a UTF8 encoded `text` until `\0` or a `\n` is found. +// NOTE: If a invalid UTF8 sequence is encountered a `?`(0x3f) codepoint is counted instead. +static inline unsigned int GuiCountCodepointsUntilNewline(const char *text) +{ + unsigned int len = 0; + char *ptr = (char*)&text[0]; + + while ((*ptr != '\0') && (*ptr != '\n')) + { + int next = 0; + int letter = GetNextCodepoint(ptr, &next); + + if (letter == 0x3f) ptr += 1; + else ptr += next; + ++len; + } + + return len; +} + +static inline void MoveTextBoxCursorRight(const char* text, int length, Rectangle textRec) +{ + // FIXME: Counting codepoints each time we press the key is expensive, find another way + int count = GuiCountCodepointsUntilNewline(text); + if (guiTextBoxState.cursor < count ) guiTextBoxState.cursor++; + + const int max = GuiTextBoxMaxCharacters(&text[guiTextBoxState.index], length - guiTextBoxState.index, textRec); + + if ((guiTextBoxState.cursor - guiTextBoxState.start) > max) + { + const int cidx = GuiTextBoxGetByteIndex(text, guiTextBoxState.index, guiTextBoxState.start, guiTextBoxState.cursor); + int pos = 0; + guiTextBoxState.index = GuiMeasureTextBoxRev(text, cidx - 1, textRec, &pos); + guiTextBoxState.start = guiTextBoxState.cursor - pos; + } +} + +static inline void MoveTextBoxCursorLeft(const char* text) +{ + if (guiTextBoxState.cursor > 0) guiTextBoxState.cursor--; + + if (guiTextBoxState.cursor < guiTextBoxState.start) + { + int prev = 0; + int letter = GetPrevCodepoint(&text[guiTextBoxState.index - 1], text, &prev); + if (letter == 0x3f) prev = 1; + guiTextBoxState.start--; + guiTextBoxState.index -= prev; + } +} + +RAYGUIDEF int GuiTextBoxGetByteIndex(const char *text, int start, int from, int to) +{ + int i = start, k = from; + + while ((text[i] != '\0') && (k < to)) + { + int j = 0; + int letter = GetNextCodepoint(&text[i], &j); + + if (letter == 0x3f) j = 1; + i += j; + ++k; + } + + return i; +} + +RAYGUIDEF int GuiTextBoxDelete(char *text, int length, bool before) +{ + if ((guiTextBoxState.cursor != -1) && (text != NULL)) + { + int startIdx = 0, endIdx = 0; + if ((guiTextBoxState.select != -1) && (guiTextBoxState.select != guiTextBoxState.cursor)) + { + // Delete selection + int start = guiTextBoxState.cursor; + int end = guiTextBoxState.select; + + if (guiTextBoxState.cursor > guiTextBoxState.select) + { + start = guiTextBoxState.select; + end = guiTextBoxState.cursor; + } + + // Convert to byte indexes + startIdx = GuiTextBoxGetByteIndex(text, 0, 0, start); + endIdx = GuiTextBoxGetByteIndex(text, 0, 0, end); + + // Adjust text box state + guiTextBoxState.cursor = start; // Always set cursor to start of selection + if (guiTextBoxState.select < guiTextBoxState.start) guiTextBoxState.start = -1; // Force to recalculate on the next frame + } + else + { + if (before) + { + // Delete character before cursor + if (guiTextBoxState.cursor != 0) + { + endIdx = GuiTextBoxGetByteIndex(text, 0, 0, guiTextBoxState.cursor); + guiTextBoxState.cursor--; + startIdx = GuiTextBoxGetByteIndex(text, 0, 0, guiTextBoxState.cursor); + + if (guiTextBoxState.cursor < guiTextBoxState.start) guiTextBoxState.start = -1; // Force to recalculate on the next frame + } + } + else + { + // Delete character after cursor + if (guiTextBoxState.cursor + 1 <= GuiCountCodepointsUntilNewline(text)) + { + startIdx = GuiTextBoxGetByteIndex(text, 0, 0, guiTextBoxState.cursor); + endIdx = GuiTextBoxGetByteIndex(text, 0, 0, guiTextBoxState.cursor+1); + } + } + } + + memmove(&text[startIdx], &text[endIdx], length - endIdx); + text[length - (endIdx - startIdx)] = '\0'; + guiTextBoxState.select = -1; // Always deselect + + return (endIdx - startIdx); + } + + return 0; +} + +RAYGUIDEF void GuiTextBoxSelectAll(const char *text) +{ + guiTextBoxState.cursor = GuiCountCodepointsUntilNewline(text); + + if (guiTextBoxState.cursor > 0) + { + guiTextBoxState.select = 0; + guiTextBoxState.start = -1; // Force recalculate on the next frame + } + else guiTextBoxState.select = -1; +} + +RAYGUIDEF void GuiTextBoxCopy(const char *text) +{ + if ((text != NULL) && + (guiTextBoxState.select != -1) && + (guiTextBoxState.cursor != -1) && + (guiTextBoxState.select != guiTextBoxState.cursor)) + { + int start = guiTextBoxState.cursor; + int end = guiTextBoxState.select; + + if (guiTextBoxState.cursor > guiTextBoxState.select) + { + start = guiTextBoxState.select; + end = guiTextBoxState.cursor; + } + + // Convert to byte indexes + start = GuiTextBoxGetByteIndex(text, 0, 0, start); + end = GuiTextBoxGetByteIndex(text, 0, 0, end); + + // FIXME: `TextSubtext()` only lets use copy MAX_TEXT_BUFFER_LENGTH (1024) bytes + // maybe modify `SetClipboardText()` so we can use it only on part of a string + const char *clipText = TextSubtext(text, start, end - start); + + SetClipboardText(clipText); + } +} + +// Paste text from clipboard into the active textbox. +// `text` is the pointer to the buffer used by the textbox while `textSize` is the text buffer max size +RAYGUIDEF void GuiTextBoxPaste(char *text, int textSize) +{ + const char *clipText = GetClipboardText(); // GLFW guaratees this should be UTF8 encoded! + int length = strlen(text); + + if ((text != NULL) && (clipText != NULL) && (guiTextBoxState.cursor != -1)) + { + if ((guiTextBoxState.select != -1) && (guiTextBoxState.select != guiTextBoxState.cursor)) + { + // If there's a selection we'll have to delete it first + length -= GuiTextBoxDelete(text, length, true); + } + + int clipLen = strlen(clipText); // We want the length in bytes + + // Calculate how many bytes can we copy from clipboard text before we run out of space + int size = ((length + clipLen) <= textSize) ? clipLen : textSize - length; + + // Make room by shifting to right the bytes after cursor + int startIdx = GuiTextBoxGetByteIndex(text, 0, 0, guiTextBoxState.cursor); + int endIdx = startIdx + size; + memmove(&text[endIdx], &text[startIdx], length - startIdx); + text[length + size] = '\0'; // Set the NULL char + + // At long last copy the clipboard text + memcpy(&text[startIdx], clipText, size); + + // Set cursor position at the end of the pasted text + guiTextBoxState.cursor = 0; + + for (int i = 0; i < (startIdx + size); guiTextBoxState.cursor++) + { + int next = 0; + int letter = GetNextCodepoint(&text[i], &next); + if (letter != 0x3f) i += next; + else i += 1; + } + + guiTextBoxState.start = -1; // Force to recalculate on the next frame + } +} + +RAYGUIDEF void GuiTextBoxCut(char* text) +{ + if ((text != NULL) && + (guiTextBoxState.select != -1) && + (guiTextBoxState.cursor != -1) && + (guiTextBoxState.select != guiTextBoxState.cursor)) + { + // First copy selection to clipboard; + int start = guiTextBoxState.cursor, end = guiTextBoxState.select; + + if (guiTextBoxState.cursor > guiTextBoxState.select) + { + start = guiTextBoxState.select; + end = guiTextBoxState.cursor; + } + + // Convert to byte indexes + int startIdx = GuiTextBoxGetByteIndex(text, 0, 0, start); + int endIdx = GuiTextBoxGetByteIndex(text, 0, 0, end); + + // FIXME: `TextSubtext()` only lets use copy MAX_TEXT_BUFFER_LENGTH (1024) bytes + // maybe modify `SetClipboardText()` so we can use it only on parts of a string + const char *clipText = TextSubtext(text, startIdx, endIdx - startIdx); + SetClipboardText(clipText); + + // Now delete selection (copy data over it) + int len = strlen(text); + memmove(&text[startIdx], &text[endIdx], len - endIdx); + text[len - (endIdx - startIdx)] = '\0'; + + // Adjust text box state + guiTextBoxState.cursor = start; // Always set cursor to start of selection + if (guiTextBoxState.select < guiTextBoxState.start) guiTextBoxState.start = -1; // Force to recalculate + guiTextBoxState.select = -1; // Deselect + } +} + +static int EncodeCodepoint(unsigned int c, char out[5]) +{ + int len = 0; + if (c <= 0x7f) + { + out[0] = (char)c; + len = 1; + } + else if (c <= 0x7ff) + { + out[0] = (char)(((c >> 6) & 0x1f) | 0xc0); + out[1] = (char)((c & 0x3f) | 0x80); + len = 2; + } + else if (c <= 0xffff) + { + out[0] = (char)(((c >> 12) & 0x0f) | 0xe0); + out[1] = (char)(((c >> 6) & 0x3f) | 0x80); + out[2] = (char)((c & 0x3f) | 0x80); + len = 3; + } + else if (c <= 0x10ffff) + { + out[0] = (char)(((c >> 18) & 0x07) | 0xf0); + out[1] = (char)(((c >> 12) & 0x3f) | 0x80); + out[2] = (char)(((c >> 6) & 0x3f) | 0x80); + out[3] = (char)((c & 0x3f) | 0x80); + len = 4; + } + + out[len] = 0; + return len; +} + +// A text box control supporting text selection, cursor positioning and commonly used keyboard shortcuts. +// NOTE 1: Requires static variables: framesCounter +// NOTE 2: Returns if KEY_ENTER pressed (useful for data validation) +RAYGUIDEF bool GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode) +{ + // Define the cursor movement/selection speed when movement keys are held/pressed + #define GUI_TEXTBOX_CURSOR_SPEED_MODIFIER 5 + + static int framesCounter = 0; // Required for blinking cursor + + GuiControlState state = guiState; + bool pressed = false; + + // Make sure length doesn't exceed `textSize`. `textSize` is actually the max amount of characters the textbox can handle. + int length = strlen(text); + if (length > textSize) + { + text[textSize] = '\0'; + length = textSize; + } + + // Make sure we have enough room to draw at least 1 character + if ((bounds.width - 2*GuiGetStyle(TEXTBOX, INNER_PADDING)) < GuiGetStyle(DEFAULT, TEXT_SIZE)) + { + bounds.width = GuiGetStyle(DEFAULT, TEXT_SIZE) + 2*GuiGetStyle(TEXTBOX, INNER_PADDING); + } + + // Center the text vertically + int verticalPadding = (bounds.height - 2*GuiGetStyle(TEXTBOX, BORDER_WIDTH) - GuiGetStyle(DEFAULT, TEXT_SIZE))/2; + + if (verticalPadding < 0) + { + // Make sure the height is sufficient + bounds.height = 2*GuiGetStyle(TEXTBOX, BORDER_WIDTH) + GuiGetStyle(DEFAULT, TEXT_SIZE); + verticalPadding = 0; + } + + // Calculate the drawing area for the text inside the control `bounds` + Rectangle textRec = { bounds.x + GuiGetStyle(TEXTBOX, BORDER_WIDTH) + GuiGetStyle(TEXTBOX, INNER_PADDING), + bounds.y + verticalPadding + GuiGetStyle(TEXTBOX, BORDER_WIDTH), + bounds.width - 2*(GuiGetStyle(TEXTBOX, INNER_PADDING) + GuiGetStyle(TEXTBOX, BORDER_WIDTH)), + GuiGetStyle(DEFAULT, TEXT_SIZE) }; + + Vector2 cursorPos = { textRec.x, textRec.y }; // This holds the coordinates inside textRec of the cursor at current position and will be recalculated later + bool active = GuiTextBoxIsActive(bounds); // Check if this textbox is the global active textbox + + int selStart = 0, selLength = 0, textStartIndex = 0; + + // Update control + //-------------------------------------------------------------------- + if ((state != GUI_STATE_DISABLED) && !guiLocked) + { + const Vector2 mousePoint = GetMousePosition(); + + if (editMode) + { + // Check if we are the global active textbox + // A textbox becomes active when the user clicks it :) + if (!active) + { + if (CheckCollisionPointRec(mousePoint, bounds) && + (IsMouseButtonPressed(MOUSE_LEFT_BUTTON) || IsMouseButtonPressed(MOUSE_RIGHT_BUTTON))) + { + // Hurray!!! we just became the active textbox + active = true; + GuiTextBoxSetActive(bounds); + } + } + else if (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_RIGHT_BUTTON)) + { + // When active and the right mouse is clicked outside the textbox we should deactivate it + GuiTextBoxSetActive(RAYGUI_CLITERAL(Rectangle){0,0,-1,-1}); // Set a dummy rect as the active textbox bounds + active = false; + } + + if (active) + { + state = GUI_STATE_PRESSED; + framesCounter++; + + // Make sure state doesn't have invalid values + if (guiTextBoxState.cursor > length) guiTextBoxState.cursor = -1; + if (guiTextBoxState.select > length) guiTextBoxState.select = -1; + if (guiTextBoxState.start > length) guiTextBoxState.start = -1; + + + // Check textbox state for changes and recalculate if necesary + if (guiTextBoxState.cursor == -1) + { + // Set cursor to last visible character in textbox + guiTextBoxState.cursor = GuiTextBoxMaxCharacters(text, length, textRec); + } + + if (guiTextBoxState.start == -1) + { + // Force recalculate text start position and text start index + + // NOTE: start and index are always in sync + // start will hold the starting character position from where the text will be drawn + // while index will hold the byte index inside the text for that character + + if (guiTextBoxState.cursor == 0) + { + guiTextBoxState.start = guiTextBoxState.index = 0; // No need to recalculate + } + else + { + int pos = 0; + int len = GuiTextBoxGetByteIndex(text, 0, 0, guiTextBoxState.cursor); + guiTextBoxState.index = GuiMeasureTextBoxRev(text, len, textRec, &pos); + guiTextBoxState.start = guiTextBoxState.cursor - pos + 1; + } + } + + // ----------------- + // HANDLE KEY INPUT + // ----------------- + // * -> | LSHIFT + -> move cursor to the right | increase selection by one + // * <- | LSHIFT + <- move cursor to the left | decrease selection by one + // * HOME | LSHIFT + HOME moves cursor to start of text | selects text from cursor to start of text + // * END | LSHIFT + END move cursor to end of text | selects text from cursor until end of text + // * CTRL + A select all characters in text + // * CTRL + C copy selected text + // * CTRL + X cut selected text + // * CTRL + V remove selected text, if any, then paste clipboard data + // * DEL delete character or selection after cursor + // * BACKSPACE delete character or selection before cursor + // TODO: Add more shortcuts (insert mode, select word, moveto/select prev/next word ...) + if (IsKeyPressed(KEY_RIGHT) || + (IsKeyDown(KEY_RIGHT) && (framesCounter%GUI_TEXTBOX_CURSOR_SPEED_MODIFIER == 0))) + { + if (IsKeyDown(KEY_LEFT_SHIFT)) + { + // Selecting + if (guiTextBoxState.select == -1) guiTextBoxState.select = guiTextBoxState.cursor; // Mark selection start + + MoveTextBoxCursorRight(text, length, textRec); + } + else + { + if (guiTextBoxState.select != -1 && guiTextBoxState.select != guiTextBoxState.cursor) + { + // Deselect and move cursor to end of selection + if (guiTextBoxState.cursor < guiTextBoxState.select) + { + guiTextBoxState.cursor = guiTextBoxState.select - 1; + MoveTextBoxCursorRight(text, length, textRec); + } + } + else + { + // Move cursor to the right + MoveTextBoxCursorRight(text, length, textRec); + } + + guiTextBoxState.select = -1; + } + + framesCounter = 0; + } + else if (IsKeyPressed(KEY_LEFT) || (IsKeyDown(KEY_LEFT) && (framesCounter%GUI_TEXTBOX_CURSOR_SPEED_MODIFIER == 0))) + { + if (IsKeyDown(KEY_LEFT_SHIFT)) + { + // Selecting + if (guiTextBoxState.select == -1) guiTextBoxState.select = guiTextBoxState.cursor; // Mark selection start + + MoveTextBoxCursorLeft(text); + } + else + { + if ((guiTextBoxState.select != -1) && (guiTextBoxState.select != guiTextBoxState.cursor)) + { + // Deselect and move cursor to start of selection + if (guiTextBoxState.cursor > guiTextBoxState.select) + { + guiTextBoxState.cursor = guiTextBoxState.select; + + if (guiTextBoxState.start > guiTextBoxState.cursor) + { + guiTextBoxState.start = guiTextBoxState.cursor; + guiTextBoxState.index = GuiTextBoxGetByteIndex(text, 0, 0, guiTextBoxState.start); // Recalculate byte index + } + } + } + else + { + // Move cursor to the left + MoveTextBoxCursorLeft(text); + } + + guiTextBoxState.select = -1; + } + + framesCounter = 0; + } + else if (IsKeyPressed(KEY_BACKSPACE) || (IsKeyDown(KEY_BACKSPACE) && (framesCounter%GUI_TEXTBOX_CURSOR_SPEED_MODIFIER) == 0)) + { + GuiTextBoxDelete(text, length, true); + } + else if (IsKeyPressed(KEY_DELETE) || (IsKeyDown(KEY_DELETE) && (framesCounter%GUI_TEXTBOX_CURSOR_SPEED_MODIFIER) == 0)) + { + GuiTextBoxDelete(text, length, false); + } + else if (IsKeyPressed(KEY_HOME)) + { + if (IsKeyDown(KEY_LEFT_SHIFT)) + { + // Select from start of text to cursor + if ((guiTextBoxState.select > guiTextBoxState.cursor) || + ((guiTextBoxState.select == -1) && (guiTextBoxState.cursor != 0))) + { + guiTextBoxState.select = guiTextBoxState.cursor; + } + } + else guiTextBoxState.select = -1; // Deselect everything + + // Move cursor to start of text + guiTextBoxState.cursor = guiTextBoxState.start = guiTextBoxState.index = 0; + framesCounter = 0; + } + else if (IsKeyPressed(KEY_END)) + { + int max = GuiCountCodepointsUntilNewline(text); + + if (IsKeyDown(KEY_LEFT_SHIFT)) + { + if ((guiTextBoxState.select == -1) && (guiTextBoxState.cursor != max)) + { + guiTextBoxState.select = guiTextBoxState.cursor; + } + } + else guiTextBoxState.select = -1; // Deselect everything + + int pos = 0; + guiTextBoxState.cursor = max; + int len = GuiTextBoxGetByteIndex(text, 0, 0, guiTextBoxState.cursor); + guiTextBoxState.index = GuiMeasureTextBoxRev(text, len, textRec, &pos); + guiTextBoxState.start = guiTextBoxState.cursor - pos + 1; + } + else if (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_A)) + { + // `CTRL + A` Select all + GuiTextBoxSelectAll(text); + } + else if (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_C)) + { + // `CTRL + C` Copy selected text to clipboard + GuiTextBoxCopy(text); + } + else if (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_X)) + { + // `CTRL + X` Cut selected text + GuiTextBoxCut(text); + } + else if (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_V)) + { + // `CTRL + V` Paste clipboard text + GuiTextBoxPaste(text, textSize); + } + else if (IsKeyPressed(KEY_ENTER)) + { + pressed = true; + } + else + { + int key = GetKeyPressed(); + if ((key >= 32) && ((guiTextBoxState.cursor + 1) < textSize)) + { + if ((guiTextBoxState.select != -1) && (guiTextBoxState.select != guiTextBoxState.cursor)) + { + // Delete selection + GuiTextBoxDelete(text, length, true); + } + + // Decode codepoint + char out[5] = {0}; + int sz = EncodeCodepoint(key, &out[0]); + + if (sz != 0) + { + int startIdx = GuiTextBoxGetByteIndex(text, 0, 0, guiTextBoxState.cursor); + int endIdx = startIdx + sz; + + if (endIdx <= textSize && length < textSize - 1) + { + guiTextBoxState.cursor++; + guiTextBoxState.select = -1; + memmove(&text[endIdx], &text[startIdx], length - startIdx); + memcpy(&text[startIdx], &out[0], sz); + length += sz; + text[length] = '\0'; + + if (guiTextBoxState.start != -1) + { + const int max = GuiTextBoxMaxCharacters(&text[guiTextBoxState.index], length - guiTextBoxState.index, textRec); + + if ((guiTextBoxState.cursor - guiTextBoxState.start) > max) guiTextBoxState.start = -1; + } + } + } + } + } + + // ------------- + // HANDLE MOUSE + // ------------- + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + if (CheckCollisionPointRec(mousePoint, textRec)) + { + GuiTextBoxGetCursorFromMouse(&text[guiTextBoxState.index], length - guiTextBoxState.index, textRec, &guiTextBoxState.cursor); + guiTextBoxState.cursor += guiTextBoxState.start; + guiTextBoxState.select = -1; + } + else + { + // Clicked outside the `textRec` but still inside bounds + if (mousePoint.x <= bounds.x+bounds.width/2) guiTextBoxState.cursor = 0 + guiTextBoxState.start; + else guiTextBoxState.cursor = guiTextBoxState.start + GuiTextBoxMaxCharacters(&text[guiTextBoxState.index], length - guiTextBoxState.index, textRec); + guiTextBoxState.select = -1; + } + } + else if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) + { + int cursor = guiTextBoxState.cursor - guiTextBoxState.start; + bool move = false; + if (CheckCollisionPointRec(mousePoint, textRec)) + { + GuiTextBoxGetCursorFromMouse(&text[guiTextBoxState.index], length - guiTextBoxState.index, textRec, &cursor); + } + else + { + // Clicked outside the `textRec` but still inside bounds, this means that we must move the text + move = true; + if (mousePoint.x > bounds.x+bounds.width/2) + { + cursor = GuiTextBoxMaxCharacters(&text[guiTextBoxState.index], length - guiTextBoxState.index, textRec); + } + } + + guiTextBoxState.cursor = cursor + guiTextBoxState.start; + + if (guiTextBoxState.select == -1) + { + // Mark start of selection + guiTextBoxState.select = guiTextBoxState.cursor; + } + + // Move the text when cursor is positioned before or after the text + if ((framesCounter%GUI_TEXTBOX_CURSOR_SPEED_MODIFIER) == 0 && move) + { + if (cursor == 0) MoveTextBoxCursorLeft(text); + else if (cursor == GuiTextBoxMaxCharacters(&text[guiTextBoxState.index], length - guiTextBoxState.index, textRec)) + { + MoveTextBoxCursorRight(text, length, textRec); + } + } + } + } + + // Calculate X coordinate of the blinking cursor + cursorPos.x = GuiTextBoxGetCursorCoordinates(&text[guiTextBoxState.index], length - guiTextBoxState.index, textRec, guiTextBoxState.cursor - guiTextBoxState.start); + + // Update variables + textStartIndex = guiTextBoxState.index; + + if (guiTextBoxState.select == -1) + { + selStart = guiTextBoxState.cursor; + selLength = 0; + } + else if (guiTextBoxState.cursor > guiTextBoxState.select) + { + selStart = guiTextBoxState.select; + selLength = guiTextBoxState.cursor - guiTextBoxState.select; + } + else + { + selStart = guiTextBoxState.cursor; + selLength = guiTextBoxState.select - guiTextBoxState.cursor; + } + + // We aren't drawing all of the text so make sure `DrawTextRecEx()` is selecting things correctly + if (guiTextBoxState.start > selStart) + { + selLength -= guiTextBoxState.start - selStart; + selStart = 0; + } + else selStart = selStart - guiTextBoxState.start; + } + else state = GUI_STATE_FOCUSED; + } + else + { + if (CheckCollisionPointRec(mousePoint, bounds)) + { + state = GUI_STATE_FOCUSED; + if (IsMouseButtonPressed(0)) pressed = true; + } + + if (active && IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_C)) + { + // If active copy all text to clipboard even when disabled + + // Backup textbox state + int select = guiTextBoxState.select; + int cursor = guiTextBoxState.cursor; + int start = guiTextBoxState.start; + if (guiTextBoxState.select == -1 || guiTextBoxState.select == guiTextBoxState.cursor) + { + // If no selection then mark all text to be copied to clipboard + GuiTextBoxSelectAll(text); + } + + GuiTextBoxCopy(text); + + // Restore textbox state + guiTextBoxState.select = select; + guiTextBoxState.cursor = cursor; + guiTextBoxState.start = start; + } + } + } + + // Draw control + //-------------------------------------------------------------------- + DrawRectangleLinesEx(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), guiAlpha)); + + if (state == GUI_STATE_PRESSED) + { + DrawRectangle(bounds.x + GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.height - 2*GuiGetStyle(TEXTBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_FOCUSED)), guiAlpha)); + if (editMode && active && ((framesCounter/TEXTEDIT_CURSOR_BLINK_FRAMES)%2 == 0) && selLength == 0) + { + // Draw the blinking cursor + DrawRectangle(cursorPos.x, cursorPos.y, 1, GuiGetStyle(DEFAULT, TEXT_SIZE), Fade(GetColor(GuiGetStyle(TEXTBOX, BORDER_COLOR_PRESSED)), guiAlpha)); + } + } + else if (state == GUI_STATE_DISABLED) + { + DrawRectangle(bounds.x + GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.height - 2*GuiGetStyle(TEXTBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_DISABLED)), guiAlpha)); + } + + // Finally draw the text and selection + DrawTextRecEx(guiFont, &text[textStartIndex], textRec, GuiGetStyle(DEFAULT, TEXT_SIZE), GuiGetStyle(DEFAULT, TEXT_SPACING), false, Fade(GetColor(GuiGetStyle(TEXTBOX, TEXT + (state*3))), guiAlpha), selStart, selLength, GetColor(GuiGetStyle(TEXTBOX, COLOR_SELECTED_FG)), GetColor(GuiGetStyle(TEXTBOX, COLOR_SELECTED_BG))); + + return pressed; +} +#else // !RAYGUI_TEXTBOX_EXTENDED + // Spinner control, returns selected value // NOTE: Requires static variables: framesCounter, valueSpeed - ERROR! RAYGUIDEF bool GuiSpinner(Rectangle bounds, int *value, int minValue, int maxValue, bool editMode) @@ -1401,10 +2511,10 @@ RAYGUIDEF bool GuiSpinner(Rectangle bounds, int *value, int minValue, int maxVal bool pressed = false; int tempValue = *value; - Rectangle spinner = { bounds.x + GuiGetStyle(TEXTBOX, SPINNER_BUTTON_WIDTH) + GuiGetStyle(TEXTBOX, SPINNER_BUTTON_PADDING), bounds.y, - bounds.width - 2*(GuiGetStyle(TEXTBOX, SPINNER_BUTTON_WIDTH) + GuiGetStyle(TEXTBOX, SPINNER_BUTTON_PADDING)), bounds.height }; - Rectangle leftButtonBound = { bounds.x, bounds.y, GuiGetStyle(TEXTBOX, SPINNER_BUTTON_WIDTH), bounds.height }; - Rectangle rightButtonBound = { bounds.x + bounds.width - GuiGetStyle(TEXTBOX, SPINNER_BUTTON_WIDTH), bounds.y, GuiGetStyle(TEXTBOX, SPINNER_BUTTON_WIDTH), bounds.height }; + Rectangle spinner = { bounds.x + GuiGetStyle(SPINNER, SELECT_BUTTON_WIDTH) + GuiGetStyle(SPINNER, SELECT_BUTTON_PADDING), bounds.y, + bounds.width - 2*(GuiGetStyle(SPINNER, SELECT_BUTTON_WIDTH) + GuiGetStyle(SPINNER, SELECT_BUTTON_PADDING)), bounds.height }; + Rectangle leftButtonBound = { (float)bounds.x, (float)bounds.y, (float)GuiGetStyle(SPINNER, SELECT_BUTTON_WIDTH), (float)bounds.height }; + Rectangle rightButtonBound = { (float)bounds.x + bounds.width - GuiGetStyle(SPINNER, SELECT_BUTTON_WIDTH), (float)bounds.y, (float)GuiGetStyle(SPINNER, SELECT_BUTTON_WIDTH), (float)bounds.height }; // Update control //-------------------------------------------------------------------- @@ -1417,12 +2527,13 @@ RAYGUIDEF bool GuiSpinner(Rectangle bounds, int *value, int minValue, int maxVal // Draw control //-------------------------------------------------------------------- + // TODO: Set Spinner properties for ValueBox pressed = GuiValueBox(spinner, &tempValue, minValue, maxValue, editMode); // Draw value selector custom buttons // NOTE: BORDER_WIDTH and TEXT_ALIGNMENT forced values int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH); - GuiSetStyle(BUTTON, BORDER_WIDTH, GuiGetStyle(TEXTBOX, SPINNER_BUTTON_BORDER_WIDTH)); + GuiSetStyle(BUTTON, BORDER_WIDTH, GuiGetStyle(SPINNER, BORDER_WIDTH)); int tempTextAlign = GuiGetStyle(BUTTON, TEXT_ALIGNMENT); GuiSetStyle(BUTTON, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_CENTER); @@ -1476,7 +2587,7 @@ RAYGUIDEF bool GuiValueBox(Rectangle bounds, int *value, int minValue, int maxVa // Only allow keys in range [48..57] if (keyCount < VALUEBOX_MAX_CHARS) { - int maxWidth = (bounds.width - (GuiGetStyle(DEFAULT, INNER_PADDING)*2)); + int maxWidth = (bounds.width - (GuiGetStyle(VALUEBOX, INNER_PADDING)*2)); if (GetTextWidth(text) < maxWidth) { int key = GetKeyPressed(); @@ -1536,19 +2647,20 @@ RAYGUIDEF bool GuiValueBox(Rectangle bounds, int *value, int minValue, int maxVa // Draw control //-------------------------------------------------------------------- - DrawRectangleLinesEx(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), guiAlpha)); + DrawRectangleLinesEx(bounds, GuiGetStyle(VALUEBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(VALUEBOX, BORDER + (state*3))), guiAlpha)); if (state == GUI_STATE_PRESSED) { - DrawRectangle(bounds.x + GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.height - 2*GuiGetStyle(TEXTBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_FOCUSED)), guiAlpha)); - if (editMode && ((framesCounter/20)%2 == 0)) DrawRectangle(bounds.x + GetTextWidth(text)/2 + bounds.width/2 + 2, bounds.y + GuiGetStyle(TEXTBOX, INNER_PADDING), 1, bounds.height - GuiGetStyle(TEXTBOX, INNER_PADDING)*2, Fade(GetColor(GuiGetStyle(TEXTBOX, BORDER_COLOR_FOCUSED)), guiAlpha)); + DrawRectangle(bounds.x + GuiGetStyle(VALUEBOX, BORDER_WIDTH), bounds.y + GuiGetStyle(VALUEBOX, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(VALUEBOX, BORDER_WIDTH), bounds.height - 2*GuiGetStyle(VALUEBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_PRESSED)), guiAlpha)); + + if (editMode && ((framesCounter/20)%2 == 0)) DrawRectangle(bounds.x + GetTextWidth(text)/2 + bounds.width/2 + 2, bounds.y + GuiGetStyle(VALUEBOX, INNER_PADDING), 1, bounds.height - GuiGetStyle(VALUEBOX, INNER_PADDING)*2, Fade(GetColor(GuiGetStyle(VALUEBOX, BORDER_COLOR_PRESSED)), guiAlpha)); } else if (state == GUI_STATE_DISABLED) { - DrawRectangle(bounds.x + GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.height - 2*GuiGetStyle(TEXTBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_DISABLED)), guiAlpha)); + DrawRectangle(bounds.x + GuiGetStyle(VALUEBOX, BORDER_WIDTH), bounds.y + GuiGetStyle(VALUEBOX, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(VALUEBOX, BORDER_WIDTH), bounds.height - 2*GuiGetStyle(VALUEBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_DISABLED)), guiAlpha)); } - GuiDrawText(text, GetTextBounds(TEXTBOX, bounds), GuiGetStyle(TEXTBOX, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(TEXTBOX, TEXT + (state*3))), guiAlpha)); + GuiDrawText(text, GetTextBounds(VALUEBOX, bounds), GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(VALUEBOX, TEXT + (state*3))), guiAlpha)); //-------------------------------------------------------------------- return pressed; @@ -1590,6 +2702,7 @@ RAYGUIDEF bool GuiTextBox(Rectangle bounds, char *text, int textSize, bool editM { text[keyCount] = (char)key; keyCount++; + text[keyCount] = '\0'; } } } @@ -1636,11 +2749,10 @@ RAYGUIDEF bool GuiTextBox(Rectangle bounds, char *text, int textSize, bool editM if (state == GUI_STATE_PRESSED) { - DrawRectangle(bounds.x + GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.height - 2*GuiGetStyle(TEXTBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_FOCUSED)), guiAlpha)); - + DrawRectangle(bounds.x + GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.height - 2*GuiGetStyle(TEXTBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_PRESSED)), guiAlpha)); + // Draw blinking cursor - // TODO: Consider TEXTBOX TEXT_ALIGNMENT - if (editMode && ((framesCounter/20)%2 == 0)) DrawRectangle(bounds.x + GuiGetStyle(TEXTBOX, INNER_PADDING) + GetTextWidth(text) + 2, bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE), 1, GuiGetStyle(DEFAULT, TEXT_SIZE)*2, Fade(GetColor(GuiGetStyle(TEXTBOX, BORDER_COLOR_PRESSED)), guiAlpha)); + if (editMode && ((framesCounter/20)%2 == 0)) DrawRectangle(bounds.x + GuiGetStyle(TEXTBOX, INNER_PADDING) + GetTextWidth(text) + 2 + bounds.width/2*GuiGetStyle(TEXTBOX, TEXT_ALIGNMENT), bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE), 1, GuiGetStyle(DEFAULT, TEXT_SIZE)*2, Fade(GetColor(GuiGetStyle(TEXTBOX, BORDER_COLOR_PRESSED)), guiAlpha)); } else if (state == GUI_STATE_DISABLED) { @@ -1652,6 +2764,7 @@ RAYGUIDEF bool GuiTextBox(Rectangle bounds, char *text, int textSize, bool editM return pressed; } +#endif // Text Box control with multiple lines RAYGUIDEF bool GuiTextBoxMulti(Rectangle bounds, char *text, int textSize, bool editMode) @@ -1665,9 +2778,6 @@ RAYGUIDEF bool GuiTextBoxMulti(Rectangle bounds, char *text, int textSize, bool int currentLine = 0; //const char *numChars = NULL; - // Security check because font is used directly in this control - if (guiFont.texture.id == 0) guiFont = GetFontDefault(); - // Update control //-------------------------------------------------------------------- if ((state != GUI_STATE_DISABLED) && !guiLocked) @@ -1825,7 +2935,7 @@ RAYGUIDEF bool GuiTextBoxMulti(Rectangle bounds, char *text, int textSize, bool if (state == GUI_STATE_PRESSED) { - DrawRectangle(bounds.x + GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.height - 2*GuiGetStyle(TEXTBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_FOCUSED)), guiAlpha)); + DrawRectangle(bounds.x + GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(TEXTBOX, BORDER_WIDTH), bounds.height - 2*GuiGetStyle(TEXTBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_PRESSED)), guiAlpha)); if (editMode) { @@ -1842,7 +2952,7 @@ RAYGUIDEF bool GuiTextBoxMulti(Rectangle bounds, char *text, int textSize, bool } // Draw characters counter - //GuiDrawText(numChars, (Vector2){ bounds.x + bounds.width - GetTextWidth(numChars) - GuiGetStyle(TEXTBOX, INNER_PADDING), bounds.y + bounds.height - GuiGetStyle(DEFAULT, TEXT_SIZE) - GuiGetStyle(TEXTBOX, INNER_PADDING) }, Fade(GetColor(GuiGetStyle(TEXTBOX, TEXT_COLOR_PRESSED)), guiAlpha/2)); + //GuiDrawText(numChars, RAYGUI_CLITERAL(Vector2){ bounds.x + bounds.width - GetTextWidth(numChars) - GuiGetStyle(TEXTBOX, INNER_PADDING), bounds.y + bounds.height - GuiGetStyle(DEFAULT, TEXT_SIZE) - GuiGetStyle(TEXTBOX, INNER_PADDING) }, Fade(GetColor(GuiGetStyle(TEXTBOX, TEXT_COLOR_PRESSED)), guiAlpha/2)); } } else if (state == GUI_STATE_DISABLED) @@ -1908,7 +3018,7 @@ RAYGUIDEF float GuiSliderPro(Rectangle bounds, const char *text, float value, fl if (value > maxValue) value = maxValue; else if (value < minValue) value = minValue; } - + // Bar limits check if (sliderWidth > 0) // Slider { @@ -1925,14 +3035,17 @@ RAYGUIDEF float GuiSliderPro(Rectangle bounds, const char *text, float value, fl //-------------------------------------------------------------------- DrawRectangleLinesEx(bounds, GuiGetStyle(SLIDER, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(SLIDER, BORDER + (state*3))), guiAlpha)); DrawRectangle(bounds.x + GuiGetStyle(SLIDER, BORDER_WIDTH), bounds.y + GuiGetStyle(SLIDER, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH), bounds.height - 2*GuiGetStyle(SLIDER, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(SLIDER, (state != GUI_STATE_DISABLED)? BASE_COLOR_NORMAL : BASE_COLOR_DISABLED)), guiAlpha)); - DrawRectangleRec(slider, Fade(GetColor(GuiGetStyle(SLIDER, (state == GUI_STATE_NORMAL)? BASE_COLOR_PRESSED : (BASE + (state*3)))), guiAlpha)); + + // Draw slider internal bar (depends on state) + if ((state == GUI_STATE_NORMAL) || (state == GUI_STATE_PRESSED)) DrawRectangleRec(slider, Fade(GetColor(GuiGetStyle(SLIDER, BASE_COLOR_PRESSED)), guiAlpha)); + else if (state == GUI_STATE_FOCUSED) DrawRectangleRec(slider, Fade(GetColor(GuiGetStyle(SLIDER, TEXT_COLOR_FOCUSED)), guiAlpha)); GuiDrawText(text, textBounds, GuiGetStyle(SLIDER, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(SLIDER, TEXT + (state*3))), guiAlpha)); // TODO: Review showValue parameter, really ugly... - if (showValue) GuiDrawText(TextFormat("%.02f", value), (Rectangle){ bounds.x + bounds.width + GuiGetStyle(SLIDER, TEXT_PADDING), - bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2 + GuiGetStyle(SLIDER, INNER_PADDING), - GuiGetStyle(DEFAULT, TEXT_SIZE), GuiGetStyle(DEFAULT, TEXT_SIZE) }, GUI_TEXT_ALIGN_LEFT, + if (showValue) GuiDrawText(TextFormat("%.02f", value), RAYGUI_CLITERAL(Rectangle){ (float)bounds.x + bounds.width + GuiGetStyle(SLIDER, TEXT_PADDING), + (float)bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2 + GuiGetStyle(SLIDER, INNER_PADDING), + (float)GuiGetStyle(DEFAULT, TEXT_SIZE), (float)GuiGetStyle(DEFAULT, TEXT_SIZE) }, GUI_TEXT_ALIGN_LEFT, Fade(GetColor(GuiGetStyle(SLIDER, TEXT + (state*3))), guiAlpha)); //-------------------------------------------------------------------- @@ -1967,11 +3080,13 @@ RAYGUIDEF float GuiProgressBar(Rectangle bounds, const char *text, float value, // Draw control //-------------------------------------------------------------------- - if (showValue) GuiLabel((Rectangle){ bounds.x + bounds.width + GuiGetStyle(SLIDER, TEXT_PADDING), bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2 + GuiGetStyle(SLIDER, INNER_PADDING), GuiGetStyle(DEFAULT, TEXT_SIZE), GuiGetStyle(DEFAULT, TEXT_SIZE) }, TextFormat("%.02f", value)); + if (showValue) GuiLabel(RAYGUI_CLITERAL(Rectangle){ (float)bounds.x + bounds.width + GuiGetStyle(SLIDER, TEXT_PADDING), (float)bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2 + GuiGetStyle(SLIDER, INNER_PADDING), (float)GuiGetStyle(DEFAULT, TEXT_SIZE), (float)GuiGetStyle(DEFAULT, TEXT_SIZE) }, TextFormat("%.02f", value)); - DrawRectangleLinesEx(bounds, GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(PROGRESSBAR, (state != GUI_STATE_DISABLED)? BORDER_COLOR_NORMAL : BORDER_COLOR_DISABLED)), guiAlpha)); - DrawRectangle(bounds.x + GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.y + GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.height - 2*GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)), guiAlpha)); - DrawRectangleRec(progress, Fade(GetColor(GuiGetStyle(PROGRESSBAR, (state != GUI_STATE_DISABLED)? BASE_COLOR_NORMAL : BASE_COLOR_DISABLED)), guiAlpha)); + DrawRectangleLinesEx(bounds, GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(PROGRESSBAR, BORDER + (state*3))), guiAlpha)); + + // Draw slider internal progress bar (depends on state) + if ((state == GUI_STATE_NORMAL) || (state == GUI_STATE_PRESSED)) DrawRectangleRec(progress, Fade(GetColor(GuiGetStyle(PROGRESSBAR, BASE_COLOR_PRESSED)), guiAlpha)); + else if (state == GUI_STATE_FOCUSED) DrawRectangleRec(progress, Fade(GetColor(GuiGetStyle(PROGRESSBAR, TEXT_COLOR_FOCUSED)), guiAlpha)); //-------------------------------------------------------------------- return value; @@ -1985,7 +3100,7 @@ RAYGUIDEF void GuiStatusBar(Rectangle bounds, const char *text) // Draw control //-------------------------------------------------------------------- DrawRectangleLinesEx(bounds, GuiGetStyle(DEFAULT, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(DEFAULT, (state != GUI_STATE_DISABLED)? BORDER_COLOR_NORMAL : BORDER_COLOR_DISABLED)), guiAlpha)); - DrawRectangleRec((Rectangle){ bounds.x + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.width - GuiGetStyle(DEFAULT, BORDER_WIDTH)*2, bounds.height - GuiGetStyle(DEFAULT, BORDER_WIDTH)*2 }, Fade(GetColor(GuiGetStyle(DEFAULT, (state != GUI_STATE_DISABLED)? BASE_COLOR_NORMAL : BASE_COLOR_DISABLED)), guiAlpha)); + DrawRectangleRec(RAYGUI_CLITERAL(Rectangle){ bounds.x + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.width - GuiGetStyle(DEFAULT, BORDER_WIDTH)*2, bounds.height - GuiGetStyle(DEFAULT, BORDER_WIDTH)*2 }, Fade(GetColor(GuiGetStyle(DEFAULT, (state != GUI_STATE_DISABLED)? BASE_COLOR_NORMAL : BASE_COLOR_DISABLED)), guiAlpha)); GuiDrawText(text, GetTextBounds(DEFAULT, bounds), GuiGetStyle(DEFAULT, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(DEFAULT, (state != GUI_STATE_DISABLED)? TEXT_COLOR_NORMAL : TEXT_COLOR_DISABLED)), guiAlpha)); //-------------------------------------------------------------------- @@ -2028,14 +3143,17 @@ RAYGUIDEF int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxVal bool isVertical = (bounds.width > bounds.height)? false : true; // The size (width or height depending on scrollbar type) of the spinner buttons - const int spinnerSize = GuiGetStyle(SCROLLBAR, SHOW_SPINNER_BUTTONS)? (isVertical? bounds.width - 2 * GuiGetStyle(SCROLLBAR, BORDER_WIDTH) : bounds.height - 2 * GuiGetStyle(SCROLLBAR, BORDER_WIDTH)) : 0; + const int spinnerSize = GuiGetStyle(SCROLLBAR, ARROWS_VISIBLE)? (isVertical? bounds.width - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH) : bounds.height - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH)) : 0; - // Spinner buttons [<] [>] [∧] [∨] - Rectangle spinnerUpLeft, spinnerDownRight; - // Actual area of the scrollbar excluding the spinner buttons - Rectangle scrollbar; // ------------ + // Arrow buttons [<] [>] [∧] [∨] + Rectangle arrowUpLeft = { 0 }; + Rectangle arrowDownRight = { 0 }; + + // Actual area of the scrollbar excluding the arrow buttons + Rectangle scrollbar = { 0 }; + // Slider bar that moves --[///]----- - Rectangle slider; + Rectangle slider = { 0 }; // Normalize value if (value > maxValue) value = maxValue; @@ -2043,23 +3161,23 @@ RAYGUIDEF int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxVal const int range = maxValue - minValue; int sliderSize = GuiGetStyle(SCROLLBAR, SLIDER_SIZE); - + // Calculate rectangles for all of the components - spinnerUpLeft = (Rectangle){ bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH), bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH), spinnerSize, spinnerSize }; + arrowUpLeft = RAYGUI_CLITERAL(Rectangle){ (float)bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)spinnerSize, (float)spinnerSize }; if (isVertical) { - spinnerDownRight = (Rectangle){ bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH), bounds.y + bounds.height - spinnerSize - GuiGetStyle(SCROLLBAR, BORDER_WIDTH), spinnerSize, spinnerSize}; - scrollbar = (Rectangle){ bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, INNER_PADDING), spinnerUpLeft.y + spinnerUpLeft.height, bounds.width - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, INNER_PADDING)), bounds.height - spinnerUpLeft.height - spinnerDownRight.height - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH) }; + arrowDownRight = RAYGUI_CLITERAL(Rectangle){ (float)bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)bounds.y + bounds.height - spinnerSize - GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)spinnerSize, (float)spinnerSize}; + scrollbar = RAYGUI_CLITERAL(Rectangle){ bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, INNER_PADDING), arrowUpLeft.y + arrowUpLeft.height, bounds.width - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, INNER_PADDING)), bounds.height - arrowUpLeft.height - arrowDownRight.height - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH) }; sliderSize = (sliderSize >= scrollbar.height)? (scrollbar.height - 2) : sliderSize; // Make sure the slider won't get outside of the scrollbar - slider = (Rectangle){ bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SLIDER_PADDING),scrollbar.y + (int)(((float)(value - minValue)/range)*(scrollbar.height - sliderSize)),bounds.width - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SLIDER_PADDING)), sliderSize }; + slider = RAYGUI_CLITERAL(Rectangle){ (float)bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SLIDER_PADDING), (float)scrollbar.y + (int)(((float)(value - minValue)/range)*(scrollbar.height - sliderSize)), (float)bounds.width - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SLIDER_PADDING)), (float)sliderSize }; } else { - spinnerDownRight = (Rectangle){ bounds.x + bounds.width - spinnerSize - GuiGetStyle(SCROLLBAR, BORDER_WIDTH), bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH), spinnerSize, spinnerSize}; - scrollbar = (Rectangle){ spinnerUpLeft.x + spinnerUpLeft.width, bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, INNER_PADDING), bounds.width - spinnerUpLeft.width - spinnerDownRight.width - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH), bounds.height - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, INNER_PADDING))}; + arrowDownRight = RAYGUI_CLITERAL(Rectangle){ (float)bounds.x + bounds.width - spinnerSize - GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)spinnerSize, (float)spinnerSize}; + scrollbar = RAYGUI_CLITERAL(Rectangle){ arrowUpLeft.x + arrowUpLeft.width, bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, INNER_PADDING), bounds.width - arrowUpLeft.width - arrowDownRight.width - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH), bounds.height - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, INNER_PADDING))}; sliderSize = (sliderSize >= scrollbar.width)? (scrollbar.width - 2) : sliderSize; // Make sure the slider won't get outside of the scrollbar - slider = (Rectangle){ scrollbar.x + (int)(((float)(value - minValue)/range)*(scrollbar.width - sliderSize)), bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SLIDER_PADDING), sliderSize, bounds.height - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SLIDER_PADDING)) }; + slider = RAYGUI_CLITERAL(Rectangle){ (float)scrollbar.x + (int)(((float)(value - minValue)/range)*(scrollbar.width - sliderSize)), (float)bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SLIDER_PADDING), (float)sliderSize, (float)bounds.height - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SLIDER_PADDING)) }; } // Update control @@ -2078,8 +3196,8 @@ RAYGUIDEF int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxVal if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) { - if (CheckCollisionPointRec(mousePoint, spinnerUpLeft)) value -= range/GuiGetStyle(SCROLLBAR, SCROLL_SPEED); - else if (CheckCollisionPointRec(mousePoint, spinnerDownRight)) value += range/GuiGetStyle(SCROLLBAR, SCROLL_SPEED); + if (CheckCollisionPointRec(mousePoint, arrowUpLeft)) value -= range/GuiGetStyle(SCROLLBAR, SCROLL_SPEED); + else if (CheckCollisionPointRec(mousePoint, arrowDownRight)) value += range/GuiGetStyle(SCROLLBAR, SCROLL_SPEED); state = GUI_STATE_PRESSED; } @@ -2087,12 +3205,12 @@ RAYGUIDEF int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxVal { if (!isVertical) { - Rectangle scrollArea = { spinnerUpLeft.x + spinnerUpLeft.width, spinnerUpLeft.y, scrollbar.width, bounds.height - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH)}; + Rectangle scrollArea = { arrowUpLeft.x + arrowUpLeft.width, arrowUpLeft.y, scrollbar.width, bounds.height - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH)}; if (CheckCollisionPointRec(mousePoint, scrollArea)) value = ((float)(mousePoint.x - scrollArea.x - slider.width/2)*range)/(scrollArea.width - slider.width) + minValue; } else { - Rectangle scrollArea = { spinnerUpLeft.x, spinnerUpLeft.y+spinnerUpLeft.height, bounds.width - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH), scrollbar.height}; + Rectangle scrollArea = { arrowUpLeft.x, arrowUpLeft.y+arrowUpLeft.height, bounds.width - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH), scrollbar.height}; if (CheckCollisionPointRec(mousePoint, scrollArea)) value = ((float)(mousePoint.y - scrollArea.y - slider.height/2)*range)/(scrollArea.height - slider.height) + minValue; } } @@ -2104,7 +3222,6 @@ RAYGUIDEF int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxVal } //-------------------------------------------------------------------- - // Draw control //-------------------------------------------------------------------- DrawRectangleRec(bounds, Fade(GetColor(GuiGetStyle(DEFAULT, BORDER_COLOR_DISABLED)), guiAlpha)); // Draw the background @@ -2114,54 +3231,44 @@ RAYGUIDEF int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxVal DrawRectangleRec(slider, Fade(GetColor(GuiGetStyle(SLIDER, BORDER + state*3)), guiAlpha)); // Draw the slider bar - // Draw arrows using lines + // Draw arrows const int padding = (spinnerSize - GuiGetStyle(SCROLLBAR, ARROWS_SIZE))/2; const Vector2 lineCoords[] = { - //coordinates for < 0,1,2 - {spinnerUpLeft.x + padding, spinnerUpLeft.y + spinnerSize/2}, - {spinnerUpLeft.x + spinnerSize - padding, spinnerUpLeft.y + padding }, - {spinnerUpLeft.x + spinnerSize - padding, spinnerUpLeft.y + spinnerSize - padding}, + // Coordinates for < 0,1,2 + { arrowUpLeft.x + padding, arrowUpLeft.y + spinnerSize/2 }, + { arrowUpLeft.x + spinnerSize - padding, arrowUpLeft.y + padding }, + { arrowUpLeft.x + spinnerSize - padding, arrowUpLeft.y + spinnerSize - padding }, - //coordinates for > 3,4,5 - {spinnerDownRight.x + padding, spinnerDownRight.y + padding}, - {spinnerDownRight.x + spinnerSize - padding, spinnerDownRight.y + spinnerSize/2 }, - {spinnerDownRight.x + padding, spinnerDownRight.y + spinnerSize - padding}, + // Coordinates for > 3,4,5 + { arrowDownRight.x + padding, arrowDownRight.y + padding }, + { arrowDownRight.x + spinnerSize - padding, arrowDownRight.y + spinnerSize/2 }, + { arrowDownRight.x + padding, arrowDownRight.y + spinnerSize - padding }, - //coordinates for ∧ 6,7,8 - {spinnerUpLeft.x + spinnerSize/2, spinnerUpLeft.y + padding}, - {spinnerUpLeft.x + padding, spinnerUpLeft.y + spinnerSize - padding}, - {spinnerUpLeft.x + spinnerSize - padding, spinnerUpLeft.y + spinnerSize - padding}, + // Coordinates for ∧ 6,7,8 + { arrowUpLeft.x + spinnerSize/2, arrowUpLeft.y + padding }, + { arrowUpLeft.x + padding, arrowUpLeft.y + spinnerSize - padding }, + { arrowUpLeft.x + spinnerSize - padding, arrowUpLeft.y + spinnerSize - padding }, - //coordinates for ∨ 9,10,11 - {spinnerDownRight.x + padding, spinnerDownRight.y + padding}, - {spinnerDownRight.x + spinnerSize/2, spinnerDownRight.y + spinnerSize - padding }, - {spinnerDownRight.x + spinnerSize - padding, spinnerDownRight.y + padding} + // Coordinates for ∨ 9,10,11 + { arrowDownRight.x + padding, arrowDownRight.y + padding }, + { arrowDownRight.x + spinnerSize/2, arrowDownRight.y + spinnerSize - padding }, + { arrowDownRight.x + spinnerSize - padding, arrowDownRight.y + padding } }; Color lineColor = Fade(GetColor(GuiGetStyle(BUTTON, TEXT + state*3)), guiAlpha); - if (GuiGetStyle(SCROLLBAR, SHOW_SPINNER_BUTTONS)) + if (GuiGetStyle(SCROLLBAR, ARROWS_VISIBLE)) { if (isVertical) { - // Draw ∧ - DrawLineEx(lineCoords[6], lineCoords[7], 3.0f, lineColor); - DrawLineEx(lineCoords[6], lineCoords[8], 3.0f, lineColor); - - // Draw ∨ - DrawLineEx(lineCoords[9], lineCoords[10], 3.0f, lineColor); - DrawLineEx(lineCoords[11], lineCoords[10], 3.0f, lineColor); + DrawTriangle(lineCoords[6], lineCoords[7], lineCoords[8], lineColor); + DrawTriangle(lineCoords[9], lineCoords[10], lineCoords[11], lineColor); } else { - // Draw < - DrawLineEx(lineCoords[0], lineCoords[1], 3.0f, lineColor); - DrawLineEx(lineCoords[0], lineCoords[2], 3.0f, lineColor); - - // Draw > - DrawLineEx(lineCoords[3], lineCoords[4], 3.0f, lineColor); - DrawLineEx(lineCoords[5], lineCoords[4], 3.0f, lineColor); + DrawTriangle(lineCoords[2], lineCoords[1], lineCoords[0], lineColor); + DrawTriangle(lineCoords[5], lineCoords[4], lineCoords[3], lineColor); } } //-------------------------------------------------------------------- @@ -2294,12 +3401,12 @@ RAYGUIDEF bool GuiListViewEx(Rectangle bounds, const char **text, int count, int elementWidth = bounds.width - GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH) - 2*GuiGetStyle(LISTVIEW, ELEMENTS_PADDING) - GuiGetStyle(DEFAULT, BORDER_WIDTH); } - Rectangle scrollBarRect = { bounds.x + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH), bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) }; + Rectangle scrollBarRect = { (float)bounds.x + GuiGetStyle(DEFAULT, BORDER_WIDTH), (float)bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), (float)GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH), (float)bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) }; if (GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_RIGHT_SIDE) scrollBarRect.x = posX + elementWidth + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING); // Area without the scrollbar - Rectangle viewArea = { posX, bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), elementWidth, bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) }; + Rectangle viewArea = { (float)posX, (float)bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), (float)elementWidth, (float)bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) }; if ((state != GUI_STATE_DISABLED) && !guiLocked) // && !guiLocked { @@ -2389,7 +3496,7 @@ RAYGUIDEF bool GuiListViewEx(Rectangle bounds, const char **text, int count, int // Get focused element for (int i = startIndex; i < endIndex; i++) { - if (CheckCollisionPointRec(mousePoint, (Rectangle){ posX, bounds.y + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH) + (i - startIndex)*(GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING)), elementWidth, GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) })) + if (CheckCollisionPointRec(mousePoint, RAYGUI_CLITERAL(Rectangle){ (float)posX, (float)bounds.y + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH) + (i - startIndex)*(GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING)), (float)elementWidth, (float)GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) })) { focusElement = i; } @@ -2397,7 +3504,7 @@ RAYGUIDEF bool GuiListViewEx(Rectangle bounds, const char **text, int count, int } const int slider = GuiGetStyle(SCROLLBAR, SLIDER_SIZE); // Save default slider size - + // Calculate percentage of visible elements and apply same percentage to scrollbar if (useScrollBar) { @@ -2455,16 +3562,16 @@ RAYGUIDEF bool GuiListViewEx(Rectangle bounds, const char **text, int count, int if ((enabled != NULL) && (enabled[i] == 0)) { GuiDisable(); - GuiListElement((Rectangle){ posX, bounds.y + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH) + (i - startIndex)*(GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING)), elementWidth, GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) }, text[i], false, false); + GuiListElement(RAYGUI_CLITERAL(Rectangle){ (float)posX, (float)bounds.y + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH) + (i - startIndex)*(GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING)), (float)elementWidth, (float)GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) }, text[i], false, false); GuiEnable(); } else if (i == auxActive) { GuiDisable(); - GuiListElement((Rectangle){ posX, bounds.y + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH) + (i - startIndex)*(GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING)), elementWidth, GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) }, text[i], true, false); + GuiListElement(RAYGUI_CLITERAL(Rectangle){ (float)posX, (float)bounds.y + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH) + (i - startIndex)*(GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING)), (float)elementWidth, (float)GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) }, text[i], true, false); GuiEnable(); } - else GuiListElement((Rectangle){ posX, bounds.y + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH) + (i - startIndex)*(GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING)), elementWidth, GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) }, text[i], false, false); + else GuiListElement(RAYGUI_CLITERAL(Rectangle){ (float)posX, (float)bounds.y + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH) + (i - startIndex)*(GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING)), (float)elementWidth, (float)GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) }, text[i], false, false); } } break; case GUI_STATE_FOCUSED: @@ -2474,11 +3581,11 @@ RAYGUIDEF bool GuiListViewEx(Rectangle bounds, const char **text, int count, int if ((enabled != NULL) && (enabled[i] == 0)) { GuiDisable(); - GuiListElement((Rectangle){ posX, bounds.y + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH) + (i - startIndex)*(GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING)), elementWidth, GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) }, text[i], false, false); + GuiListElement(RAYGUI_CLITERAL(Rectangle){ (float)posX, (float)bounds.y + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH) + (i - startIndex)*(GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING)), (float)elementWidth, (float)GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) }, text[i], false, false); GuiEnable(); } - else if (i == auxActive) GuiListElement((Rectangle){ posX, bounds.y + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH) + (i - startIndex)*(GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING)), elementWidth, GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) }, text[i], true, false); - else GuiListElement((Rectangle){ posX, bounds.y + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH) + (i - startIndex)*(GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING)), elementWidth, GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) }, text[i], false, false); + else if (i == auxActive) GuiListElement(RAYGUI_CLITERAL(Rectangle){ (float)posX, (float)bounds.y + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH) + (i - startIndex)*(GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING)), (float)elementWidth, (float)GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) }, text[i], true, false); + else GuiListElement(RAYGUI_CLITERAL(Rectangle){ (float)posX, (float)bounds.y + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH) + (i - startIndex)*(GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING)), (float)elementWidth, (float)GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) }, text[i], false, false); } } break; case GUI_STATE_PRESSED: @@ -2488,16 +3595,16 @@ RAYGUIDEF bool GuiListViewEx(Rectangle bounds, const char **text, int count, int if ((enabled != NULL) && (enabled[i] == 0)) { GuiDisable(); - GuiListElement((Rectangle){ posX, bounds.y + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH) + (i - startIndex)*(GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING)), elementWidth, GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) }, text[i], false, false); + GuiListElement(RAYGUI_CLITERAL(Rectangle){ (float)posX, (float)bounds.y + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH) + (i - startIndex)*(GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING)), (float)elementWidth, (float)GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) }, text[i], false, false); GuiEnable(); } else if ((i == auxActive) && editMode) { - if (GuiListElement((Rectangle){ posX, bounds.y + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH) + (i - startIndex)*(GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING)), elementWidth, GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) }, text[i], true, true) == false) auxActive = -1; + if (GuiListElement(RAYGUI_CLITERAL(Rectangle){ (float)posX, (float)bounds.y + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH) + (i - startIndex)*(GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING)), (float)elementWidth, (float)GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) }, text[i], true, true) == false) auxActive = -1; } else { - if (GuiListElement((Rectangle){ posX, bounds.y + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH) + (i - startIndex)*(GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING)), elementWidth, GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) }, text[i], false, true) == true) auxActive = i; + if (GuiListElement(RAYGUI_CLITERAL(Rectangle){ (float)posX, (float)bounds.y + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH) + (i - startIndex)*(GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING)), (float)elementWidth, (float)GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) }, text[i], false, true) == true) auxActive = i; } } } break; @@ -2505,8 +3612,8 @@ RAYGUIDEF bool GuiListViewEx(Rectangle bounds, const char **text, int count, int { for (int i = startIndex; i < endIndex; i++) { - if (i == auxActive) GuiListElement((Rectangle){ posX, bounds.y + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH) + (i - startIndex)*(GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING)), elementWidth, GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) }, text[i], true, false); - else GuiListElement((Rectangle){ posX, bounds.y + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH) + (i - startIndex)*(GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING)), elementWidth, GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) }, text[i], false, false); + if (i == auxActive) GuiListElement(RAYGUI_CLITERAL(Rectangle){ (float)posX, (float)bounds.y + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH) + (i - startIndex)*(GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING)), (float)elementWidth, (float)GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) }, text[i], true, false); + else GuiListElement(RAYGUI_CLITERAL(Rectangle){ (float)posX, (float)bounds.y + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH) + (i - startIndex)*(GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING)), (float)elementWidth, (float)GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) }, text[i], false, false); } } break; default: break; @@ -2521,7 +3628,7 @@ RAYGUIDEF bool GuiListViewEx(Rectangle bounds, const char **text, int count, int } // Color Panel control -RAYGUIDEF Color GuiColorPanel(Rectangle bounds, Color color) +RAYGUIDEF Color GuiColorPanelEx(Rectangle bounds, Color color, float hue) { GuiControlState state = guiState; Vector2 pickerSelector = { 0 }; @@ -2532,11 +3639,14 @@ RAYGUIDEF Color GuiColorPanel(Rectangle bounds, Color color) pickerSelector.x = bounds.x + (float)hsv.y*bounds.width; // HSV: Saturation pickerSelector.y = bounds.y + (1.0f - (float)hsv.z)*bounds.height; // HSV: Value - Vector3 maxHue = { hsv.x, 1.0f, 1.0f }; + Vector3 maxHue = { hue >= 0.0f ? hue : hsv.x, 1.0f, 1.0f }; Vector3 rgbHue = ConvertHSVtoRGB(maxHue); Color maxHueCol = { (unsigned char)(255.0f*rgbHue.x), (unsigned char)(255.0f*rgbHue.y), (unsigned char)(255.0f*rgbHue.z), 255 }; + + const Color colWhite = { 255, 255, 255, 255 }; + const Color colBlack = { 0, 0, 0, 255 }; // Update control //-------------------------------------------------------------------- @@ -2563,7 +3673,7 @@ RAYGUIDEF Color GuiColorPanel(Rectangle bounds, Color color) Vector3 rgb = ConvertHSVtoRGB(hsv); // NOTE: Vector3ToColor() only available on raylib 1.8.1 - color = (Color){ (unsigned char)(255.0f*rgb.x), + color = RAYGUI_CLITERAL(Color){ (unsigned char)(255.0f*rgb.x), (unsigned char)(255.0f*rgb.y), (unsigned char)(255.0f*rgb.z), (unsigned char)(255.0f*(float)color.a/255.0f) }; @@ -2578,23 +3688,28 @@ RAYGUIDEF Color GuiColorPanel(Rectangle bounds, Color color) //-------------------------------------------------------------------- if (state != GUI_STATE_DISABLED) { - DrawRectangleGradientEx(bounds, Fade(WHITE, guiAlpha), Fade(WHITE, guiAlpha), Fade(maxHueCol, guiAlpha), Fade(maxHueCol, guiAlpha)); - DrawRectangleGradientEx(bounds, Fade(BLACK, 0), Fade(BLACK, guiAlpha), Fade(BLACK, guiAlpha), Fade(BLACK, 0)); + DrawRectangleGradientEx(bounds, Fade(colWhite, guiAlpha), Fade(colWhite, guiAlpha), Fade(maxHueCol, guiAlpha), Fade(maxHueCol, guiAlpha)); + DrawRectangleGradientEx(bounds, Fade(colBlack, 0), Fade(colBlack, guiAlpha), Fade(colBlack, guiAlpha), Fade(colBlack, 0)); // Draw color picker: selector - DrawRectangle(pickerSelector.x - GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE)/2, pickerSelector.y - GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE)/2, GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE), GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE), Fade(WHITE, guiAlpha)); + DrawRectangle(pickerSelector.x - GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE)/2, pickerSelector.y - GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE)/2, GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE), GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE), Fade(colWhite, guiAlpha)); } else { - DrawRectangleGradientEx(bounds, Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), guiAlpha), Fade(Fade(BLACK, 0.6f), guiAlpha), Fade(Fade(BLACK, 0.6f), guiAlpha), Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), 0.6f), guiAlpha)); + DrawRectangleGradientEx(bounds, Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), guiAlpha), Fade(Fade(colBlack, 0.6f), guiAlpha), Fade(Fade(colBlack, 0.6f), guiAlpha), Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), 0.6f), guiAlpha)); } - DrawRectangleLines(bounds.x, bounds.y, bounds.width, bounds.height, Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), guiAlpha)); + DrawRectangleLinesEx(bounds, 1, Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), guiAlpha)); //-------------------------------------------------------------------- return color; } +RAYGUIDEF Color GuiColorPanel(Rectangle bounds, Color color) +{ + return GuiColorPanelEx(bounds, color, -1.0f); +} + // Color Bar Alpha control // NOTE: Returns alpha value normalized [0..1] RAYGUIDEF float GuiColorBarAlpha(Rectangle bounds, float alpha) @@ -2602,7 +3717,7 @@ RAYGUIDEF float GuiColorBarAlpha(Rectangle bounds, float alpha) #define COLORBARALPHA_CHECKED_SIZE 10 GuiControlState state = guiState; - Rectangle selector = { bounds.x + alpha*bounds.width - GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING), bounds.y - GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING), GuiGetStyle(COLORPICKER, BAR_SELECTOR_HEIGHT), bounds.height + GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING)*2 }; + Rectangle selector = { (float)bounds.x + alpha*bounds.width - GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING), (float)bounds.y - GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING), (float)GuiGetStyle(COLORPICKER, BAR_SELECTOR_HEIGHT), (float)bounds.height + GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING)*2 }; // Update control //-------------------------------------------------------------------- @@ -2630,25 +3745,33 @@ RAYGUIDEF float GuiColorBarAlpha(Rectangle bounds, float alpha) // Draw control //-------------------------------------------------------------------- + // Draw alpha bar: checked background if (state != GUI_STATE_DISABLED) { - for (int i = 0; i < bounds.width/COLORBARALPHA_CHECKED_SIZE; i++) DrawRectangle(bounds.x + COLORBARALPHA_CHECKED_SIZE*(i%((int)bounds.width/COLORBARALPHA_CHECKED_SIZE)), bounds.y, bounds.width/(bounds.width/COLORBARALPHA_CHECKED_SIZE), COLORBARALPHA_CHECKED_SIZE, (i%2)? Fade(Fade(GRAY, 0.4f), guiAlpha) : Fade(Fade(RAYWHITE, 0.4f), guiAlpha)); - for (int i = 0; i < bounds.width/COLORBARALPHA_CHECKED_SIZE; i++) DrawRectangle(bounds.x + COLORBARALPHA_CHECKED_SIZE*(i%((int)bounds.width/COLORBARALPHA_CHECKED_SIZE)), bounds.y + COLORBARALPHA_CHECKED_SIZE, bounds.width/(bounds.width/COLORBARALPHA_CHECKED_SIZE), COLORBARALPHA_CHECKED_SIZE, (i%2)? Fade(Fade(RAYWHITE, 0.4f), guiAlpha) : Fade(Fade(GRAY, 0.4f), guiAlpha)); - DrawRectangleGradientH(bounds.x, bounds.y, bounds.width, bounds.height, Fade((Color){ 255,255,255,0 }, guiAlpha), Fade((Color){ 0,0,0,255 }, guiAlpha)); - } - else DrawRectangleGradientH(bounds.x, bounds.y, bounds.width, bounds.height, Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), guiAlpha)); + int checksX = bounds.width/COLORBARALPHA_CHECKED_SIZE; + int checksY = bounds.height/COLORBARALPHA_CHECKED_SIZE; + + for (int x = 0; x < checksX; x++) + { + for (int y = 0; y < checksY; y++) + { + DrawRectangle(bounds.x + x*COLORBARALPHA_CHECKED_SIZE, + bounds.y + y*COLORBARALPHA_CHECKED_SIZE, + COLORBARALPHA_CHECKED_SIZE, COLORBARALPHA_CHECKED_SIZE, + ((x + y)%2)? Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), 0.4f), guiAlpha) : + Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.4f), guiAlpha)); + } + } - DrawRectangleLines(bounds.x, bounds.y, bounds.width, bounds.height, Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), guiAlpha)); - - switch (state) - { - case GUI_STATE_NORMAL: DrawRectangle(selector.x , selector.y, selector.width, selector.height, Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_PRESSED)), guiAlpha)); break; - case GUI_STATE_FOCUSED: DrawRectangle(selector.x, selector.y, selector.width, selector.height, Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_FOCUSED)), guiAlpha)); break; - case GUI_STATE_PRESSED: DrawRectangle(selector.x, selector.y, selector.width, selector.height, Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_PRESSED)), guiAlpha)); break; - case GUI_STATE_DISABLED: DrawRectangleRec(selector, Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), guiAlpha)); break; - default: break; + DrawRectangleGradientEx(bounds, RAYGUI_CLITERAL(Color){ 255, 255, 255, 0 }, RAYGUI_CLITERAL(Color){ 255, 255, 255, 0 }, Fade(RAYGUI_CLITERAL(Color){ 0, 0, 0, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 0, 0, 0, 255 }, guiAlpha)); } + else DrawRectangleGradientEx(bounds, Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), guiAlpha), Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), guiAlpha)); + + DrawRectangleLinesEx(bounds, 1, Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), guiAlpha)); + + // Draw alpha bar: selector + DrawRectangleRec(selector, Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), guiAlpha)); //-------------------------------------------------------------------- return alpha; @@ -2659,7 +3782,7 @@ RAYGUIDEF float GuiColorBarAlpha(Rectangle bounds, float alpha) RAYGUIDEF float GuiColorBarHue(Rectangle bounds, float hue) { GuiControlState state = guiState; - Rectangle selector = { bounds.x - GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING), bounds.y + hue/360.0f*bounds.height - GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING), bounds.width + GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING)*2, GuiGetStyle(COLORPICKER, BAR_SELECTOR_HEIGHT) }; + Rectangle selector = { (float)bounds.x - GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING), (float)bounds.y + hue/360.0f*bounds.height - GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING), (float)bounds.width + GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING)*2, (float)GuiGetStyle(COLORPICKER, BAR_SELECTOR_HEIGHT) }; // Update control //-------------------------------------------------------------------- @@ -2701,21 +3824,19 @@ RAYGUIDEF float GuiColorBarHue(Rectangle bounds, float hue) if (state != GUI_STATE_DISABLED) { // Draw hue bar:color bars - DrawRectangleGradientV(bounds.x + GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING)/2, bounds.y + GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING)/2, bounds.width - GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING), (int)bounds.height/6, Fade((Color){ 255,0,0,255 }, guiAlpha), Fade((Color){ 255,255,0,255 }, guiAlpha)); - DrawRectangleGradientV(bounds.x + GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING)/2, bounds.y + (int)bounds.height/6 + GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING)/2, bounds.width - GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING), (int)bounds.height/6, Fade((Color){ 255,255,0,255 }, guiAlpha), Fade((Color){ 0,255,0,255 }, guiAlpha)); - DrawRectangleGradientV(bounds.x + GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING)/2, bounds.y + 2*((int)bounds.height/6) + GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING)/2, bounds.width - GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING), (int)bounds.height/6, Fade((Color){ 0,255,0,255 }, guiAlpha), Fade((Color){ 0,255,255,255 }, guiAlpha)); - DrawRectangleGradientV(bounds.x + GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING)/2, bounds.y + 3*((int)bounds.height/6) + GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING)/2, bounds.width - GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING), (int)bounds.height/6, Fade((Color){ 0,255,255,255 }, guiAlpha), Fade((Color){ 0,0,255,255 }, guiAlpha)); - DrawRectangleGradientV(bounds.x + GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING)/2, bounds.y + 4*((int)bounds.height/6) + GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING)/2, bounds.width - GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING), (int)bounds.height/6, Fade((Color){ 0,0,255,255 }, guiAlpha), Fade((Color){ 255,0,255,255 }, guiAlpha)); - DrawRectangleGradientV(bounds.x + GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING)/2, bounds.y + 5*((int)bounds.height/6) + GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING)/2, bounds.width - GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING), (int)bounds.height/6 - GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING), Fade((Color){ 255,0,255,255 }, guiAlpha), Fade((Color){ 255,0,0,255 }, guiAlpha)); - } - else - { - DrawRectangleGradientV(bounds.x, bounds.y, bounds.width, bounds.height, Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), guiAlpha), Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), guiAlpha)); + DrawRectangleGradientV(bounds.x + GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING)/2, bounds.y + GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING)/2, bounds.width - GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING), (int)bounds.height/6, Fade(RAYGUI_CLITERAL(Color){ 255,0,0,255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 255,255,0,255 }, guiAlpha)); + DrawRectangleGradientV(bounds.x + GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING)/2, bounds.y + (int)bounds.height/6 + GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING)/2, bounds.width - GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING), (int)bounds.height/6, Fade(RAYGUI_CLITERAL(Color){ 255,255,0,255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 0,255,0,255 }, guiAlpha)); + DrawRectangleGradientV(bounds.x + GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING)/2, bounds.y + 2*((int)bounds.height/6) + GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING)/2, bounds.width - GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING), (int)bounds.height/6, Fade(RAYGUI_CLITERAL(Color){ 0,255,0,255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 0,255,255,255 }, guiAlpha)); + DrawRectangleGradientV(bounds.x + GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING)/2, bounds.y + 3*((int)bounds.height/6) + GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING)/2, bounds.width - GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING), (int)bounds.height/6, Fade(RAYGUI_CLITERAL(Color){ 0,255,255,255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 0,0,255,255 }, guiAlpha)); + DrawRectangleGradientV(bounds.x + GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING)/2, bounds.y + 4*((int)bounds.height/6) + GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING)/2, bounds.width - GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING), (int)bounds.height/6, Fade(RAYGUI_CLITERAL(Color){ 0,0,255,255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 255,0,255,255 }, guiAlpha)); + DrawRectangleGradientV(bounds.x + GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING)/2, bounds.y + 5*((int)bounds.height/6) + GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING)/2, bounds.width - GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING), (int)bounds.height/6 - GuiGetStyle(COLORPICKER, BAR_SELECTOR_PADDING), Fade(RAYGUI_CLITERAL(Color){ 255,0,255,255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 255,0,0,255 }, guiAlpha)); } + else DrawRectangleGradientV(bounds.x, bounds.y, bounds.width, bounds.height, Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), guiAlpha), Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), guiAlpha)); + + DrawRectangleLinesEx(bounds, 1, Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), guiAlpha)); // Draw hue bar: selector - DrawRectangleLines(bounds.x, bounds.y, bounds.width, bounds.height, Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), guiAlpha)); - DrawRectangle(selector.x, selector.y, selector.width, selector.height, Fade(GetColor(GuiGetStyle(COLORPICKER, (state == GUI_STATE_NORMAL)? BORDER_COLOR_PRESSED : (BORDER + state*3))), guiAlpha)); + DrawRectangleRec(selector, Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), guiAlpha)); //-------------------------------------------------------------------- return hue; @@ -2735,14 +3856,14 @@ RAYGUIDEF Color GuiColorPicker(Rectangle bounds, Color color) { color = GuiColorPanel(bounds, color); - Rectangle boundsHue = { bounds.x + bounds.width + GuiGetStyle(COLORPICKER, BAR_PADDING), bounds.y, GuiGetStyle(COLORPICKER, BAR_WIDTH), bounds.height }; + Rectangle boundsHue = { (float)bounds.x + bounds.width + GuiGetStyle(COLORPICKER, BAR_PADDING), (float)bounds.y, (float)GuiGetStyle(COLORPICKER, BAR_WIDTH), (float)bounds.height }; //Rectangle boundsAlpha = { bounds.x, bounds.y + bounds.height + GuiGetStyle(COLORPICKER, BARS_PADDING), bounds.width, GuiGetStyle(COLORPICKER, BARS_THICK) }; - Vector3 hsv = ConvertRGBtoHSV((Vector3){ color.r/255.0f, color.g/255.0f, color.b/255.0f }); + Vector3 hsv = ConvertRGBtoHSV(RAYGUI_CLITERAL(Vector3){ color.r/255.0f, color.g/255.0f, color.b/255.0f }); hsv.x = GuiColorBarHue(boundsHue, hsv.x); //color.a = (unsigned char)(GuiColorBarAlpha(boundsAlpha, (float)color.a/255.0f)*255.0f); Vector3 rgb = ConvertHSVtoRGB(hsv); - color = (Color){ (unsigned char)(rgb.x*255.0f), (unsigned char)(rgb.y*255.0f), (unsigned char)(rgb.z*255.0f), color.a }; + color = RAYGUI_CLITERAL(Color){ (unsigned char)(rgb.x*255.0f), (unsigned char)(rgb.y*255.0f), (unsigned char)(rgb.z*255.0f), color.a }; return color; } @@ -2754,12 +3875,12 @@ RAYGUIDEF int GuiMessageBox(Rectangle bounds, const char *windowTitle, const cha #define MESSAGEBOX_BUTTON_PADDING 10 int clicked = -1; // Returns clicked button from buttons list, 0 refers to closed window button - + int buttonsCount = 0; const char **buttonsText = GuiTextSplit(buttons, &buttonsCount, NULL); Vector2 textSize = MeasureTextEx(guiFont, message, GuiGetStyle(DEFAULT, TEXT_SIZE), 1); - + Rectangle textBounds = { 0 }; textBounds.x = bounds.x + bounds.width/2 - textSize.x/2; textBounds.y = bounds.y + WINDOW_STATUSBAR_HEIGHT + (bounds.height - WINDOW_STATUSBAR_HEIGHT)/4 - textSize.y/2; @@ -2775,7 +3896,7 @@ RAYGUIDEF int GuiMessageBox(Rectangle bounds, const char *windowTitle, const cha // Draw control //-------------------------------------------------------------------- if (GuiWindowBox(bounds, windowTitle)) clicked = 0; - + int prevTextAlignment = GuiGetStyle(LABEL, TEXT_ALIGNMENT); GuiSetStyle(LABEL, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_CENTER); GuiLabel(textBounds, message); @@ -2783,19 +3904,29 @@ RAYGUIDEF int GuiMessageBox(Rectangle bounds, const char *windowTitle, const cha prevTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT); GuiSetStyle(BUTTON, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_CENTER); - + for (int i = 0; i < buttonsCount; i++) { if (GuiButton(buttonBounds, buttonsText[i])) clicked = i + 1; buttonBounds.x += (buttonBounds.width + MESSAGEBOX_BUTTON_PADDING); } - + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, prevTextAlignment); //-------------------------------------------------------------------- return clicked; } +// Text Input Box control, ask for text +RAYGUIDEF int GuiTextInputBox(Rectangle bounds, const char *windowTitle, const char *message, char *text, const char *buttons) +{ + int btnIndex = -1; + + // TODO: GuiTextInputBox() + + return btnIndex; +} + // Grid control // NOTE: Returns grid mouse-hover selected cell // About drawing lines at subpixel spacing, simple put, not easy solution: @@ -2832,13 +3963,13 @@ RAYGUIDEF Vector2 GuiGrid(Rectangle bounds, float spacing, int subdivs) // Draw vertical grid lines for (int i = 0; i < linesV; i++) { - DrawRectangleRec((Rectangle){ bounds.x + spacing*i, bounds.y, 1, bounds.height }, ((i%subdivs) == 0)? Fade(GetColor(GuiGetStyle(DEFAULT, LINE_COLOR)), GRID_COLOR_ALPHA*4) : Fade(GetColor(GuiGetStyle(DEFAULT, LINE_COLOR)), GRID_COLOR_ALPHA)); + DrawRectangleRec(RAYGUI_CLITERAL(Rectangle){ bounds.x + spacing*i, bounds.y, 1, bounds.height }, ((i%subdivs) == 0)? Fade(GetColor(GuiGetStyle(DEFAULT, LINE_COLOR)), GRID_COLOR_ALPHA*4) : Fade(GetColor(GuiGetStyle(DEFAULT, LINE_COLOR)), GRID_COLOR_ALPHA)); } // Draw horizontal grid lines for (int i = 0; i < linesH; i++) { - DrawRectangleRec((Rectangle){ bounds.x, bounds.y + spacing*i, bounds.width, 1 }, ((i%subdivs) == 0)? Fade(GetColor(GuiGetStyle(DEFAULT, LINE_COLOR)), GRID_COLOR_ALPHA*4) : Fade(GetColor(GuiGetStyle(DEFAULT, LINE_COLOR)), GRID_COLOR_ALPHA)); + DrawRectangleRec(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + spacing*i, bounds.width, 1 }, ((i%subdivs) == 0)? Fade(GetColor(GuiGetStyle(DEFAULT, LINE_COLOR)), GRID_COLOR_ALPHA*4) : Fade(GetColor(GuiGetStyle(DEFAULT, LINE_COLOR)), GRID_COLOR_ALPHA)); } } break; @@ -2855,45 +3986,117 @@ RAYGUIDEF Vector2 GuiGrid(Rectangle bounds, float spacing, int subdivs) // Load raygui style file (.rgs) RAYGUIDEF void GuiLoadStyle(const char *fileName) { - FILE *rgsFile = fopen(fileName, "rb"); + bool tryBinary = false; + + // Try reading the files as text file first + FILE *rgsFile = fopen(fileName, "rt"); if (rgsFile != NULL) { - unsigned int value = 0; + char buffer[256] = { 0 }; + fgets(buffer, 256, rgsFile); + + if (buffer[0] == '#') + { + int controlId = 0; + int propertyId = 0; + int propertyValue = 0; + + while (!feof(rgsFile)) + { + switch (buffer[0]) + { + case 'p': + { + sscanf(buffer, "p %d %d 0x%x", &controlId, &propertyId, &propertyValue); + + if (controlId == 0) // DEFAULT control + { + // If a DEFAULT property is loaded, it is propagated to all controls, + // NOTE: All DEFAULT properties should be defined first in the file + GuiSetStyle(0, propertyId, propertyValue); + + if (propertyId < NUM_PROPS_DEFAULT) for (int i = 1; i < NUM_CONTROLS; i++) GuiSetStyle(i, propertyId, propertyValue); + } + else GuiSetStyle(controlId, propertyId, propertyValue); + + } break; + case 'f': + { + int fontSize = 0; + int fontSpacing = 0; + char fontFileName[256] = { 0 }; + sscanf(buffer, "f %d %d %[^\n]s", &fontSize, &fontSpacing, fontFileName); + + Font font = LoadFontEx(FormatText("%s/%s", GetDirectoryPath(fileName), fontFileName), fontSize, NULL, 0); + + if ((font.texture.id > 0) && (font.charsCount > 0)) + { + GuiFont(font); + GuiSetStyle(DEFAULT, TEXT_SIZE, fontSize); + GuiSetStyle(DEFAULT, TEXT_SPACING, fontSpacing); + } + } break; + default: break; + } + + fgets(buffer, 256, rgsFile); + } + } + else tryBinary = true; + + fclose(rgsFile); + } + else return; + + if (tryBinary) + { + rgsFile = fopen(fileName, "rb"); + + if (rgsFile == NULL) return; char signature[5] = ""; short version = 0; - short numControls = 0; - short numPropsDefault = 0; - short numPropsExtended = 0; + short reserved = 0; + int propertiesCount = 0; fread(signature, 1, 4, rgsFile); fread(&version, 1, sizeof(short), rgsFile); - fread(&numControls, 1, sizeof(short), rgsFile); - fread(&numPropsDefault, 1, sizeof(short), rgsFile); - fread(&numPropsExtended, 1, sizeof(short), rgsFile); + fread(&reserved, 1, sizeof(short), rgsFile); + fread(&propertiesCount, 1, sizeof(int), rgsFile); if ((signature[0] == 'r') && (signature[1] == 'G') && (signature[2] == 'S') && (signature[3] == ' ')) { - for (int i = 0; i < NUM_CONTROLS; i++) + short controlId = 0; + short propertyId = 0; + int propertyValue = 0; + + for (int i = 0; i < propertiesCount; i++) { - for (int j = 0; j < NUM_PROPS_DEFAULT + NUM_PROPS_EXTENDED; j++) + fread(&controlId, 1, sizeof(short), rgsFile); + fread(&propertyId, 1, sizeof(short), rgsFile); + fread(&propertyValue, 1, sizeof(int), rgsFile); + + if (controlId == 0) // DEFAULT control { - fread(&value, 1, sizeof(unsigned int), rgsFile); - GuiSetStyle(i, j, value); + // If a DEFAULT property is loaded, it is propagated to all controls + // NOTE: All DEFAULT properties should be defined first in the file + GuiSetStyle(0, (int)propertyId, propertyValue); + + if (propertyId < NUM_PROPS_DEFAULT) for (int i = 1; i < NUM_CONTROLS; i++) GuiSetStyle(i, (int)propertyId, propertyValue); } + else GuiSetStyle((int)controlId, (int)propertyId, propertyValue); } // Font loading is highly dependant on raylib API to load font data and image // TODO: Find some mechanism to support it in standalone mode - #if !defined(RAYGUI_STANDALONE) // Load custom font if available int fontDataSize = 0; - fwrite(&fontDataSize, 1, sizeof(int), rgsFile); + fread(&fontDataSize, 1, sizeof(int), rgsFile); if (fontDataSize > 0) { @@ -2919,9 +4122,12 @@ RAYGUIDEF void GuiLoadStyle(const char *fileName) fread(&imFont.width, 1, sizeof(int), rgsFile); fread(&imFont.height, 1, sizeof(int), rgsFile); fread(&imFont.format, 1, sizeof(int), rgsFile); - fread(&imFont.data, 1, fontImageSize, rgsFile); + + imFont.data = (unsigned char *)malloc(fontImageSize); + fread(imFont.data, 1, fontImageSize, rgsFile); font.texture = LoadTextureFromImage(imFont); + UnloadImage(imFont); } @@ -2929,7 +4135,7 @@ RAYGUIDEF void GuiLoadStyle(const char *fileName) font.chars = (CharInfo *)calloc(font.charsCount, sizeof(CharInfo)); for (int i = 0; i < font.charsCount; i++) { - fread(&font.chars[i].rec, 1, sizeof(Rectangle), rgsFile); + fread(&font.recs[i], 1, sizeof(Rectangle), rgsFile); fread(&font.chars[i].value, 1, sizeof(int), rgsFile); fread(&font.chars[i].offsetX, 1, sizeof(int), rgsFile); fread(&font.chars[i].offsetY, 1, sizeof(int), rgsFile); @@ -2944,7 +4150,7 @@ RAYGUIDEF void GuiLoadStyle(const char *fileName) } #endif } - + fclose(rgsFile); } } @@ -2958,7 +4164,7 @@ RAYGUIDEF void GuiLoadStyleProps(const int *props, int count) // Load style palette values from array (complete property sets) for (int i = 0; i < completeSets; i++) { - for (int j = 0; j < (NUM_PROPS_DEFAULT + NUM_PROPS_EXTENDED); i++) GuiSetStyle(i, j, props[i]); + for (int j = 0; j < (NUM_PROPS_DEFAULT + NUM_PROPS_EXTENDED); j++) GuiSetStyle(i, j, props[i]); } // Load style palette values from array (uncomplete property set) @@ -2994,6 +4200,8 @@ RAYGUIDEF void GuiLoadStyleDefault(void) { for (int j = 0; j < NUM_PROPS_DEFAULT; j++) GuiSetStyle(i, j, GuiGetStyle(DEFAULT, j)); } + + guiFont = GetFontDefault(); // Initialize default font // Initialize extended property values // NOTE: By default, extended property values are initialized to 0 @@ -3015,26 +4223,28 @@ RAYGUIDEF void GuiLoadStyleDefault(void) GuiSetStyle(TEXTBOX, INNER_PADDING, 4); GuiSetStyle(TEXTBOX, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_LEFT); GuiSetStyle(TEXTBOX, MULTILINE_PADDING, 5); - GuiSetStyle(TEXTBOX, SPINNER_BUTTON_WIDTH, 20); // SPINNER specific property - GuiSetStyle(TEXTBOX, SPINNER_BUTTON_PADDING, 2); // SPINNER specific property - GuiSetStyle(TEXTBOX, SPINNER_BUTTON_BORDER_WIDTH, 1); // SPINNER specific property - //GuiSetStyle(VALUEBOX, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_CENTER); // TODO. + GuiSetStyle(TEXTBOX, COLOR_SELECTED_FG, 0xf0fffeff); + GuiSetStyle(TEXTBOX, COLOR_SELECTED_BG, 0x839affe0); + GuiSetStyle(VALUEBOX, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_CENTER); + GuiSetStyle(SPINNER, SELECT_BUTTON_WIDTH, 20); + GuiSetStyle(SPINNER, SELECT_BUTTON_PADDING, 2); + GuiSetStyle(SPINNER, SELECT_BUTTON_BORDER_WIDTH, 1); + GuiSetStyle(SCROLLBAR, BORDER_WIDTH, 0); + GuiSetStyle(SCROLLBAR, ARROWS_VISIBLE, 0); + GuiSetStyle(SCROLLBAR, INNER_PADDING, 0); + GuiSetStyle(SCROLLBAR, ARROWS_SIZE, 6); + GuiSetStyle(SCROLLBAR, SLIDER_PADDING, 0); + GuiSetStyle(SCROLLBAR, SLIDER_SIZE, 16); + GuiSetStyle(SCROLLBAR, SCROLL_SPEED, 10); + GuiSetStyle(LISTVIEW, ELEMENTS_HEIGHT, 0x1e); + GuiSetStyle(LISTVIEW, ELEMENTS_PADDING, 2); + GuiSetStyle(LISTVIEW, SCROLLBAR_WIDTH, 10); + GuiSetStyle(LISTVIEW, SCROLLBAR_SIDE, SCROLLBAR_RIGHT_SIDE); GuiSetStyle(COLORPICKER, COLOR_SELECTOR_SIZE, 6); GuiSetStyle(COLORPICKER, BAR_WIDTH, 0x14); GuiSetStyle(COLORPICKER, BAR_PADDING, 0xa); GuiSetStyle(COLORPICKER, BAR_SELECTOR_HEIGHT, 6); GuiSetStyle(COLORPICKER, BAR_SELECTOR_PADDING, 2); - GuiSetStyle(LISTVIEW, ELEMENTS_HEIGHT, 0x1e); - GuiSetStyle(LISTVIEW, ELEMENTS_PADDING, 2); - GuiSetStyle(LISTVIEW, SCROLLBAR_WIDTH, 10); - GuiSetStyle(LISTVIEW, SCROLLBAR_SIDE, SCROLLBAR_RIGHT_SIDE); - GuiSetStyle(SCROLLBAR, BORDER_WIDTH, 0); - GuiSetStyle(SCROLLBAR, SHOW_SPINNER_BUTTONS, 0); - GuiSetStyle(SCROLLBAR, ARROWS_SIZE, 6); - GuiSetStyle(SCROLLBAR, INNER_PADDING, 0); - GuiSetStyle(SCROLLBAR, SLIDER_PADDING, 0); - GuiSetStyle(SCROLLBAR, SLIDER_SIZE, 16); - GuiSetStyle(SCROLLBAR, SCROLL_SPEED, 10); } // Updates controls style with default values @@ -3049,15 +4259,15 @@ RAYGUIDEF void GuiUpdateStyleComplete(void) } // Get text with icon id prepended -// NOTE: Useful to add icons by name id (enum) instead of +// NOTE: Useful to add icons by name id (enum) instead of // a number that can change between ricon versions RAYGUIDEF const char *GuiIconText(int iconId, const char *text) { static char buffer[1024] = { 0 }; memset(buffer, 0, 1024); - + sprintf(buffer, "#%03i#", iconId); - + if (text != NULL) { for (int i = 5; i < 1024; i++) @@ -3066,7 +4276,7 @@ RAYGUIDEF const char *GuiIconText(int iconId, const char *text) if (text[i - 5] == '\0') break; } } - + return buffer; } @@ -3284,7 +4494,7 @@ static Color Fade(Color color, float alpha) if (alpha < 0.0f) alpha = 0.0f; else if (alpha > 1.0f) alpha = 1.0f; - return (Color){color.r, color.g, color.b, (unsigned char)(255.0f*alpha)}; + return RAYGUI_CLITERAL(Color){ color.r, color.g, color.b, (unsigned char)(255.0f*alpha) }; } // Formatting of text with variables to 'embed' @@ -3301,6 +4511,30 @@ static const char *TextFormat(const char *text, ...) return buffer; } + +// Draw rectangle filled with color +static void DrawRectangleRec(Rectangle rec, Color color) +{ + DrawRectangle(rec.x, rec.y, rec.width, rec.height, color); +} + +// Draw rectangle border lines with color +static void DrawRectangleLinesEx(Rectangle rec, int lineThick, Color color) +{ + DrawRectangle(rec.x, rec.y, rec.width, lineThick, color); + DrawRectangle(rec.x, rec.y + lineThick, lineThick, rec.height - 2*lineThick, color); + DrawRectangle(rec.x + rec.width - lineThick, rec.y + lineThick, lineThick, rec.height - 2*lineThick, color); + DrawRectangle(rec.x, rec.y + rec.height - lineThick, rec.width, lineThick, color); +} + +// Draw rectangle with vertical gradient fill color +// NOTE: This function is only used by GuiColorPicker() +static void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2) +{ + Rectangle bounds = { (float)posX, (float)posY, (float)width, (float)height }; + DrawRectangleGradientEx(bounds, color1, color2, color2, color1); +} + #endif // RAYGUI_STANDALONE -#endif // RAYGUI_IMPLEMENTATION +#endif // RAYGUI_IMPLEMENTATION \ No newline at end of file diff --git a/examples/shapes/shapes_basic_shapes.c b/examples/shapes/shapes_basic_shapes.c index 67eea9d5f..f7a8d02fd 100644 --- a/examples/shapes/shapes_basic_shapes.c +++ b/examples/shapes/shapes_basic_shapes.c @@ -11,16 +11,16 @@ #include "raylib.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [shapes] example - basic shapes drawing"); - - SetTargetFPS(60); + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop diff --git a/examples/shapes/shapes_bouncing_ball.c b/examples/shapes/shapes_bouncing_ball.c index 6b27c9dd3..9f01ff145 100644 --- a/examples/shapes/shapes_bouncing_ball.c +++ b/examples/shapes/shapes_bouncing_ball.c @@ -11,58 +11,58 @@ #include "raylib.h" -int main() +int main(void) { // Initialization //--------------------------------------------------------- const int screenWidth = 800; const int screenHeight = 450; - + InitWindow(screenWidth, screenHeight, "raylib [shapes] example - bouncing ball"); - - Vector2 ballPosition = { GetScreenWidth()/2, GetScreenHeight()/2 }; - Vector2 ballSpeed = { 5.0f, 4.0f }; - int ballRadius = 20; - + + Vector2 ballPosition = { GetScreenWidth()/2, GetScreenHeight()/2 }; + Vector2 ballSpeed = { 5.0f, 4.0f }; + int ballRadius = 20; + bool pause = 0; int framesCounter = 0; - SetTargetFPS(60); + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //---------------------------------------------------------- - + // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //----------------------------------------------------- if (IsKeyPressed(KEY_SPACE)) pause = !pause; - + if (!pause) { ballPosition.x += ballSpeed.x; ballPosition.y += ballSpeed.y; - + // Check walls collision for bouncing if ((ballPosition.x >= (GetScreenWidth() - ballRadius)) || (ballPosition.x <= ballRadius)) ballSpeed.x *= -1.0f; if ((ballPosition.y >= (GetScreenHeight() - ballRadius)) || (ballPosition.y <= ballRadius)) ballSpeed.y *= -1.0f; } else framesCounter++; //----------------------------------------------------- - + // Draw //----------------------------------------------------- BeginDrawing(); - + ClearBackground(RAYWHITE); - + DrawCircleV(ballPosition, ballRadius, MAROON); DrawText("PRESS SPACE to PAUSE BALL MOVEMENT", 10, GetScreenHeight() - 25, 20, LIGHTGRAY); - + // On pause, we draw a blinking message if (pause && ((framesCounter/30)%2)) DrawText("PAUSED", 350, 200, 30, GRAY); DrawFPS(10, 10); - + EndDrawing(); //----------------------------------------------------- } @@ -71,6 +71,6 @@ int main() //--------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //---------------------------------------------------------- - + return 0; } \ No newline at end of file diff --git a/examples/shapes/shapes_collision_area.c b/examples/shapes/shapes_collision_area.c index e61623abf..0deba0dda 100644 --- a/examples/shapes/shapes_collision_area.c +++ b/examples/shapes/shapes_collision_area.c @@ -12,89 +12,89 @@ #include "raylib.h" #include // Required for abs() -int main() +int main(void) { // Initialization //--------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [shapes] example - collision area"); - + // Box A: Moving box Rectangle boxA = { 10, GetScreenHeight()/2 - 50, 200, 100 }; - int boxASpeedX = 4; - + int boxASpeedX = 4; + // Box B: Mouse moved box Rectangle boxB = { GetScreenWidth()/2 - 30, GetScreenHeight()/2 - 30, 60, 60 }; - - Rectangle boxCollision = { 0 }; // Collision rectangle - + + Rectangle boxCollision = { 0 }; // Collision rectangle + int screenUpperLimit = 40; // Top menu limits - - bool pause = false; // Movement pause - bool collision = false; // Collision detection - - SetTargetFPS(60); + + bool pause = false; // Movement pause + bool collision = false; // Collision detection + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //---------------------------------------------------------- - + // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //----------------------------------------------------- // Move box if not paused - if (!pause) boxA.x += boxASpeedX; - + if (!pause) boxA.x += boxASpeedX; + // Bounce box on x screen limits - if (((boxA.x + boxA.width) >= GetScreenWidth()) || (boxA.x <= 0)) boxASpeedX *= -1; - - // Update player-controlled-box (box02) - boxB.x = GetMouseX() - boxB.width/2; - boxB.y = GetMouseY() - boxB.height/2; - + if (((boxA.x + boxA.width) >= GetScreenWidth()) || (boxA.x <= 0)) boxASpeedX *= -1; + + // Update player-controlled-box (box02) + boxB.x = GetMouseX() - boxB.width/2; + boxB.y = GetMouseY() - boxB.height/2; + // Make sure Box B does not go out of move area limits - if ((boxB.x + boxB.width) >= GetScreenWidth()) boxB.x = GetScreenWidth() - boxB.width; - else if (boxB.x <= 0) boxB.x = 0; - - if ((boxB.y + boxB.height) >= GetScreenHeight()) boxB.y = GetScreenHeight() - boxB.height; - else if (boxB.y <= screenUpperLimit) boxB.y = screenUpperLimit; - + if ((boxB.x + boxB.width) >= GetScreenWidth()) boxB.x = GetScreenWidth() - boxB.width; + else if (boxB.x <= 0) boxB.x = 0; + + if ((boxB.y + boxB.height) >= GetScreenHeight()) boxB.y = GetScreenHeight() - boxB.height; + else if (boxB.y <= screenUpperLimit) boxB.y = screenUpperLimit; + // Check boxes collision collision = CheckCollisionRecs(boxA, boxB); - - // Get collision rectangle (only on collision) - if (collision) boxCollision = GetCollisionRec(boxA, boxB); - + + // Get collision rectangle (only on collision) + if (collision) boxCollision = GetCollisionRec(boxA, boxB); + // Pause Box A movement - if (IsKeyPressed(KEY_SPACE)) pause = !pause; + if (IsKeyPressed(KEY_SPACE)) pause = !pause; //----------------------------------------------------- - + // Draw //----------------------------------------------------- BeginDrawing(); - + ClearBackground(RAYWHITE); - + DrawRectangle(0, 0, screenWidth, screenUpperLimit, collision? RED : BLACK); DrawRectangleRec(boxA, GOLD); DrawRectangleRec(boxB, BLUE); - + if (collision) { // Draw collision area DrawRectangleRec(boxCollision, LIME); - + // Draw collision message DrawText("COLLISION!", GetScreenWidth()/2 - MeasureText("COLLISION!", 20)/2, screenUpperLimit/2 - 10, 20, BLACK); - + // Draw collision area DrawText(FormatText("Collision Area: %i", (int)boxCollision.width*(int)boxCollision.height), GetScreenWidth()/2 - 100, screenUpperLimit + 10, 20, BLACK); - } + } DrawFPS(10, 10); - + EndDrawing(); //----------------------------------------------------- } @@ -103,6 +103,6 @@ int main() //--------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //---------------------------------------------------------- - + return 0; } \ No newline at end of file diff --git a/examples/shapes/shapes_colors_palette.c b/examples/shapes/shapes_colors_palette.c index dcab862e2..a0bba002a 100644 --- a/examples/shapes/shapes_colors_palette.c +++ b/examples/shapes/shapes_colors_palette.c @@ -1,26 +1,53 @@ /******************************************************************************************* * -* raylib [shapes] example - Draw raylib custom color palette +* raylib [shapes] example - Colors palette * -* This example has been created using raylib 1.0 (www.raylib.com) +* This example has been created using raylib 2.5 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * -* Copyright (c) 2014 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2019 Ramon Santamaria (@raysan5) * ********************************************************************************************/ #include "raylib.h" -int main() +#define MAX_COLORS_COUNT 21 // Number of colors available + +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; - InitWindow(screenWidth, screenHeight, "raylib [shapes] example - raylib color palette"); - - SetTargetFPS(60); + InitWindow(screenWidth, screenHeight, "raylib [shapes] example - colors palette"); + + Color colors[MAX_COLORS_COUNT] = { + DARKGRAY, MAROON, ORANGE, DARKGREEN, DARKBLUE, DARKPURPLE, DARKBROWN, + GRAY, RED, GOLD, LIME, BLUE, VIOLET, BROWN, LIGHTGRAY, PINK, YELLOW, + GREEN, SKYBLUE, PURPLE, BEIGE }; + + const char *colorNames[MAX_COLORS_COUNT] = { + "DARKGRAY", "MAROON", "ORANGE", "DARKGREEN", "DARKBLUE", "DARKPURPLE", + "DARKBROWN", "GRAY", "RED", "GOLD", "LIME", "BLUE", "VIOLET", "BROWN", + "LIGHTGRAY", "PINK", "YELLOW", "GREEN", "SKYBLUE", "PURPLE", "BEIGE" }; + + Rectangle colorsRecs[MAX_COLORS_COUNT] = { 0 }; // Rectangles array + + // Fills colorsRecs data (for every rectangle) + for (int i = 0; i < MAX_COLORS_COUNT; i++) + { + colorsRecs[i].x = 20 + 100*(i%7) + 10*(i%7); + colorsRecs[i].y = 80 + 100*(i/7) + 10*(i/7); + colorsRecs[i].width = 100; + colorsRecs[i].height = 100; + } + + int colorState[MAX_COLORS_COUNT] = { 0 }; // Color state: 0-DEFAULT, 1-MOUSE_HOVER + + Vector2 mousePoint = { 0.0f, 0.0f }; + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop @@ -28,7 +55,13 @@ int main() { // Update //---------------------------------------------------------------------------------- - // TODO: Update your variables here + mousePoint = GetMousePosition(); + + for (int i = 0; i < MAX_COLORS_COUNT; i++) + { + if (CheckCollisionPointRec(mousePoint, colorsRecs[i])) colorState[i] = 1; + else colorState[i] = 0; + } //---------------------------------------------------------------------------------- // Draw @@ -37,52 +70,21 @@ int main() ClearBackground(RAYWHITE); - DrawText("raylib color palette", 28, 42, 20, BLACK); + DrawText("raylib colors palette", 28, 42, 20, BLACK); + DrawText("press SPACE to see all colors", GetScreenWidth() - 180, GetScreenHeight() - 40, 10, GRAY); - DrawRectangle(26, 80, 100, 100, DARKGRAY); - DrawRectangle(26, 188, 100, 100, GRAY); - DrawRectangle(26, 296, 100, 100, LIGHTGRAY); - DrawRectangle(134, 80, 100, 100, MAROON); - DrawRectangle(134, 188, 100, 100, RED); - DrawRectangle(134, 296, 100, 100, PINK); - DrawRectangle(242, 80, 100, 100, ORANGE); - DrawRectangle(242, 188, 100, 100, GOLD); - DrawRectangle(242, 296, 100, 100, YELLOW); - DrawRectangle(350, 80, 100, 100, DARKGREEN); - DrawRectangle(350, 188, 100, 100, LIME); - DrawRectangle(350, 296, 100, 100, GREEN); - DrawRectangle(458, 80, 100, 100, DARKBLUE); - DrawRectangle(458, 188, 100, 100, BLUE); - DrawRectangle(458, 296, 100, 100, SKYBLUE); - DrawRectangle(566, 80, 100, 100, DARKPURPLE); - DrawRectangle(566, 188, 100, 100, VIOLET); - DrawRectangle(566, 296, 100, 100, PURPLE); - DrawRectangle(674, 80, 100, 100, DARKBROWN); - DrawRectangle(674, 188, 100, 100, BROWN); - DrawRectangle(674, 296, 100, 100, BEIGE); + for (int i = 0; i < MAX_COLORS_COUNT; i++) // Draw all rectangles + { + DrawRectangleRec(colorsRecs[i], Fade(colors[i], colorState[i]? 0.6f : 1.0f)); - - DrawText("DARKGRAY", 65, 166, 10, BLACK); - DrawText("GRAY", 93, 274, 10, BLACK); - DrawText("LIGHTGRAY", 61, 382, 10, BLACK); - DrawText("MAROON", 186, 166, 10, BLACK); - DrawText("RED", 208, 274, 10, BLACK); - DrawText("PINK", 204, 382, 10, BLACK); - DrawText("ORANGE", 295, 166, 10, BLACK); - DrawText("GOLD", 310, 274, 10, BLACK); - DrawText("YELLOW", 300, 382, 10, BLACK); - DrawText("DARKGREEN", 382, 166, 10, BLACK); - DrawText("LIME", 420, 274, 10, BLACK); - DrawText("GREEN", 410, 382, 10, BLACK); - DrawText("DARKBLUE", 498, 166, 10, BLACK); - DrawText("BLUE", 526, 274, 10, BLACK); - DrawText("SKYBLUE", 505, 382, 10, BLACK); - DrawText("DARKPURPLE", 592, 166, 10, BLACK); - DrawText("VIOLET", 621, 274, 10, BLACK); - DrawText("PURPLE", 620, 382, 10, BLACK); - DrawText("DARKBROWN", 705, 166, 10, BLACK); - DrawText("BROWN", 733, 274, 10, BLACK); - DrawText("BEIGE", 737, 382, 10, BLACK); + if (IsKeyDown(KEY_SPACE) || colorState[i]) + { + DrawRectangle(colorsRecs[i].x, colorsRecs[i].y + colorsRecs[i].height - 26, colorsRecs[i].width, 20, BLACK); + DrawRectangleLinesEx(colorsRecs[i], 6, Fade(BLACK, 0.3f)); + DrawText(colorNames[i], colorsRecs[i].x + colorsRecs[i].width - MeasureText(colorNames[i], 10) - 12, + colorsRecs[i].y + colorsRecs[i].height - 20, 10, colors[i]); + } + } EndDrawing(); //---------------------------------------------------------------------------------- @@ -90,7 +92,7 @@ int main() // De-Initialization //-------------------------------------------------------------------------------------- - CloseWindow(); // Close window and OpenGL context + CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; diff --git a/examples/shapes/shapes_colors_palette.png b/examples/shapes/shapes_colors_palette.png index 4073b6701..b68e497e4 100644 Binary files a/examples/shapes/shapes_colors_palette.png and b/examples/shapes/shapes_colors_palette.png differ diff --git a/examples/shapes/shapes_draw_circle_sector.c b/examples/shapes/shapes_draw_circle_sector.c index a88a59d56..ae6de5fff 100644 --- a/examples/shapes/shapes_draw_circle_sector.c +++ b/examples/shapes/shapes_draw_circle_sector.c @@ -5,7 +5,9 @@ * This example has been created using raylib 2.5 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * -* Copyright (c) 2019 Vlad Adrian (@Demizdor) and Ramon Santamaria (@raysan5) +* Example contributed by Vlad Adrian (@demizdor) and reviewed by Ramon Santamaria (@raysan5) +* +* Copyright (c) 2018 Vlad Adrian (@demizdor) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ @@ -14,7 +16,7 @@ #define RAYGUI_IMPLEMENTATION #include "raygui.h" // Required for GUI controls -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- @@ -30,7 +32,7 @@ int main() int endAngle = 180; int segments = 0; - SetTargetFPS(60); + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop diff --git a/examples/shapes/shapes_draw_rectangle_rounded.c b/examples/shapes/shapes_draw_rectangle_rounded.c index 35fe63fb8..c183e88b2 100644 --- a/examples/shapes/shapes_draw_rectangle_rounded.c +++ b/examples/shapes/shapes_draw_rectangle_rounded.c @@ -5,7 +5,9 @@ * This example has been created using raylib 2.5 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * -* Copyright (c) 2019 Vlad Adrian (@Demizdor) and Ramon Santamaria (@raysan5) +* Example contributed by Vlad Adrian (@demizdor) and reviewed by Ramon Santamaria (@raysan5) +* +* Copyright (c) 2018 Vlad Adrian (@demizdor) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ @@ -28,12 +30,12 @@ int main(void) int height = 100; int segments = 0; int lineThick = 1; - + bool drawRect = false; bool drawRoundedRect = true; bool drawRoundedLines = false; - SetTargetFPS(60); + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop @@ -43,20 +45,20 @@ int main(void) //---------------------------------------------------------------------------------- Rectangle rec = { (GetScreenWidth() - width - 250)/2, (GetScreenHeight() - height)/2, width, height }; //---------------------------------------------------------------------------------- - + // Draw //---------------------------------------------------------------------------------- BeginDrawing(); - + ClearBackground(RAYWHITE); - + DrawLine(560, 0, 560, GetScreenHeight(), Fade(LIGHTGRAY, 0.6f)); DrawRectangle(560, 0, GetScreenWidth() - 500, GetScreenHeight(), Fade(LIGHTGRAY, 0.3f)); if (drawRect) DrawRectangleRec(rec, Fade(GOLD, 0.6)); if (drawRoundedRect) DrawRectangleRounded(rec, roundness, segments, Fade(MAROON, 0.2)); if (drawRoundedLines) DrawRectangleRoundedLines(rec,roundness, segments, lineThick, Fade(MAROON, 0.4)); - + // Draw GUI controls //------------------------------------------------------------------------------ width = GuiSliderBar((Rectangle){ 640, 40, 105, 20 }, "Width", width, 0, GetScreenWidth() - 300, true ); @@ -64,22 +66,22 @@ int main(void) roundness = GuiSliderBar((Rectangle){ 640, 140, 105, 20 }, "Roundness", roundness, 0.0f, 1.0f, true); lineThick = GuiSliderBar((Rectangle){ 640, 170, 105, 20 }, "Thickness", lineThick, 0, 20, true); segments = GuiSliderBar((Rectangle){ 640, 240, 105, 20}, "Segments", segments, 0, 60, true); - + drawRoundedRect = GuiCheckBox((Rectangle){ 640, 320, 20, 20 }, "DrawRoundedRect", drawRoundedRect); drawRoundedLines = GuiCheckBox((Rectangle){ 640, 350, 20, 20 }, "DrawRoundedLines", drawRoundedLines); drawRect = GuiCheckBox((Rectangle){ 640, 380, 20, 20}, "DrawRect", drawRect); //------------------------------------------------------------------------------ - + DrawText(FormatText("MODE: %s", (segments >= 4)? "MANUAL" : "AUTO"), 640, 280, 10, (segments >= 4)? MAROON : DARKGRAY); - + DrawFPS(10, 10); - + EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization - //-------------------------------------------------------------------------------------- + //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/shapes/shapes_draw_ring.c b/examples/shapes/shapes_draw_ring.c index d56b9c2eb..a90feab71 100644 --- a/examples/shapes/shapes_draw_ring.c +++ b/examples/shapes/shapes_draw_ring.c @@ -5,7 +5,9 @@ * This example has been created using raylib 2.5 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * -* Copyright (c) 2019 Vlad Adrian (@Demizdor) and Ramon Santamaria (@raysan5) +* Example contributed by Vlad Adrian (@demizdor) and reviewed by Ramon Santamaria (@raysan5) +* +* Copyright (c) 2018 Vlad Adrian (@demizdor) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ @@ -14,7 +16,7 @@ #define RAYGUI_IMPLEMENTATION #include "raygui.h" // Required for GUI controls -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- @@ -27,16 +29,16 @@ int main() float innerRadius = 80.0f; float outerRadius = 190.0f; - + int startAngle = 0; int endAngle = 360; int segments = 0; - + bool drawRing = true; bool drawRingLines = false; bool drawCircleLines = false; - - SetTargetFPS(60); + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop @@ -46,13 +48,13 @@ int main() //---------------------------------------------------------------------------------- // NOTE: All variables update happens inside GUI control functions //---------------------------------------------------------------------------------- - + // Draw //---------------------------------------------------------------------------------- BeginDrawing(); - + ClearBackground(RAYWHITE); - + DrawLine(500, 0, 500, GetScreenHeight(), Fade(LIGHTGRAY, 0.6f)); DrawRectangle(500, 0, GetScreenWidth() - 500, GetScreenHeight(), Fade(LIGHTGRAY, 0.3f)); @@ -64,27 +66,27 @@ int main() //------------------------------------------------------------------------------ startAngle = GuiSliderBar((Rectangle){ 600, 40, 120, 20 }, "StartAngle", startAngle, -450, 450, true); endAngle = GuiSliderBar((Rectangle){ 600, 70, 120, 20 }, "EndAngle", endAngle, -450, 450, true); - + innerRadius = GuiSliderBar((Rectangle){ 600, 140, 120, 20 }, "InnerRadius", innerRadius, 0, 100, true); outerRadius = GuiSliderBar((Rectangle){ 600, 170, 120, 20 }, "OuterRadius", outerRadius, 0, 200, true); - + segments = GuiSliderBar((Rectangle){ 600, 240, 120, 20 }, "Segments", segments, 0, 100, true); - + drawRing = GuiCheckBox((Rectangle){ 600, 320, 20, 20 }, "Draw Ring", drawRing); drawRingLines = GuiCheckBox((Rectangle){ 600, 350, 20, 20 }, "Draw RingLines", drawRingLines); drawCircleLines = GuiCheckBox((Rectangle){ 600, 380, 20, 20 }, "Draw CircleLines", drawCircleLines); //------------------------------------------------------------------------------ - + DrawText(FormatText("MODE: %s", (segments >= 4)? "MANUAL" : "AUTO"), 600, 270, 10, (segments >= 4)? MAROON : DARKGRAY); - + DrawFPS(10, 10); - + EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization - //-------------------------------------------------------------------------------------- + //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/shapes/shapes_easings_ball_anim.c b/examples/shapes/shapes_easings_ball_anim.c index 4477203c6..5bb2b4c66 100644 --- a/examples/shapes/shapes_easings_ball_anim.c +++ b/examples/shapes/shapes_easings_ball_anim.c @@ -11,9 +11,9 @@ #include "raylib.h" -#include "easings.h" // Required for easing functions +#include "easings.h" // Required for easing functions -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- @@ -21,16 +21,16 @@ int main() const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [shapes] example - easings ball anim"); - + // Ball variable value to be animated with easings int ballPositionX = -100; int ballRadius = 20; float ballAlpha = 0.0f; - + int state = 0; int framesCounter = 0; - - SetTargetFPS(60); + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop @@ -42,7 +42,7 @@ int main() { framesCounter++; ballPositionX = EaseElasticOut(framesCounter, -100, screenWidth/2 + 100, 120); - + if (framesCounter >= 120) { framesCounter = 0; @@ -53,7 +53,7 @@ int main() { framesCounter++; ballRadius = EaseElasticIn(framesCounter, 20, 500, 200); - + if (framesCounter >= 200) { framesCounter = 0; @@ -64,7 +64,7 @@ int main() { framesCounter++; ballAlpha = EaseCubicOut(framesCounter, 0.0f, 1.0f, 200); - + if (framesCounter >= 200) { framesCounter = 0; @@ -73,7 +73,7 @@ int main() } else if (state == 3) // Reset state to play again { - if (IsKeyPressed(KEY_ENTER)) + if (IsKeyPressed(KEY_ENTER)) { // Reset required variables to play again ballPositionX = -100; @@ -82,7 +82,7 @@ int main() state = 0; } } - + if (IsKeyPressed(KEY_R)) framesCounter = 0; //---------------------------------------------------------------------------------- @@ -94,15 +94,15 @@ int main() if (state >= 2) DrawRectangle(0, 0, screenWidth, screenHeight, GREEN); DrawCircle(ballPositionX, 200, ballRadius, Fade(RED, 1.0f - ballAlpha)); - + if (state == 3) DrawText("PRESS [ENTER] TO PLAY AGAIN!", 240, 200, 20, BLACK); - + EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization - //-------------------------------------------------------------------------------------- + //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/shapes/shapes_easings_box_anim.c b/examples/shapes/shapes_easings_box_anim.c index c74cb2a34..6805d5310 100644 --- a/examples/shapes/shapes_easings_box_anim.c +++ b/examples/shapes/shapes_easings_box_anim.c @@ -13,7 +13,7 @@ #include "easings.h" // Required for easing functions -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- @@ -21,16 +21,16 @@ int main() const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [shapes] example - easings box anim"); - + // Box variables to be animated with easings Rectangle rec = { GetScreenWidth()/2, -100, 100, 100 }; float rotation = 0.0f; float alpha = 1.0f; - + int state = 0; int framesCounter = 0; - - SetTargetFPS(60); + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop @@ -43,12 +43,12 @@ int main() case 0: // Move box down to center of screen { framesCounter++; - + // NOTE: Remember that 3rd parameter of easing function refers to // desired value variation, do not confuse it with expected final value! rec.y = EaseElasticOut(framesCounter, -100, GetScreenHeight()/2 + 100, 120); - if (framesCounter >= 120) + if (framesCounter >= 120) { framesCounter = 0; state = 1; @@ -59,8 +59,8 @@ int main() framesCounter++; rec.height = EaseBounceOut(framesCounter, 100, -90, 120); rec.width = EaseBounceOut(framesCounter, 100, GetScreenWidth(), 120); - - if (framesCounter >= 120) + + if (framesCounter >= 120) { framesCounter = 0; state = 2; @@ -70,8 +70,8 @@ int main() { framesCounter++; rotation = EaseQuadOut(framesCounter, 0.0f, 270.0f, 240); - - if (framesCounter >= 240) + + if (framesCounter >= 240) { framesCounter = 0; state = 3; @@ -81,8 +81,8 @@ int main() { framesCounter++; rec.height = EaseCircOut(framesCounter, 10, GetScreenWidth(), 120); - - if (framesCounter >= 120) + + if (framesCounter >= 120) { framesCounter = 0; state = 4; @@ -92,7 +92,7 @@ int main() { framesCounter++; alpha = EaseSineOut(framesCounter, 1.0f, -1.0f, 160); - + if (framesCounter >= 160) { framesCounter = 0; @@ -101,7 +101,7 @@ int main() } break; default: break; } - + // Reset animation at any moment if (IsKeyPressed(KEY_SPACE)) { @@ -112,7 +112,7 @@ int main() framesCounter = 0; } //---------------------------------------------------------------------------------- - + // Draw //---------------------------------------------------------------------------------- BeginDrawing(); @@ -120,7 +120,7 @@ int main() ClearBackground(RAYWHITE); DrawRectanglePro(rec, (Vector2){ rec.width/2, rec.height/2 }, rotation, Fade(BLACK, alpha)); - + DrawText("PRESS [SPACE] TO RESET BOX ANIMATION!", 10, GetScreenHeight() - 25, 20, LIGHTGRAY); EndDrawing(); @@ -128,7 +128,7 @@ int main() } // De-Initialization - //-------------------------------------------------------------------------------------- + //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/shapes/shapes_easings_rectangle_array.c b/examples/shapes/shapes_easings_rectangle_array.c index 27bad5c94..07de98a05 100644 --- a/examples/shapes/shapes_easings_rectangle_array.c +++ b/examples/shapes/shapes_easings_rectangle_array.c @@ -2,7 +2,7 @@ * * raylib [shapes] example - easings rectangle array * -* NOTE: This example requires 'easings.h' library, provided on raylib/src. Just copy +* NOTE: This example requires 'easings.h' library, provided on raylib/src. Just copy * the library to same directory as example or make sure it's available on include path. * * This example has been created using raylib 2.0 (www.raylib.com) @@ -24,17 +24,17 @@ #define PLAY_TIME_IN_FRAMES 240 // At 60 fps = 4 seconds -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [shapes] example - easings rectangle array"); - - Rectangle recs[MAX_RECS_X*MAX_RECS_Y]; - + + Rectangle recs[MAX_RECS_X*MAX_RECS_Y] = { 0 }; + for (int y = 0; y < MAX_RECS_Y; y++) { for (int x = 0; x < MAX_RECS_X; x++) @@ -45,12 +45,12 @@ int main() recs[y*MAX_RECS_X + x].height = RECS_HEIGHT; } } - + float rotation = 0.0f; int framesCounter = 0; - int state = 0; // Rectangles animation state: 0-Playing, 1-Finished - - SetTargetFPS(60); + int state = 0; // Rectangles animation state: 0-Playing, 1-Finished + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop @@ -62,16 +62,16 @@ int main() { framesCounter++; - for (int i = 0; i < MAX_RECS_X*MAX_RECS_Y; i++) + for (int i = 0; i < MAX_RECS_X*MAX_RECS_Y; i++) { recs[i].height = EaseCircOut(framesCounter, RECS_HEIGHT, -RECS_HEIGHT, PLAY_TIME_IN_FRAMES); recs[i].width = EaseCircOut(framesCounter, RECS_WIDTH, -RECS_WIDTH, PLAY_TIME_IN_FRAMES); - + if (recs[i].height < 0) recs[i].height = 0; if (recs[i].width < 0) recs[i].width = 0; - + if ((recs[i].height == 0) && (recs[i].width == 0)) state = 1; // Finish playing - + rotation = EaseLinearIn(framesCounter, 0.0f, 360.0f, PLAY_TIME_IN_FRAMES); } } @@ -79,13 +79,13 @@ int main() { // When animation has finished, press space to restart framesCounter = 0; - - for (int i = 0; i < MAX_RECS_X*MAX_RECS_Y; i++) + + for (int i = 0; i < MAX_RECS_X*MAX_RECS_Y; i++) { recs[i].height = RECS_HEIGHT; recs[i].width = RECS_WIDTH; } - + state = 0; } //---------------------------------------------------------------------------------- @@ -110,7 +110,7 @@ int main() } // De-Initialization - //-------------------------------------------------------------------------------------- + //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/shapes/shapes_following_eyes.c b/examples/shapes/shapes_following_eyes.c index e99a7e07e..a36a8d67b 100644 --- a/examples/shapes/shapes_following_eyes.c +++ b/examples/shapes/shapes_following_eyes.c @@ -13,7 +13,7 @@ #include // Required for: atan2f() -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- @@ -21,19 +21,19 @@ int main() const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [shapes] example - following eyes"); - + Vector2 scleraLeftPosition = { GetScreenWidth()/2 - 100, GetScreenHeight()/2 }; Vector2 scleraRightPosition = { GetScreenWidth()/2 + 100, GetScreenHeight()/2 }; float scleraRadius = 80; - + Vector2 irisLeftPosition = { GetScreenWidth()/2 - 100, GetScreenHeight()/2 }; Vector2 irisRightPosition = { GetScreenWidth()/2 + 100, GetScreenHeight()/2}; float irisRadius = 24; - - float angle; - float dx, dy, dxx, dyy; - - SetTargetFPS(60); + + float angle = 0.0f; + float dx = 0.0f, dy = 0.0f, dxx = 0.0f, dyy = 0.0f; + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop @@ -43,13 +43,13 @@ int main() //---------------------------------------------------------------------------------- irisLeftPosition = GetMousePosition(); irisRightPosition = GetMousePosition(); - + // Check not inside the left eye sclera if (!CheckCollisionPointCircle(irisLeftPosition, scleraLeftPosition, scleraRadius - 20)) { dx = irisLeftPosition.x - scleraLeftPosition.x; dy = irisLeftPosition.y - scleraLeftPosition.y; - + angle = atan2f(dy, dx); dxx = (scleraRadius - irisRadius)*cosf(angle); @@ -64,7 +64,7 @@ int main() { dx = irisRightPosition.x - scleraRightPosition.x; dy = irisRightPosition.y - scleraRightPosition.y; - + angle = atan2f(dy, dx); dxx = (scleraRadius - irisRadius)*cosf(angle); @@ -84,19 +84,19 @@ int main() DrawCircleV(scleraLeftPosition, scleraRadius, LIGHTGRAY); DrawCircleV(irisLeftPosition, irisRadius, BROWN); DrawCircleV(irisLeftPosition, 10, BLACK); - + DrawCircleV(scleraRightPosition, scleraRadius, LIGHTGRAY); DrawCircleV(irisRightPosition, irisRadius, DARKGREEN); DrawCircleV(irisRightPosition, 10, BLACK); - + DrawFPS(10, 10); - + EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization - //-------------------------------------------------------------------------------------- + //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/shapes/shapes_lines_bezier.c b/examples/shapes/shapes_lines_bezier.c index f41334594..3d4edcded 100644 --- a/examples/shapes/shapes_lines_bezier.c +++ b/examples/shapes/shapes_lines_bezier.c @@ -11,20 +11,20 @@ #include "raylib.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; SetConfigFlags(FLAG_MSAA_4X_HINT); InitWindow(screenWidth, screenHeight, "raylib [shapes] example - cubic-bezier lines"); - + Vector2 start = { 0, 0 }; Vector2 end = { screenWidth, screenHeight }; - - SetTargetFPS(60); + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop @@ -41,17 +41,17 @@ int main() BeginDrawing(); ClearBackground(RAYWHITE); - + DrawText("USE MOUSE LEFT-RIGHT CLICK to DEFINE LINE START and END POINTS", 15, 20, 20, GRAY); DrawLineBezier(start, end, 2.0f, RED); - + EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization - //-------------------------------------------------------------------------------------- + //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/shapes/shapes_logo_raylib.c b/examples/shapes/shapes_logo_raylib.c index be94988c9..3e2d343f1 100644 --- a/examples/shapes/shapes_logo_raylib.c +++ b/examples/shapes/shapes_logo_raylib.c @@ -11,16 +11,16 @@ #include "raylib.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [shapes] example - raylib logo using shapes"); - - SetTargetFPS(60); + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop diff --git a/examples/shapes/shapes_logo_raylib_anim.c b/examples/shapes/shapes_logo_raylib_anim.c index 9be1d9635..b8558393e 100644 --- a/examples/shapes/shapes_logo_raylib_anim.c +++ b/examples/shapes/shapes_logo_raylib_anim.c @@ -11,12 +11,12 @@ #include "raylib.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [shapes] example - raylib logo animation"); @@ -35,7 +35,7 @@ int main() int state = 0; // Tracking animation states (State Machine) float alpha = 1.0f; // Useful for fading - SetTargetFPS(60); + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop diff --git a/examples/shapes/shapes_rectangle_scaling_mouse.c b/examples/shapes/shapes_rectangle_scaling.c similarity index 85% rename from examples/shapes/shapes_rectangle_scaling_mouse.c rename to examples/shapes/shapes_rectangle_scaling.c index d8c521cab..6940cbcd0 100644 --- a/examples/shapes/shapes_rectangle_scaling_mouse.c +++ b/examples/shapes/shapes_rectangle_scaling.c @@ -5,7 +5,9 @@ * This example has been created using raylib 2.5 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * -* Copyright (c) 2019 Demioz and Ramon Santamaria (@raysan5) +* Example contributed by Vlad Adrian (@demizdor) and reviewed by Ramon Santamaria (@raysan5) +* +* Copyright (c) 2018 Vlad Adrian (@demizdor) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ @@ -13,23 +15,23 @@ #define MOUSE_SCALE_MARK_SIZE 12 -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [shapes] example - rectangle scaling mouse"); - + Rectangle rec = { 100, 100, 200, 80 }; - + Vector2 mousePosition = { 0 }; - + bool mouseScaleReady = false; bool mouseScaleMode = false; - - SetTargetFPS(60); + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop @@ -38,25 +40,25 @@ int main() // Update //---------------------------------------------------------------------------------- mousePosition = GetMousePosition(); - - if (CheckCollisionPointRec(mousePosition, rec) && + + if (CheckCollisionPointRec(mousePosition, rec) && CheckCollisionPointRec(mousePosition, (Rectangle){ rec.x + rec.width - MOUSE_SCALE_MARK_SIZE, rec.y + rec.height - MOUSE_SCALE_MARK_SIZE, MOUSE_SCALE_MARK_SIZE, MOUSE_SCALE_MARK_SIZE })) { mouseScaleReady = true; if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) mouseScaleMode = true; } else mouseScaleReady = false; - + if (mouseScaleMode) { mouseScaleReady = true; - + rec.width = (mousePosition.x - rec.x); rec.height = (mousePosition.y - rec.y); - + if (rec.width < MOUSE_SCALE_MARK_SIZE) rec.width = MOUSE_SCALE_MARK_SIZE; if (rec.height < MOUSE_SCALE_MARK_SIZE) rec.height = MOUSE_SCALE_MARK_SIZE; - + if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) mouseScaleMode = false; } //---------------------------------------------------------------------------------- @@ -66,15 +68,15 @@ int main() BeginDrawing(); ClearBackground(RAYWHITE); - + DrawText("Scale rectangle dragging from bottom-right corner!", 10, 10, 20, GRAY); DrawRectangleRec(rec, Fade(GREEN, 0.5f)); - - if (mouseScaleReady) + + if (mouseScaleReady) { DrawRectangleLinesEx(rec, 1, RED); - DrawTriangle((Vector2){ rec.x + rec.width - MOUSE_SCALE_MARK_SIZE, rec.y + rec.height }, + DrawTriangle((Vector2){ rec.x + rec.width - MOUSE_SCALE_MARK_SIZE, rec.y + rec.height }, (Vector2){ rec.x + rec.width, rec.y + rec.height }, (Vector2){ rec.x + rec.width, rec.y + rec.height - MOUSE_SCALE_MARK_SIZE }, RED); } @@ -84,7 +86,7 @@ int main() } // De-Initialization - //-------------------------------------------------------------------------------------- + //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/shapes/shapes_rectangle_scaling_mouse.png b/examples/shapes/shapes_rectangle_scaling.png similarity index 100% rename from examples/shapes/shapes_rectangle_scaling_mouse.png rename to examples/shapes/shapes_rectangle_scaling.png diff --git a/examples/text/resources/emoji.fnt b/examples/text/resources/emoji.fnt index cabbdf6c8..85c71968e 100644 --- a/examples/text/resources/emoji.fnt +++ b/examples/text/resources/emoji.fnt @@ -1,6 +1,6 @@ info face="Symbola" size=-64 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=2,2 outline=2 common lineHeight=81 base=59 scaleW=1024 scaleH=1024 pages=1 packed=0 alphaChnl=0 redChnl=4 greenChnl=4 blueChnl=4 -page id=0 file="emoji_0.png" +page id=0 file="emoji.png" chars count=187 char id=9749 x=135 y=333 width=63 height=61 xoffset=1 yoffset=9 xadvance=65 page=0 chnl=15 char id=9752 x=366 y=396 width=57 height=59 xoffset=0 yoffset=10 xadvance=58 page=0 chnl=15 diff --git a/examples/text/resources/emoji_0.png b/examples/text/resources/emoji.png similarity index 100% rename from examples/text/resources/emoji_0.png rename to examples/text/resources/emoji.png diff --git a/examples/text/resources/notoCJK.fnt b/examples/text/resources/notoCJK.fnt index 235ee7712..2edfb61ed 100644 --- a/examples/text/resources/notoCJK.fnt +++ b/examples/text/resources/notoCJK.fnt @@ -1,6 +1,6 @@ info face="Noto Serif CJK JP" size=-16 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=2,2 outline=1 common lineHeight=23 base=18 scaleW=512 scaleH=512 pages=1 packed=0 alphaChnl=0 redChnl=4 greenChnl=4 blueChnl=4 -page id=0 file="notoCJK_0.png" +page id=0 file="notoCJK.png" chars count=576 char id=32 x=507 y=185 width=3 height=3 xoffset=-1 yoffset=-1 xadvance=4 page=0 chnl=15 char id=33 x=449 y=285 width=5 height=14 xoffset=0 yoffset=5 xadvance=5 page=0 chnl=15 diff --git a/examples/text/resources/notoCJK_0.png b/examples/text/resources/notoCJK.png similarity index 100% rename from examples/text/resources/notoCJK_0.png rename to examples/text/resources/notoCJK.png diff --git a/examples/text/resources/pixantiqua.fnt b/examples/text/resources/pixantiqua.fnt index 971b9b0bc..fd9f9dbb7 100644 --- a/examples/text/resources/pixantiqua.fnt +++ b/examples/text/resources/pixantiqua.fnt @@ -1,6 +1,6 @@ info face="PixAntiqua" size=32 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=2,2,2,2 spacing=2,2 outline=0 common lineHeight=32 base=27 scaleW=512 scaleH=512 pages=1 packed=0 alphaChnl=0 redChnl=4 greenChnl=4 blueChnl=4 -page id=0 file="pixantiqua_0.png" +page id=0 file="pixantiqua.png" chars count=184 char id=32 x=9 y=304 width=7 height=36 xoffset=-3 yoffset=-2 xadvance=8 page=0 chnl=15 char id=33 x=391 y=266 width=11 height=36 xoffset=-3 yoffset=-2 xadvance=8 page=0 chnl=15 diff --git a/examples/text/resources/pixantiqua_0.png b/examples/text/resources/pixantiqua.png similarity index 100% rename from examples/text/resources/pixantiqua_0.png rename to examples/text/resources/pixantiqua.png diff --git a/examples/text/resources/shaders/glsl100/sdf.fs b/examples/text/resources/shaders/glsl100/sdf.fs new file mode 100644 index 000000000..b4214d92c --- /dev/null +++ b/examples/text/resources/shaders/glsl100/sdf.fs @@ -0,0 +1,23 @@ +#version 100 + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// NOTE: Add here your custom variables +const float smoothing = 1.0/16.0; + +void main() +{ + // Texel color fetching from texture sampler + // NOTE: Calculate alpha using signed distance field (SDF) + float distance = texture2D(texture0, fragTexCoord).a; + float alpha = smoothstep(0.5 - smoothing, 0.5 + smoothing, distance); + + // Calculate final fragment color + gl_FragColor = vec4(fragColor.rgb, fragColor.a*alpha); +} diff --git a/examples/text/resources/shaders/sdf.fs b/examples/text/resources/shaders/glsl330/sdf.fs similarity index 100% rename from examples/text/resources/shaders/sdf.fs rename to examples/text/resources/shaders/glsl330/sdf.fs diff --git a/examples/text/text_bmfont_ttf.c b/examples/text/text_bmfont_ttf.c deleted file mode 100644 index f71f5ddb1..000000000 --- a/examples/text/text_bmfont_ttf.c +++ /dev/null @@ -1,68 +0,0 @@ -/******************************************************************************************* -* -* raylib [text] example - BMFont and TTF Fonts loading -* -* This example has been created using raylib 1.4 (www.raylib.com) -* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) -* -* Copyright (c) 2016 Ramon Santamaria (@raysan5) -* -********************************************************************************************/ - -#include "raylib.h" - -int main() -{ - // Initialization - //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; - - InitWindow(screenWidth, screenHeight, "raylib [text] example - bmfont and ttf sprite fonts loading"); - - const char msgBm[64] = "THIS IS AN AngelCode SPRITE FONT"; - const char msgTtf[64] = "THIS SPRITE FONT has been GENERATED from a TTF"; - - // NOTE: Textures/Fonts MUST be loaded after Window initialization (OpenGL context is required) - Font fontBm = LoadFont("resources/bmfont.fnt"); // BMFont (AngelCode) - Font fontTtf = LoadFont("resources/pixantiqua.ttf"); // TTF font - - Vector2 fontPosition; - - fontPosition.x = screenWidth/2 - MeasureTextEx(fontBm, msgBm, fontBm.baseSize, 0).x/2; - fontPosition.y = screenHeight/2 - fontBm.baseSize/2 - 80; - - SetTargetFPS(60); - //-------------------------------------------------------------------------------------- - - // Main game loop - while (!WindowShouldClose()) // Detect window close button or ESC key - { - // Update - //---------------------------------------------------------------------------------- - // TODO: Update variables here... - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - BeginDrawing(); - - ClearBackground(RAYWHITE); - - DrawTextEx(fontBm, msgBm, fontPosition, fontBm.baseSize, 0, MAROON); - DrawTextEx(fontTtf, msgTtf, (Vector2){ 75.0f, 240.0f }, fontTtf.baseSize*0.8f, 2, LIME); - - EndDrawing(); - //---------------------------------------------------------------------------------- - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - UnloadFont(fontBm); // AngelCode Font unloading - UnloadFont(fontTtf); // TTF Font unloading - - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} \ No newline at end of file diff --git a/examples/text/text_bmfont_ttf.png b/examples/text/text_bmfont_ttf.png deleted file mode 100644 index 8305d36b8..000000000 Binary files a/examples/text/text_bmfont_ttf.png and /dev/null differ diff --git a/examples/text/text_bmfont_unordered.c b/examples/text/text_bmfont_unordered.c deleted file mode 100644 index a51476198..000000000 --- a/examples/text/text_bmfont_unordered.c +++ /dev/null @@ -1,65 +0,0 @@ -/******************************************************************************************* -* -* raylib [text] example - BMFont unordered chars loading and drawing -* -* This example has been created using raylib 1.4 (www.raylib.com) -* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) -* -* Copyright (c) 2016 Ramon Santamaria (@raysan5) -* -********************************************************************************************/ - -#include "raylib.h" - -int main() -{ - // Initialization - //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; - - InitWindow(screenWidth, screenHeight, "raylib [text] example - bmfont unordered loading and drawing"); - - // NOTE: Using chars outside the [32..127] limits! - // NOTE: If a character is not found in the font, it just renders a space - const char msg[256] = "ASCII extended characters:\n¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆ\nÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæ\nçèéêëìíîïðñòóôõö÷øùúûüýþÿ"; - - // NOTE: Loaded font has an unordered list of characters (chars in the range 32..255) - Font font = LoadFont("resources/pixantiqua.fnt"); // BMFont (AngelCode) - - SetTargetFPS(60); - //-------------------------------------------------------------------------------------- - - // Main game loop - while (!WindowShouldClose()) // Detect window close button or ESC key - { - // Update - //---------------------------------------------------------------------------------- - // TODO: Update variables here... - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - BeginDrawing(); - - ClearBackground(RAYWHITE); - - DrawText("Font name: PixAntiqua", 40, 50, 20, GRAY); - DrawText(FormatText("Font base size: %i", font.baseSize), 40, 80, 20, GRAY); - DrawText(FormatText("Font chars number: %i", font.charsCount), 40, 110, 20, GRAY); - - DrawTextEx(font, msg, (Vector2){ 40, 180 }, font.baseSize, 0, MAROON); - - EndDrawing(); - //---------------------------------------------------------------------------------- - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - UnloadFont(font); // AngelCode Font unloading - - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} \ No newline at end of file diff --git a/examples/text/text_bmfont_unordered.png b/examples/text/text_bmfont_unordered.png deleted file mode 100644 index c67675675..000000000 Binary files a/examples/text/text_bmfont_unordered.png and /dev/null differ diff --git a/examples/text/text_ttf_loading.c b/examples/text/text_font_filters.c similarity index 83% rename from examples/text/text_ttf_loading.c rename to examples/text/text_font_filters.c index 0e964ebd8..60b16a045 100644 --- a/examples/text/text_ttf_loading.c +++ b/examples/text/text_font_filters.c @@ -1,6 +1,10 @@ /******************************************************************************************* * -* raylib [text] example - TTF loading and usage +* raylib [text] example - Font filters +* +* After font loading, font texture atlas filter could be configured for a softer +* display of the font when scaling it to different sizes, that way, it's not required +* to generate multiple fonts at multiple sizes (as long as the scaling is not very different) * * This example has been created using raylib 1.3.0 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) @@ -11,49 +15,44 @@ #include "raylib.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; - InitWindow(screenWidth, screenHeight, "raylib [text] example - ttf loading"); - - const char msg[50] = "TTF Font"; + InitWindow(screenWidth, screenHeight, "raylib [text] example - font filters"); + + const char msg[50] = "Loaded Font"; // NOTE: Textures/Fonts MUST be loaded after Window initialization (OpenGL context is required) - + // TTF Font loading with custom generation parameters Font font = LoadFontEx("resources/KAISG.ttf", 96, 0, 0); - + // Generate mipmap levels to use trilinear filtering // NOTE: On 2D drawing it won't be noticeable, it looks like FILTER_BILINEAR GenTextureMipmaps(&font.texture); float fontSize = font.baseSize; Vector2 fontPosition = { 40, screenHeight/2 - 80 }; - Vector2 textSize; + Vector2 textSize = { 0.0f, 0.0f }; + // Setup texture scaling filter SetTextureFilter(font.texture, FILTER_POINT); int currentFontFilter = 0; // FILTER_POINT - - // NOTE: Drag and drop support only available for desktop platforms: Windows, Linux, OSX -#if defined(PLATFORM_DESKTOP) - int count = 0; - char **droppedFiles; -#endif - - SetTargetFPS(60); + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- - + // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- fontSize += GetMouseWheelMove()*4.0f; - + // Choose font texture filter method if (IsKeyPressed(KEY_ONE)) { @@ -71,66 +70,65 @@ int main() SetTextureFilter(font.texture, FILTER_TRILINEAR); currentFontFilter = 2; } - + textSize = MeasureTextEx(font, msg, fontSize, 0); - + if (IsKeyDown(KEY_LEFT)) fontPosition.x -= 10; else if (IsKeyDown(KEY_RIGHT)) fontPosition.x += 10; - -#if defined(PLATFORM_DESKTOP) + // Load a dropped TTF file dynamically (at current fontSize) if (IsFileDropped()) { - droppedFiles = GetDroppedFiles(&count); - - if (count == 1) // Only support one ttf file dropped + int count = 0; + char **droppedFiles = GetDroppedFiles(&count); + + // NOTE: We only support first ttf file dropped + if (IsFileExtension(droppedFiles[0], ".ttf")) { UnloadFont(font); font = LoadFontEx(droppedFiles[0], fontSize, 0, 0); ClearDroppedFiles(); } } -#endif //---------------------------------------------------------------------------------- - + // Draw //---------------------------------------------------------------------------------- BeginDrawing(); - + ClearBackground(RAYWHITE); - + DrawText("Use mouse wheel to change font size", 20, 20, 10, GRAY); DrawText("Use KEY_RIGHT and KEY_LEFT to move text", 20, 40, 10, GRAY); DrawText("Use 1, 2, 3 to change texture filter", 20, 60, 10, GRAY); DrawText("Drop a new TTF font for dynamic loading", 20, 80, 10, DARKGRAY); DrawTextEx(font, msg, fontPosition, fontSize, 0, BLACK); - + // TODO: It seems texSize measurement is not accurate due to chars offsets... //DrawRectangleLines(fontPosition.x, fontPosition.y, textSize.x, textSize.y, RED); - + DrawRectangle(0, screenHeight - 80, screenWidth, 80, LIGHTGRAY); DrawText(FormatText("Font size: %02.02f", fontSize), 20, screenHeight - 50, 10, DARKGRAY); DrawText(FormatText("Text size: [%02.02f, %02.02f]", textSize.x, textSize.y), 20, screenHeight - 30, 10, DARKGRAY); DrawText("CURRENT TEXTURE FILTER:", 250, 400, 20, GRAY); - + if (currentFontFilter == 0) DrawText("POINT", 570, 400, 20, BLACK); else if (currentFontFilter == 1) DrawText("BILINEAR", 570, 400, 20, BLACK); else if (currentFontFilter == 2) DrawText("TRILINEAR", 570, 400, 20, BLACK); - + EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- -#if defined(PLATFORM_DESKTOP) ClearDroppedFiles(); // Clear internal buffers -#endif - UnloadFont(font); // Font unloading - + + UnloadFont(font); // Font unloading + CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- - + return 0; } \ No newline at end of file diff --git a/examples/text/text_font_filters.png b/examples/text/text_font_filters.png new file mode 100644 index 000000000..7ad823fbd Binary files /dev/null and b/examples/text/text_font_filters.png differ diff --git a/examples/text/text_font_loading.c b/examples/text/text_font_loading.c new file mode 100644 index 000000000..7eaaed8fe --- /dev/null +++ b/examples/text/text_font_loading.c @@ -0,0 +1,91 @@ +/******************************************************************************************* +* +* raylib [text] example - Font loading +* +* raylib can load fonts from multiple file formats: +* +* - TTF/OTF > Sprite font atlas is generated on loading, user can configure +* some of the generation parameters (size, characters to include) +* - BMFonts > Angel code font fileformat, sprite font image must be provided +* together with the .fnt file, font generation cna not be configured +* - XNA Spritefont > Sprite font image, following XNA Spritefont conventions, +* Characters in image must follow some spacing and order rules +* +* This example has been created using raylib 2.6 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2016-2019 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [text] example - font loading"); + + // Define characters to draw + // NOTE: raylib supports UTF-8 encoding, following list is actually codified as UTF8 internally + const char msg[256] = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHI\nJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmn\nopqrstuvwxyz{|}~¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓ\nÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷\nøùúûüýþÿ"; + + // NOTE: Textures/Fonts MUST be loaded after Window initialization (OpenGL context is required) + + // BMFont (AngelCode) : Font data and image atlas have been generated using external program + Font fontBm = LoadFont("resources/pixantiqua.fnt"); + + // TTF font : Font data and atlas are generated directly from TTF + // NOTE: We define a font base size of 32 pixels tall and up-to 250 characters + Font fontTtf = LoadFontEx("resources/pixantiqua.ttf", 32, 0, 250); + + bool useTtf = false; + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + if (IsKeyDown(KEY_SPACE)) useTtf = true; + else useTtf = false; + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + DrawText("Hold SPACE to use TTF generated font", 20, 20, 20, LIGHTGRAY); + + if (!useTtf) + { + DrawTextEx(fontBm, msg, (Vector2){ 20.0f, 100.0f }, fontBm.baseSize, 2, MAROON); + DrawText("Using BMFont (Angelcode) imported", 20, GetScreenHeight() - 30, 20, GRAY); + } + else + { + DrawTextEx(fontTtf, msg, (Vector2){ 20.0f, 100.0f }, fontTtf.baseSize, 2, LIME); + DrawText("Using TTF font generated", 20, GetScreenHeight() - 30, 20, GRAY); + } + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadFont(fontBm); // AngelCode Font unloading + UnloadFont(fontTtf); // TTF Font unloading + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} \ No newline at end of file diff --git a/examples/text/text_font_loading.png b/examples/text/text_font_loading.png new file mode 100644 index 000000000..a99027ad5 Binary files /dev/null and b/examples/text/text_font_loading.png differ diff --git a/examples/text/text_font_sdf.c b/examples/text/text_font_sdf.c index 755b642dd..86545e809 100644 --- a/examples/text/text_font_sdf.c +++ b/examples/text/text_font_sdf.c @@ -11,17 +11,25 @@ #include "raylib.h" -int main() +#if defined(PLATFORM_DESKTOP) + #define GLSL_VERSION 330 +#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB + #define GLSL_VERSION 100 +#endif + +#include + +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [text] example - SDF fonts"); // NOTE: Textures/Fonts MUST be loaded after Window initialization (OpenGL context is required) - + const char msg[50] = "Signed Distance Fields"; // Default font generation from TTF font @@ -31,10 +39,10 @@ int main() // Parameters > font size: 16, no chars array provided (0), chars count: 95 (autogenerate chars array) fontDefault.chars = LoadFontData("resources/AnonymousPro-Bold.ttf", 16, 0, 95, FONT_DEFAULT); // Parameters > chars count: 95, font size: 16, chars padding in image: 4 px, pack method: 0 (default) - Image atlas = GenImageFontAtlas(fontDefault.chars, 95, 16, 4, 0); + Image atlas = GenImageFontAtlas(fontDefault.chars, &fontDefault.recs, 95, 16, 4, 0); fontDefault.texture = LoadTextureFromImage(atlas); UnloadImage(atlas); - + // SDF font generation from TTF font Font fontSDF = { 0 }; fontSDF.baseSize = 16; @@ -42,62 +50,62 @@ int main() // Parameters > font size: 16, no chars array provided (0), chars count: 0 (defaults to 95) fontSDF.chars = LoadFontData("resources/AnonymousPro-Bold.ttf", 16, 0, 0, FONT_SDF); // Parameters > chars count: 95, font size: 16, chars padding in image: 0 px, pack method: 1 (Skyline algorythm) - atlas = GenImageFontAtlas(fontSDF.chars, 95, 16, 0, 1); + atlas = GenImageFontAtlas(fontSDF.chars, &fontSDF.recs, 95, 16, 0, 1); fontSDF.texture = LoadTextureFromImage(atlas); UnloadImage(atlas); - + // Load SDF required shader (we use default vertex shader) - Shader shader = LoadShader(0, "resources/shaders/sdf.fs"); + Shader shader = LoadShader(0, FormatText("resources/shaders/glsl%i/sdf.fs", GLSL_VERSION)); SetTextureFilter(fontSDF.texture, FILTER_BILINEAR); // Required for SDF font Vector2 fontPosition = { 40, screenHeight/2 - 50 }; - Vector2 textSize = { 0.0f }; + Vector2 textSize = { 0.0f, 0.0f }; float fontSize = 16.0f; - int currentFont = 0; // 0 - fontDefault, 1 - fontSDF - - SetTargetFPS(60); - //-------------------------------------------------------------------------------------- + int currentFont = 0; // 0 - fontDefault, 1 - fontSDF + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + //-------------------------------------------------------------------------------------- + // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- fontSize += GetMouseWheelMove()*8.0f; - + if (fontSize < 6) fontSize = 6; - + if (IsKeyDown(KEY_SPACE)) currentFont = 1; else currentFont = 0; - + if (currentFont == 0) textSize = MeasureTextEx(fontDefault, msg, fontSize, 0); else textSize = MeasureTextEx(fontSDF, msg, fontSize, 0); - + fontPosition.x = GetScreenWidth()/2 - textSize.x/2; fontPosition.y = GetScreenHeight()/2 - textSize.y/2 + 80; //---------------------------------------------------------------------------------- - + // Draw //---------------------------------------------------------------------------------- BeginDrawing(); - + ClearBackground(RAYWHITE); - + if (currentFont == 1) { // NOTE: SDF fonts require a custom SDf shader to compute fragment color BeginShaderMode(shader); // Activate SDF font shader DrawTextEx(fontSDF, msg, fontPosition, fontSize, 0, BLACK); EndShaderMode(); // Activate our default shader for next drawings - + DrawTexture(fontSDF.texture, 10, 10, BLACK); } - else + else { DrawTextEx(fontDefault, msg, fontPosition, fontSize, 0, BLACK); DrawTexture(fontDefault.texture, 10, 10, BLACK); } - + if (currentFont == 1) DrawText("SDF!", 320, 20, 80, RED); else DrawText("default font", 315, 40, 30, GRAY); @@ -105,8 +113,8 @@ int main() DrawText(FormatText("RENDER SIZE: %02.02f", fontSize), GetScreenWidth() - 240, 50, 20, DARKGRAY); DrawText("Use MOUSE WHEEL to SCALE TEXT!", GetScreenWidth() - 240, 90, 10, DARKGRAY); - DrawText("PRESS SPACE to USE SDF FONT VERSION!", 340, GetScreenHeight() - 30, 20, MAROON); - + DrawText("HOLD SPACE to USE SDF FONT VERSION!", 340, GetScreenHeight() - 30, 20, MAROON); + EndDrawing(); //---------------------------------------------------------------------------------- } @@ -115,11 +123,11 @@ int main() //-------------------------------------------------------------------------------------- UnloadFont(fontDefault); // Default font unloading UnloadFont(fontSDF); // SDF font unloading - + UnloadShader(shader); // Unload SDF shader - + CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- - + return 0; } \ No newline at end of file diff --git a/examples/text/text_sprite_fonts.c b/examples/text/text_font_spritefont.c similarity index 66% rename from examples/text/text_sprite_fonts.c rename to examples/text/text_font_spritefont.c index 7ce2fef5f..dff2b47ae 100644 --- a/examples/text/text_sprite_fonts.c +++ b/examples/text/text_font_spritefont.c @@ -1,6 +1,15 @@ /******************************************************************************************* * -* raylib [text] example - Font loading and usage +* raylib [text] example - Sprite font loading +* +* Loaded sprite fonts have been generated following XNA SpriteFont conventions: +* - Characters must be ordered starting with character 32 (Space) +* - Every character must be contained within the same Rectangle height +* - Every character and every line must be separated the same distance +* - Rectangles must be defined by a MAGENTA color background +* +* If following this constraints, a font can be provided just by an image, +* this is quite handy to avoid additional information files (like BMFonts use). * * 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) @@ -11,14 +20,14 @@ #include "raylib.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; - InitWindow(screenWidth, screenHeight, "raylib [text] example - sprite fonts usage"); + InitWindow(screenWidth, screenHeight, "raylib [text] example - sprite font loading"); const char msg1[50] = "THIS IS A custom SPRITE FONT..."; const char msg2[50] = "...and this is ANOTHER CUSTOM font..."; @@ -29,17 +38,16 @@ int main() Font font2 = LoadFont("resources/custom_alagard.png"); // Font loading Font font3 = LoadFont("resources/custom_jupiter_crash.png"); // Font loading - Vector2 fontPosition1, fontPosition2, fontPosition3; + Vector2 fontPosition1 = { screenWidth/2 - MeasureTextEx(font1, msg1, font1.baseSize, -3).x/2, + screenHeight/2 - font1.baseSize/2 - 80 }; - fontPosition1.x = screenWidth/2 - MeasureTextEx(font1, msg1, font1.baseSize, -3).x/2; - fontPosition1.y = screenHeight/2 - font1.baseSize/2 - 80; + Vector2 fontPosition2 = { screenWidth/2 - MeasureTextEx(font2, msg2, font2.baseSize, -2).x/2, + screenHeight/2 - font2.baseSize/2 - 10 }; - fontPosition2.x = screenWidth/2 - MeasureTextEx(font2, msg2, font2.baseSize, -2).x/2; - fontPosition2.y = screenHeight/2 - font2.baseSize/2 - 10; - - fontPosition3.x = screenWidth/2 - MeasureTextEx(font3, msg3, font3.baseSize, 2).x/2; - fontPosition3.y = screenHeight/2 - font3.baseSize/2 + 50; + Vector2 fontPosition3 = { screenWidth/2 - MeasureTextEx(font3, msg3, font3.baseSize, 2).x/2, + screenHeight/2 - font3.baseSize/2 + 50 }; + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop diff --git a/examples/text/text_sprite_fonts.png b/examples/text/text_font_spritefont.png similarity index 100% rename from examples/text/text_sprite_fonts.png rename to examples/text/text_font_spritefont.png diff --git a/examples/text/text_format_text.c b/examples/text/text_format_text.c index ca28be742..a9f041761 100644 --- a/examples/text/text_format_text.c +++ b/examples/text/text_format_text.c @@ -11,12 +11,12 @@ #include "raylib.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [text] example - text formatting"); @@ -24,7 +24,7 @@ int main() int hiscore = 200450; int lives = 5; - SetTargetFPS(60); + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop diff --git a/examples/text/text_input_box.c b/examples/text/text_input_box.c index 5f8d1c018..ea3d29925 100644 --- a/examples/text/text_input_box.c +++ b/examples/text/text_input_box.c @@ -13,12 +13,12 @@ #define MAX_INPUT_CHARS 9 -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [text] example - input box"); @@ -30,7 +30,7 @@ int main() int framesCounter = 0; - SetTargetFPS(60); + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop @@ -40,27 +40,27 @@ int main() //---------------------------------------------------------------------------------- if (CheckCollisionPointRec(GetMousePosition(), textBox)) mouseOnText = true; else mouseOnText = false; - + if (mouseOnText) { int key = GetKeyPressed(); - + // NOTE: Only allow keys in range [32..125] if ((key >= 32) && (key <= 125) && (letterCount < MAX_INPUT_CHARS)) { name[letterCount] = (char)key; letterCount++; } - + if (IsKeyPressed(KEY_BACKSPACE)) { letterCount--; name[letterCount] = '\0'; - + if (letterCount < 0) letterCount = 0; } } - + if (mouseOnText) framesCounter++; else framesCounter = 0; //---------------------------------------------------------------------------------- @@ -70,15 +70,15 @@ int main() BeginDrawing(); ClearBackground(RAYWHITE); - + DrawText("PLACE MOUSE OVER INPUT BOX!", 240, 140, 20, GRAY); DrawRectangleRec(textBox, LIGHTGRAY); if (mouseOnText) DrawRectangleLines(textBox.x, textBox.y, textBox.width, textBox.height, RED); else DrawRectangleLines(textBox.x, textBox.y, textBox.width, textBox.height, DARKGRAY); - + DrawText(name, textBox.x + 5, textBox.y + 8, 40, MAROON); - + DrawText(FormatText("INPUT CHARS: %i/%i", letterCount, MAX_INPUT_CHARS), 315, 250, 20, DARKGRAY); if (mouseOnText) @@ -90,13 +90,13 @@ int main() } else DrawText("Press BACKSPACE to delete chars...", 230, 300, 20, GRAY); } - + EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization - //-------------------------------------------------------------------------------------- + //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/text/text_raylib_fonts.c b/examples/text/text_raylib_fonts.c index 3c930ac2b..d7e41a78c 100644 --- a/examples/text/text_raylib_fonts.c +++ b/examples/text/text_raylib_fonts.c @@ -16,18 +16,18 @@ #define MAX_FONTS 8 -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [text] example - raylib fonts"); // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) - Font fonts[MAX_FONTS]; - + Font fonts[MAX_FONTS] = { 0 }; + fonts[0] = LoadFont("resources/fonts/alagard.png"); fonts[1] = LoadFont("resources/fonts/pixelplay.png"); fonts[2] = LoadFont("resources/fonts/mecha.png"); @@ -36,32 +36,34 @@ int main() fonts[5] = LoadFont("resources/fonts/pixantiqua.png"); fonts[6] = LoadFont("resources/fonts/alpha_beta.png"); fonts[7] = LoadFont("resources/fonts/jupiter_crash.png"); - - const char *messages[MAX_FONTS] = { "ALAGARD FONT designed by Hewett Tsoi", + + const char *messages[MAX_FONTS] = { "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", + "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[MAX_FONTS] = { 2, 4, 8, 4, 3, 4, 4, 1 }; - - Vector2 positions[MAX_FONTS]; - + + Vector2 positions[MAX_FONTS] = { 0 }; + for (int i = 0; i < MAX_FONTS; i++) { positions[i].x = screenWidth/2 - MeasureTextEx(fonts[i], messages[i], fonts[i].baseSize*2, spacings[i]).x/2; positions[i].y = 60 + fonts[i].baseSize + 45*i; } - + // Small Y position corrections positions[3].y += 8; positions[4].y += 2; positions[7].y -= 8; - + Color colors[MAX_FONTS] = { MAROON, ORANGE, DARKGREEN, DARKBLUE, DARKPURPLE, LIME, GOLD, RED }; + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop @@ -77,10 +79,10 @@ int main() BeginDrawing(); ClearBackground(RAYWHITE); - + DrawText("free fonts included with raylib", 250, 20, 20, DARKGRAY); DrawLine(220, 50, 590, 50, DARKGRAY); - + for (int i = 0; i < MAX_FONTS; i++) { DrawTextEx(fonts[i], messages[i], positions[i], fonts[i].baseSize*2, spacings[i], colors[i]); @@ -92,7 +94,7 @@ int main() // De-Initialization //-------------------------------------------------------------------------------------- - + // Fonts unloading for (int i = 0; i < MAX_FONTS; i++) UnloadFont(fonts[i]); diff --git a/examples/text/text_draw_inside_rectangle.c b/examples/text/text_rectangle_bounds.c similarity index 77% rename from examples/text/text_draw_inside_rectangle.c rename to examples/text/text_rectangle_bounds.c index e60fa5e56..abfb142b0 100644 --- a/examples/text/text_draw_inside_rectangle.c +++ b/examples/text/text_rectangle_bounds.c @@ -5,80 +5,80 @@ * This example has been created using raylib 2.3 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * -* Copyright (c) 2018 Vlad Adrian (@demizdor) +* Example contributed by Vlad Adrian (@demizdor) and reviewed by Ramon Santamaria (@raysan5) +* +* Copyright (c) 2018 Vlad Adrian (@demizdor) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ #include "raylib.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [text] example - draw text inside a rectangle"); - - char text[] = "Text cannot escape\tthis container\t...word wrap also works when active so here's\ - a long text for testing.\n\nLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod\ - tempor incididunt ut labore et dolore magna aliqua. Nec ullamcorper sit amet risus nullam eget felis eget."; - + + const char text[] = "Text cannot escape\tthis container\t...word wrap also works when active so here's\ + a long text for testing.\n\nLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod\ + tempor incididunt ut labore et dolore magna aliqua. Nec ullamcorper sit amet risus nullam eget felis eget."; + bool resizing = false; bool wordWrap = true; - + Rectangle container = { 25, 25, screenWidth - 50, screenHeight - 250}; Rectangle resizer = { container.x + container.width - 17, container.y + container.height - 17, 14, 14 }; - + // Minimum width and heigh for the container rectangle const int minWidth = 60; - const int minHeight = 60; + const int minHeight = 60; const int maxWidth = screenWidth - 50; const int maxHeight = screenHeight - 160; - - Vector2 lastMouse = { 0, 0 }; // Stores last mouse coordinates - Color borderColor = MAROON; // Container border color + Vector2 lastMouse = { 0.0f, 0.0f }; // Stores last mouse coordinates + Color borderColor = MAROON; // Container border color + Font font = GetFontDefault(); // Get default system font - Font font = GetFontDefault(); // Get default system font - - SetTargetFPS(60); + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop - while (!WindowShouldClose()) // Detect window close button or ESC key + while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- if (IsKeyPressed(KEY_SPACE)) wordWrap = !wordWrap; - + Vector2 mouse = GetMousePosition(); - + // Check if the mouse is inside the container and toggle border color if (CheckCollisionPointRec(mouse, container)) borderColor = Fade(MAROON, 0.4f); else if (!resizing) borderColor = MAROON; - + // Container resizing logic - if (resizing) + if (resizing) { if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) resizing = false; - + int width = container.width + (mouse.x - lastMouse.x); container.width = (width > minWidth)? ((width < maxWidth)? width : maxWidth) : minWidth; - + int height = container.height + (mouse.y - lastMouse.y); container.height = (height > minHeight)? ((height < maxHeight)? height : maxHeight) : minHeight; - } - else + } + else { // Check if we're resizing if (IsMouseButtonDown(MOUSE_LEFT_BUTTON) && CheckCollisionPointRec(mouse, resizer)) resizing = true; } - + // Move resizer rectangle properly resizer.x = container.x + container.width - 17; resizer.y = container.y + container.height - 17; - + lastMouse = mouse; // Update mouse //---------------------------------------------------------------------------------- @@ -89,10 +89,10 @@ int main() ClearBackground(RAYWHITE); DrawRectangleLinesEx(container, 3, borderColor); // Draw container border - + // Draw text in container (add some padding) - DrawTextRec(font, text, - (Rectangle){ container.x + 4, container.y + 4, container.width - 4, container.height - 4 }, + DrawTextRec(font, text, + (Rectangle){ container.x + 4, container.y + 4, container.width - 4, container.height - 4 }, 20.0f, 2.0f, wordWrap, GRAY); DrawRectangleRec(resizer, borderColor); // Draw the resize box @@ -106,13 +106,13 @@ int main() DrawRectangle(0, screenHeight - 54, screenWidth, 54, GRAY); DrawText("Click hold & drag the to resize the container", 155, screenHeight - 38, 20, RAYWHITE); DrawRectangleRec((Rectangle){ 382, screenHeight - 34, 12, 12 }, MAROON); - + EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization - //-------------------------------------------------------------------------------------- + //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/text/text_draw_inside_rectangle.png b/examples/text/text_rectangle_bounds.png similarity index 100% rename from examples/text/text_draw_inside_rectangle.png rename to examples/text/text_rectangle_bounds.png diff --git a/examples/text/text_ttf_loading.png b/examples/text/text_ttf_loading.png deleted file mode 100644 index 5fdbda198..000000000 Binary files a/examples/text/text_ttf_loading.png and /dev/null differ diff --git a/examples/text/text_unicode.c b/examples/text/text_unicode.c index b6c6db307..53803e050 100644 --- a/examples/text/text_unicode.c +++ b/examples/text/text_unicode.c @@ -5,6 +5,8 @@ * This example has been created using raylib 2.5 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * +* Example contributed by Vlad Adrian (@demizdor) and reviewed by Ramon Santamaria (@raysan5) +* * Copyright (c) 2019 Vlad Adrian (@demizdor) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ @@ -137,15 +139,12 @@ static void RandomizeEmoji(void); // Fills the emoji array with random emojis // Arrays that holds the random emojis struct { int index; // Index inside `emojiCodepoints` - int message; // Message index + int message; // Message index Color color; // Emoji color } emoji[EMOJI_PER_WIDTH*EMOJI_PER_HEIGHT] = { 0 }; static int hovered = -1, selected = -1; -//-------------------------------------------------------------------------------------- -// Main entry point -//-------------------------------------------------------------------------------------- int main(int argc, char **argv) { // Initialization @@ -154,26 +153,26 @@ int main(int argc, char **argv) const int screenHeight = 450; SetConfigFlags(FLAG_MSAA_4X_HINT | FLAG_VSYNC_HINT); - InitWindow(screenWidth, screenHeight, "raylib - unicode test"); + InitWindow(screenWidth, screenHeight, "raylib [text] example - unicode"); // Load the font resources - // NOTE: fontAsian is for asian languages, - // fontEmoji is the emojis and fontDefault is used for everything else + // NOTE: fontAsian is for asian languages, + // fontEmoji is the emojis and fontDefault is used for everything else Font fontDefault = LoadFont("resources/dejavu.fnt"); Font fontAsian = LoadFont("resources/notoCJK.fnt"); Font fontEmoji = LoadFont("resources/emoji.fnt"); - + Vector2 hoveredPos = { 0.0f, 0.0f }; Vector2 selectedPos = { 0.0f, 0.0f }; // Set a random set of emojis when starting up RandomizeEmoji(); - - SetTargetFPS(60); + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- - + // Main loop - while (!WindowShouldClose()) + while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- @@ -187,117 +186,117 @@ int main(int argc, char **argv) selectedPos = hoveredPos; SetClipboardText(messages[emoji[selected].message].text); } - + Vector2 mouse = GetMousePosition(); Vector2 pos = { 28.8f, 10.0f }; hovered = -1; //---------------------------------------------------------------------------------- - + // Draw //---------------------------------------------------------------------------------- BeginDrawing(); - + ClearBackground(RAYWHITE); - + // Draw random emojis in the background //------------------------------------------------------------------------------ for (int i = 0; i < SIZEOF(emoji); ++i) { const char *txt = &emojiCodepoints[emoji[i].index]; Rectangle emojiRect = { pos.x, pos.y, fontEmoji.baseSize, fontEmoji.baseSize }; - + if (!CheckCollisionPointRec(mouse, emojiRect)) { DrawTextEx(fontEmoji, txt, pos, fontEmoji.baseSize, 1.0, selected == i ? emoji[i].color : Fade(LIGHTGRAY, 0.4f)); } - else + else { DrawTextEx(fontEmoji, txt, pos, fontEmoji.baseSize, 1.0, emoji[i].color ); hovered = i; hoveredPos = pos; } - + if ((i != 0) && (i%EMOJI_PER_WIDTH == 0)) { pos.y += fontEmoji.baseSize + 24.25f; pos.x = 28.8f; } else pos.x += fontEmoji.baseSize + 28.8f; } //------------------------------------------------------------------------------ - + // Draw the message when a emoji is selected //------------------------------------------------------------------------------ - if (selected != -1) + if (selected != -1) { const int message = emoji[selected].message; const int horizontalPadding = 20, verticalPadding = 30; Font *font = &fontDefault; - + // Set correct font for asian languages - if (TextIsEqual(messages[message].language, "Chinese") || - TextIsEqual(messages[message].language, "Korean") || + if (TextIsEqual(messages[message].language, "Chinese") || + TextIsEqual(messages[message].language, "Korean") || TextIsEqual(messages[message].language, "Japanese")) font = &fontAsian; - + // Calculate size for the message box (approximate the height and width) Vector2 sz = MeasureTextEx(*font, messages[message].text, font->baseSize, 1.0f); - if (sz.x > 300) { sz.y *= sz.x/300; sz.x = 300; } + if (sz.x > 300) { sz.y *= sz.x/300; sz.x = 300; } else if (sz.x < 160) sz.x = 160; - + Rectangle msgRect = { selectedPos.x - 38.8f, selectedPos.y, 2 * horizontalPadding + sz.x, 2 * verticalPadding + sz.y }; msgRect.y -= msgRect.height; - + // Coordinates for the chat bubble triangle Vector2 a = { selectedPos.x, msgRect.y + msgRect.height }, b = {a.x + 8, a.y + 10}, c= { a.x + 10, a.y }; - + // Don't go outside the screen if (msgRect.x < 10) msgRect.x += 28; - if (msgRect.y < 10) + if (msgRect.y < 10) { msgRect.y = selectedPos.y + 84; a.y = msgRect.y; c.y = a.y; b.y = a.y - 10; - + // Swap values so we can actually render the triangle :( Vector2 tmp = a; a = b; b = tmp; } if (msgRect.x + msgRect.width > screenWidth) msgRect.x -= (msgRect.x + msgRect.width) - screenWidth + 10; - + // Draw chat bubble DrawRectangleRec(msgRect, emoji[selected].color); DrawTriangle(a, b, c, emoji[selected].color); - + // Draw the main text message Rectangle textRect = { msgRect.x + horizontalPadding/2, msgRect.y + verticalPadding/2, msgRect.width - horizontalPadding, msgRect.height }; DrawTextRec(*font, messages[message].text, textRect, font->baseSize, 1.0f, true, WHITE); - + // Draw the info text below the main message int size = strlen(messages[message].text); - unsigned int len = TextCountCodepoints(messages[message].text); + int len = GetCodepointsCount(messages[message].text); const char *info = TextFormat("%s %u characters %i bytes", messages[message].language, len, size); sz = MeasureTextEx(GetFontDefault(), info, 10, 1.0f); Vector2 pos = { textRect.x + textRect.width - sz.x, msgRect.y + msgRect.height - sz.y - 2 }; DrawText(info, pos.x, pos.y, 10, RAYWHITE); } //------------------------------------------------------------------------------ - + // Draw the info text DrawText("These emojis have something to tell you, click each to find out!", (screenWidth - 650)/2, screenHeight - 40, 20, GRAY); DrawText("Each emoji is a unicode character from a font, not a texture... Press [SPACEBAR] to refresh", (screenWidth - 484)/2, screenHeight - 16, 10, GRAY); - - EndDrawing(); + + EndDrawing(); //---------------------------------------------------------------------------------- - } - + } + // De-Initialization - //-------------------------------------------------------------------------------------- + //-------------------------------------------------------------------------------------- UnloadFont(fontDefault); // Unload font resource UnloadFont(fontAsian); // Unload font resource UnloadFont(fontEmoji); // Unload font resource - - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - return 0; + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; } // Fills the emoji array with random emoji (only those emojis present in fontEmoji) @@ -305,16 +304,16 @@ static void RandomizeEmoji(void) { hovered = selected = -1; int start = GetRandomValue(45, 360); - + for (int i = 0; i < SIZEOF(emoji); ++i) { // 0-179 emoji codepoints (from emoji char array) each 4bytes + null char emoji[i].index = GetRandomValue(0, 179)*5; - + // Generate a random color for this emoji Vector3 hsv = {(start*(i + 1))%360, 0.6f, 0.85f}; emoji[i].color = Fade(ColorFromHSV(hsv), 0.8f); - + // Set a random message for this emoji emoji[i].message = GetRandomValue(0, SIZEOF(messages) - 1); } diff --git a/examples/text/text_writing_anim.c b/examples/text/text_writing_anim.c index b2aba6977..2cf2eaa23 100644 --- a/examples/text/text_writing_anim.c +++ b/examples/text/text_writing_anim.c @@ -11,20 +11,20 @@ #include "raylib.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [text] example - text writing anim"); - + const char message[128] = "This sample illustrates a text writing\nanimation effect! Check it out! ;)"; - + int framesCounter = 0; - - SetTargetFPS(60); + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop @@ -34,7 +34,7 @@ int main() //---------------------------------------------------------------------------------- if (IsKeyDown(KEY_SPACE)) framesCounter += 8; else framesCounter++; - + if (IsKeyPressed(KEY_ENTER)) framesCounter = 0; //---------------------------------------------------------------------------------- @@ -45,7 +45,7 @@ int main() ClearBackground(RAYWHITE); DrawText(TextSubtext(message, 0, framesCounter/10), 210, 160, 20, MAROON); - + DrawText("PRESS [ENTER] to RESTART!", 240, 260, 20, LIGHTGRAY); DrawText("PRESS [SPACE] to SPEED UP!", 239, 300, 20, LIGHTGRAY); @@ -54,7 +54,7 @@ int main() } // De-Initialization - //-------------------------------------------------------------------------------------- + //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/textures/textures_background_scrolling.c b/examples/textures/textures_background_scrolling.c index 2be0810a4..c2e5ac80e 100644 --- a/examples/textures/textures_background_scrolling.c +++ b/examples/textures/textures_background_scrolling.c @@ -11,26 +11,26 @@ #include "raylib.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [textures] example - background scrolling"); - + // NOTE: Be careful, background width must be equal or bigger than screen width // if not, texture should be draw more than two times for scrolling effect Texture2D background = LoadTexture("resources/cyberpunk_street_background.png"); Texture2D midground = LoadTexture("resources/cyberpunk_street_midground.png"); Texture2D foreground = LoadTexture("resources/cyberpunk_street_foreground.png"); - - float scrollingBack = 0; - float scrollingMid = 0; - float scrollingFore = 0; - - SetTargetFPS(60); + + float scrollingBack = 0.0f; + float scrollingMid = 0.0f; + float scrollingFore = 0.0f; + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop @@ -41,7 +41,7 @@ int main() scrollingBack -= 0.1f; scrollingMid -= 0.5f; scrollingFore -= 1.0f; - + // NOTE: Texture is scaled twice its size, so it sould be considered on scrolling if (scrollingBack <= -background.width*2) scrollingBack = 0; if (scrollingMid <= -midground.width*2) scrollingMid = 0; @@ -58,15 +58,15 @@ int main() // NOTE: Texture is scaled twice its size DrawTextureEx(background, (Vector2){ scrollingBack, 20 }, 0.0f, 2.0f, WHITE); DrawTextureEx(background, (Vector2){ background.width*2 + scrollingBack, 20 }, 0.0f, 2.0f, WHITE); - + // Draw midground image twice DrawTextureEx(midground, (Vector2){ scrollingMid, 20 }, 0.0f, 2.0f, WHITE); DrawTextureEx(midground, (Vector2){ midground.width*2 + scrollingMid, 20 }, 0.0f, 2.0f, WHITE); - + // Draw foreground image twice DrawTextureEx(foreground, (Vector2){ scrollingFore, 70 }, 0.0f, 2.0f, WHITE); DrawTextureEx(foreground, (Vector2){ foreground.width*2 + scrollingFore, 70 }, 0.0f, 2.0f, WHITE); - + DrawText("BACKGROUND SCROLLING & PARALLAX", 10, 10, 20, RED); DrawText("(c) Cyberpunk Street Environment by Luis Zuno (@ansimuz)", screenWidth - 330, screenHeight - 20, 10, RAYWHITE); diff --git a/examples/textures/textures_bunnymark.c b/examples/textures/textures_bunnymark.c index 76078838d..86605b901 100644 --- a/examples/textures/textures_bunnymark.c +++ b/examples/textures/textures_bunnymark.c @@ -13,7 +13,7 @@ #include // Required for: malloc(), free() -#define MAX_BUNNIES 100000 // 100K bunnies limit +#define MAX_BUNNIES 50000 // 50K bunnies limit // This is the maximum amount of elements (quads) per batch // NOTE: This value is defined in [rlgl] module and can be changed there @@ -25,7 +25,7 @@ typedef struct Bunny { Color color; } Bunny; -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- @@ -34,13 +34,14 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [textures] example - bunnymark"); + // Load bunny texture Texture2D texBunny = LoadTexture("resources/wabbit_alpha.png"); - Bunny *bunnies = (Bunny *)malloc(MAX_BUNNIES*sizeof(Bunny)); // Bunnies array + Bunny *bunnies = (Bunny *)malloc(MAX_BUNNIES*sizeof(Bunny)); // Bunnies array - int bunniesCount = 0; // Bunnies counter + int bunniesCount = 0; // Bunnies counter - SetTargetFPS(60); + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop @@ -53,13 +54,16 @@ int main() // Create more bunnies for (int i = 0; i < 100; i++) { - bunnies[bunniesCount].position = GetMousePosition(); - bunnies[bunniesCount].speed.x = (float)GetRandomValue(-250, 250)/60.0f; - bunnies[bunniesCount].speed.y = (float)GetRandomValue(-250, 250)/60.0f; - bunnies[bunniesCount].color = (Color){ GetRandomValue(50, 240), - GetRandomValue(80, 240), + if (bunniesCount < MAX_BUNNIES) + { + bunnies[bunniesCount].position = GetMousePosition(); + bunnies[bunniesCount].speed.x = (float)GetRandomValue(-250, 250)/60.0f; + bunnies[bunniesCount].speed.y = (float)GetRandomValue(-250, 250)/60.0f; + bunnies[bunniesCount].color = (Color){ GetRandomValue(50, 240), + GetRandomValue(80, 240), GetRandomValue(100, 240), 255 }; - bunniesCount++; + bunniesCount++; + } } } @@ -69,9 +73,9 @@ int main() bunnies[i].position.x += bunnies[i].speed.x; bunnies[i].position.y += bunnies[i].speed.y; - if (((bunnies[i].position.x + texBunny.width/2) > GetScreenWidth()) || + if (((bunnies[i].position.x + texBunny.width/2) > GetScreenWidth()) || ((bunnies[i].position.x + texBunny.width/2) < 0)) bunnies[i].speed.x *= -1; - if (((bunnies[i].position.y + texBunny.height/2) > GetScreenHeight()) || + if (((bunnies[i].position.y + texBunny.height/2) > GetScreenHeight()) || ((bunnies[i].position.y + texBunny.height/2 - 40) < 0)) bunnies[i].speed.y *= -1; } //---------------------------------------------------------------------------------- @@ -84,9 +88,9 @@ int main() for (int i = 0; i < bunniesCount; i++) { - // NOTE: When internal batch buffer limit is reached (MAX_BATCH_ELEMENTS), + // NOTE: When internal batch buffer limit is reached (MAX_BATCH_ELEMENTS), // a draw call is launched and buffer starts being filled again; - // before issuing a draw call, updated vertex data from internal CPU buffer is send to GPU... + // before issuing a draw call, updated vertex data from internal CPU buffer is send to GPU... // Process of sending data is costly and it could happen that GPU data has not been completely // processed for drawing while new data is tried to be sent (updating current in-use buffers) // it could generates a stall and consequently a frame drop, limiting the number of drawn bunnies @@ -96,7 +100,7 @@ int main() DrawRectangle(0, 0, screenWidth, 40, BLACK); DrawText(FormatText("bunnies: %i", bunniesCount), 120, 10, 20, GREEN); DrawText(FormatText("batched draw calls: %i", 1 + bunniesCount/MAX_BATCH_ELEMENTS), 320, 10, 20, MAROON); - + DrawFPS(10, 10); EndDrawing(); @@ -106,7 +110,7 @@ int main() // De-Initialization //-------------------------------------------------------------------------------------- free(bunnies); // Unload bunnies data array - + UnloadTexture(texBunny); // Unload bunny texture CloseWindow(); // Close window and OpenGL context diff --git a/examples/textures/textures_bunnymark.png b/examples/textures/textures_bunnymark.png new file mode 100644 index 000000000..4431ccec4 Binary files /dev/null and b/examples/textures/textures_bunnymark.png differ diff --git a/examples/textures/textures_image_drawing.c b/examples/textures/textures_image_drawing.c index b179612d4..02caf1f93 100644 --- a/examples/textures/textures_image_drawing.c +++ b/examples/textures/textures_image_drawing.c @@ -13,12 +13,12 @@ #include "raylib.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [textures] example - image drawing"); @@ -28,26 +28,26 @@ int main() ImageCrop(&cat, (Rectangle){ 100, 10, 280, 380 }); // Crop an image piece ImageFlipHorizontal(&cat); // Flip cropped image horizontally ImageResize(&cat, 150, 200); // Resize flipped-cropped image - + Image parrots = LoadImage("resources/parrots.png"); // Load image in CPU memory (RAM) - + // Draw one image over the other with a scaling of 1.5f - ImageDraw(&parrots, cat, (Rectangle){ 0, 0, cat.width, cat.height }, (Rectangle){ 30, 40, cat.width*1.5f, cat.height*1.5f }); + ImageDraw(&parrots, cat, (Rectangle){ 0, 0, cat.width, cat.height }, (Rectangle){ 30, 40, cat.width*1.5f, cat.height*1.5f }, WHITE); ImageCrop(&parrots, (Rectangle){ 0, 50, parrots.width, parrots.height - 100 }); // Crop resulting image - + UnloadImage(cat); // Unload image from RAM - + // Load custom font for frawing on image Font font = LoadFont("resources/custom_jupiter_crash.png"); - + // Draw over image using custom font ImageDrawTextEx(&parrots, (Vector2){ 300, 230 }, font, "PARROTS & CAT", font.baseSize, -2, WHITE); - + UnloadFont(font); // Unload custom spritefont (already drawn used on image) Texture2D texture = LoadTextureFromImage(parrots); // Image converted to texture, uploaded to GPU memory (VRAM) UnloadImage(parrots); // Once image has been converted to texture and uploaded to VRAM, it can be unloaded from RAM - + SetTargetFPS(60); //--------------------------------------------------------------------------------------- diff --git a/examples/textures/textures_image_generation.c b/examples/textures/textures_image_generation.c index b9608c89a..0bb10583c 100644 --- a/examples/textures/textures_image_generation.c +++ b/examples/textures/textures_image_generation.c @@ -13,12 +13,12 @@ #define NUM_TEXTURES 7 // Currently we have 7 generation algorithms -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [textures] example - procedural images generation"); @@ -30,7 +30,8 @@ int main() Image perlinNoise = GenImagePerlinNoise(screenWidth, screenHeight, 50, 50, 4.0f); Image cellular = GenImageCellular(screenWidth, screenHeight, 32); - Texture2D textures[NUM_TEXTURES]; + Texture2D textures[NUM_TEXTURES] = { 0 }; + textures[0] = LoadTextureFromImage(verticalGradient); textures[1] = LoadTextureFromImage(horizontalGradient); textures[2] = LoadTextureFromImage(radialGradient); @@ -38,7 +39,7 @@ int main() textures[4] = LoadTextureFromImage(whiteNoise); textures[5] = LoadTextureFromImage(perlinNoise); textures[6] = LoadTextureFromImage(cellular); - + // Unload image data (CPU RAM) UnloadImage(verticalGradient); UnloadImage(horizontalGradient); @@ -49,10 +50,10 @@ int main() UnloadImage(cellular); int currentTexture = 0; - + SetTargetFPS(60); //--------------------------------------------------------------------------------------- - + // Main game loop while (!WindowShouldClose()) { @@ -67,15 +68,15 @@ int main() // Draw //---------------------------------------------------------------------------------- BeginDrawing(); - + ClearBackground(RAYWHITE); - + DrawTexture(textures[currentTexture], 0, 0, WHITE); - + DrawRectangle(30, 400, 325, 30, Fade(SKYBLUE, 0.5f)); DrawRectangleLines(30, 400, 325, 30, Fade(WHITE, 0.5f)); DrawText("MOUSE LEFT BUTTON to CYCLE PROCEDURAL TEXTURES", 40, 410, 10, WHITE); - + switch(currentTexture) { case 0: DrawText("VERTICAL GRADIENT", 560, 10, 20, RAYWHITE); break; @@ -87,19 +88,19 @@ int main() case 6: DrawText("CELLULAR", 670, 10, 20, RAYWHITE); break; default: break; } - + EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- - + // Unload textures data (GPU VRAM) for (int i = 0; i < NUM_TEXTURES; i++) UnloadTexture(textures[i]); - + CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- - + return 0; } diff --git a/examples/textures/textures_image_loading.c b/examples/textures/textures_image_loading.c index 54c735860..265cab440 100644 --- a/examples/textures/textures_image_loading.c +++ b/examples/textures/textures_image_loading.c @@ -13,12 +13,12 @@ #include "raylib.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [textures] example - image loading"); diff --git a/examples/textures/textures_image_npatch.png b/examples/textures/textures_image_npatch.png deleted file mode 100644 index 5258811b4..000000000 Binary files a/examples/textures/textures_image_npatch.png and /dev/null differ diff --git a/examples/textures/textures_image_processing.c b/examples/textures/textures_image_processing.c index 6d33d95bf..14442290e 100644 --- a/examples/textures/textures_image_processing.c +++ b/examples/textures/textures_image_processing.c @@ -13,19 +13,19 @@ #include "raylib.h" -#include // Required for: free() +#include // Required for: free() #define NUM_PROCESSES 8 -typedef enum { - NONE = 0, - COLOR_GRAYSCALE, - COLOR_TINT, - COLOR_INVERT, - COLOR_CONTRAST, - COLOR_BRIGHTNESS, - FLIP_VERTICAL, - FLIP_HORIZONTAL +typedef enum { + NONE = 0, + COLOR_GRAYSCALE, + COLOR_TINT, + COLOR_INVERT, + COLOR_CONTRAST, + COLOR_BRIGHTNESS, + FLIP_VERTICAL, + FLIP_HORIZONTAL } ImageProcess; static const char *processText[] = { @@ -39,12 +39,12 @@ static const char *processText[] = { "FLIP HORIZONTAL" }; -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [textures] example - image processing"); @@ -57,10 +57,10 @@ int main() int currentProcess = NONE; bool textureReload = false; - Rectangle selectRecs[NUM_PROCESSES]; - + Rectangle selectRecs[NUM_PROCESSES] = { 0 }; + for (int i = 0; i < NUM_PROCESSES; i++) selectRecs[i] = (Rectangle){ 40.0f, (float)(50 + 32*i), 150.0f, 30.0f }; - + SetTargetFPS(60); //--------------------------------------------------------------------------------------- @@ -81,14 +81,14 @@ int main() if (currentProcess < 0) currentProcess = 7; textureReload = true; } - + if (textureReload) { UnloadImage(image); // Unload current image data image = LoadImage("resources/parrots.png"); // Re-load image data - // NOTE: Image processing is a costly CPU process to be done every frame, - // If image processing is required in a frame-basis, it should be done + // NOTE: Image processing is a costly CPU process to be done every frame, + // If image processing is required in a frame-basis, it should be done // with a texture and by shaders switch (currentProcess) { @@ -101,11 +101,11 @@ int main() case FLIP_HORIZONTAL: ImageFlipHorizontal(&image); break; default: break; } - + Color *pixels = GetImageData(image); // Get pixel data from image (RGBA 32bit) UpdateTexture(texture, pixels); // Update texture with new image data free(pixels); // Unload pixels data from RAM - + textureReload = false; } //---------------------------------------------------------------------------------- @@ -115,9 +115,9 @@ int main() BeginDrawing(); ClearBackground(RAYWHITE); - + DrawText("IMAGE PROCESSING:", 40, 30, 10, DARKGRAY); - + // Draw rectangles for (int i = 0; i < NUM_PROCESSES; i++) { @@ -128,7 +128,7 @@ int main() DrawTexture(texture, screenWidth - texture.width - 60, screenHeight/2 - texture.height/2, WHITE); DrawRectangleLines(screenWidth - texture.width - 60, screenHeight/2 - texture.height/2, texture.width, texture.height, BLACK); - + EndDrawing(); //---------------------------------------------------------------------------------- } diff --git a/examples/textures/textures_image_text.c b/examples/textures/textures_image_text.c index ce91fbf26..c8dfe4589 100644 --- a/examples/textures/textures_image_text.c +++ b/examples/textures/textures_image_text.c @@ -11,28 +11,28 @@ #include "raylib.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [texture] example - image text drawing"); + Image parrots = LoadImage("resources/parrots.png"); // Load image in CPU memory (RAM) + // TTF Font loading with custom generation parameters Font font = LoadFontEx("resources/KAISG.ttf", 64, 0, 0); - - Image parrots = LoadImage("resources/parrots.png"); // Load image in CPU memory (RAM) // Draw over image using custom font ImageDrawTextEx(&parrots, (Vector2){ 20.0f, 20.0f }, font, "[Parrots font drawing]", (float)font.baseSize, 0.0f, RED); Texture2D texture = LoadTextureFromImage(parrots); // Image converted to texture, uploaded to GPU memory (VRAM) UnloadImage(parrots); // Once image has been converted to texture and uploaded to VRAM, it can be unloaded from RAM - + Vector2 position = { (float)(screenWidth/2 - texture.width/2), (float)(screenHeight/2 - texture.height/2 - 20) }; - + bool showFont = false; SetTargetFPS(60); @@ -57,15 +57,15 @@ int main() { // Draw texture with text already drawn inside DrawTextureV(texture, position, WHITE); - + // Draw text directly using sprite font - DrawTextEx(font, "[Parrots font drawing]", (Vector2){ position.x + 20, + DrawTextEx(font, "[Parrots font drawing]", (Vector2){ position.x + 20, position.y + 20 + 280 }, (float)font.baseSize, 0.0f, WHITE); } else DrawTexture(font.texture, screenWidth/2 - font.texture.width/2, 50, BLACK); - + DrawText("PRESS SPACE to SEE USED SPRITEFONT ", 290, 420, 10, DARKGRAY); - + EndDrawing(); //---------------------------------------------------------------------------------- } @@ -73,9 +73,9 @@ int main() // De-Initialization //-------------------------------------------------------------------------------------- UnloadTexture(texture); // Texture unloading - - UnloadFont(font); // Unload custom spritefont - + + UnloadFont(font); // Unload custom spritefont + CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/textures/textures_logo_raylib.c b/examples/textures/textures_logo_raylib.c index f2f931281..de8bb2aee 100644 --- a/examples/textures/textures_logo_raylib.c +++ b/examples/textures/textures_logo_raylib.c @@ -11,12 +11,12 @@ #include "raylib.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [textures] example - texture loading and drawing"); diff --git a/examples/textures/textures_mouse_painting.c b/examples/textures/textures_mouse_painting.c new file mode 100644 index 000000000..0149176c5 --- /dev/null +++ b/examples/textures/textures_mouse_painting.c @@ -0,0 +1,210 @@ +/******************************************************************************************* +* +* raylib [textures] example - Mouse painting +* +* This example has been created using raylib 2.5 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Example contributed by Chris Dill (@MysteriousSpace) and reviewed by Ramon Santamaria (@raysan5) +* +* Copyright (c) 2019 Chris Dill (@MysteriousSpace) and Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#define MAX_COLORS_COUNT 23 // Number of colors available + +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [textures] example - mouse painting"); + + // Colours to choose from + Color colors[MAX_COLORS_COUNT] = { + RAYWHITE, YELLOW, GOLD, ORANGE, PINK, RED, MAROON, GREEN, LIME, DARKGREEN, + SKYBLUE, BLUE, DARKBLUE, PURPLE, VIOLET, DARKPURPLE, BEIGE, BROWN, DARKBROWN, + LIGHTGRAY, GRAY, DARKGRAY, BLACK }; + + // Define colorsRecs data (for every rectangle) + Rectangle colorsRecs[MAX_COLORS_COUNT] = { 0 }; + + for (int i = 0; i < MAX_COLORS_COUNT; i++) + { + colorsRecs[i].x = 10 + 30*i + 2*i; + colorsRecs[i].y = 10; + colorsRecs[i].width = 30; + colorsRecs[i].height = 30; + } + + int colorSelected = 0; + int colorSelectedPrev = colorSelected; + int colorMouseHover = 0; + int brushSize = 20; + + Rectangle btnSaveRec = { 750, 10, 40, 30 }; + bool btnSaveMouseHover = false; + bool showSaveMessage = false; + int saveMessageCounter = 0; + + // Create a RenderTexture2D to use as a canvas + RenderTexture2D target = LoadRenderTexture(screenWidth, screenHeight); + + // Clear render texture before entering the game loop + BeginTextureMode(target); + ClearBackground(colors[0]); + EndTextureMode(); + + SetTargetFPS(120); // Set our game to run at 120 frames-per-second + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + Vector2 mousePos = GetMousePosition(); + + // Move between colors with keys + if (IsKeyPressed(KEY_RIGHT)) colorSelected++; + else if (IsKeyPressed(KEY_LEFT)) colorSelected--; + + if (colorSelected >= MAX_COLORS_COUNT) colorSelected = MAX_COLORS_COUNT - 1; + else if (colorSelected < 0) colorSelected = 0; + + // Choose color with mouse + for (int i = 0; i < MAX_COLORS_COUNT; i++) + { + if (CheckCollisionPointRec(mousePos, colorsRecs[i])) + { + colorMouseHover = i; + break; + } + else colorMouseHover = -1; + } + + if ((colorMouseHover >= 0) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + colorSelected = colorMouseHover; + colorSelectedPrev = colorSelected; + } + + // Change brush size + brushSize += GetMouseWheelMove()*5; + if (brushSize < 2) brushSize = 2; + if (brushSize > 50) brushSize = 50; + + if (IsKeyPressed(KEY_C)) + { + // Clear render texture to clear color + BeginTextureMode(target); + ClearBackground(colors[0]); + EndTextureMode(); + } + + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) + { + // Paint circle into render texture + // NOTE: To avoid discontinuous circles, we could store + // previous-next mouse points and just draw a line using brush size + BeginTextureMode(target); + if (mousePos.y > 50) DrawCircle(mousePos.x, mousePos.y, brushSize, colors[colorSelected]); + EndTextureMode(); + } + + if (IsMouseButtonDown(MOUSE_RIGHT_BUTTON)) + { + colorSelected = 0; + + // Erase circle from render texture + BeginTextureMode(target); + if (mousePos.y > 50) DrawCircle(mousePos.x, mousePos.y, brushSize, colors[0]); + EndTextureMode(); + } + else colorSelected = colorSelectedPrev; + + // Check mouse hover save button + if (CheckCollisionPointRec(mousePos, btnSaveRec)) btnSaveMouseHover = true; + else btnSaveMouseHover = false; + + // Image saving logic + // NOTE: Saving painted texture to a default named image + if ((btnSaveMouseHover && IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) || IsKeyPressed(KEY_S)) + { + Image image = GetTextureData(target.texture); + ImageFlipVertical(&image); + ExportImage(image, "my_amazing_texture_painting.png"); + UnloadImage(image); + showSaveMessage = true; + } + + if (showSaveMessage) + { + // On saving, show a full screen message for 2 seconds + saveMessageCounter++; + if (saveMessageCounter > 240) + { + showSaveMessage = false; + saveMessageCounter = 0; + } + } + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + // NOTE: Render texture must be y-flipped due to default OpenGL coordinates (left-bottom) + DrawTextureRec(target.texture, (Rectangle){ 0, 0, target.texture.width, -target.texture.height }, (Vector2){ 0, 0 }, WHITE); + + // Draw drawing circle for reference + if (mousePos.y > 50) + { + if (IsMouseButtonDown(MOUSE_RIGHT_BUTTON)) DrawCircleLines(mousePos.x, mousePos.y, brushSize, colors[colorSelected]); + else DrawCircle(GetMouseX(), GetMouseY(), brushSize, colors[colorSelected]); + } + + // Draw top panel + DrawRectangle(0, 0, GetScreenWidth(), 50, RAYWHITE); + DrawLine(0, 50, GetScreenWidth(), 50, LIGHTGRAY); + + // Draw color selection rectangles + for (int i = 0; i < MAX_COLORS_COUNT; i++) DrawRectangleRec(colorsRecs[i], colors[i]); + DrawRectangleLines(10, 10, 30, 30, LIGHTGRAY); + + if (colorMouseHover >= 0) DrawRectangleRec(colorsRecs[colorMouseHover], Fade(WHITE, 0.6f)); + + DrawRectangleLinesEx((Rectangle){ colorsRecs[colorSelected].x - 2, colorsRecs[colorSelected].y - 2, + colorsRecs[colorSelected].width + 4, colorsRecs[colorSelected].height + 4 }, 2, BLACK); + + // Draw save image button + DrawRectangleLinesEx(btnSaveRec, 2, btnSaveMouseHover? RED : BLACK); + DrawText("SAVE!", 755, 20, 10, btnSaveMouseHover? RED : BLACK); + + // Draw save image message + if (showSaveMessage) + { + DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), Fade(RAYWHITE, 0.8f)); + DrawRectangle(0, 150, GetScreenWidth(), 80, BLACK); + DrawText("IMAGE SAVED: my_amazing_texture_painting.png", 150, 180, 20, RAYWHITE); + } + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadRenderTexture(target); // Unload render texture + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} diff --git a/examples/textures/textures_mouse_painting.png b/examples/textures/textures_mouse_painting.png new file mode 100644 index 000000000..a3dec5dad Binary files /dev/null and b/examples/textures/textures_mouse_painting.png differ diff --git a/examples/textures/textures_image_npatch.c b/examples/textures/textures_npatch_drawing.c similarity index 71% rename from examples/textures/textures_image_npatch.c rename to examples/textures/textures_npatch_drawing.c index 357b8a98c..1c57e2e72 100644 --- a/examples/textures/textures_image_npatch.c +++ b/examples/textures/textures_npatch_drawing.c @@ -7,40 +7,45 @@ * This example has been created using raylib 2.0 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * -* Copyright (c) 2016 Ramon Santamaria (@raysan5) +* Example contributed by Jorge A. Gomes (@overdev) and reviewed by Ramon Santamaria (@raysan5) +* +* Copyright (c) 2018 Jorge A. Gomes (@overdev) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ #include "raylib.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [textures] example - N-patch drawing"); // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) Texture2D nPatchTexture = LoadTexture("resources/ninepatch_button.png"); - Vector2 mousePosition; - Vector2 origin = {0.0f, 0.0f}; - // The location and size of the n-patches. - Rectangle dstRec1 = {480.0f, 160.0f, 32.0f, 32.0f}; - Rectangle dstRec2 = {160.0f, 160.0f, 32.0f, 32.0f}; - Rectangle dstRecH = {160.0f, 93.0f, 32.0f, 32.0f}; // this rec's height is ignored - Rectangle dstRecV = {92.0f, 160.0f, 32.0f, 32.0f}; // this rec's width is ignored + Vector2 mousePosition = { 0 }; + Vector2 origin = { 0.0f, 0.0f }; + + // Position and size of the n-patches + Rectangle dstRec1 = { 480.0f, 160.0f, 32.0f, 32.0f }; + Rectangle dstRec2 = { 160.0f, 160.0f, 32.0f, 32.0f }; + Rectangle dstRecH = { 160.0f, 93.0f, 32.0f, 32.0f }; + Rectangle dstRecV = { 92.0f, 160.0f, 32.0f, 32.0f }; // A 9-patch (NPT_9PATCH) changes its sizes in both axis - NPatchInfo ninePatchInfo1 = {(Rectangle){0.0f, 0.0f, 64.0f, 64.0f}, 12, 40, 12, 12, NPT_9PATCH }; - NPatchInfo ninePatchInfo2 = {(Rectangle){0.0f, 128.0f, 64.0f, 64.0f}, 16, 16, 16, 16, NPT_9PATCH }; + NPatchInfo ninePatchInfo1 = { (Rectangle){ 0.0f, 0.0f, 64.0f, 64.0f }, 12, 40, 12, 12, NPT_9PATCH }; + NPatchInfo ninePatchInfo2 = { (Rectangle){ 0.0f, 128.0f, 64.0f, 64.0f }, 16, 16, 16, 16, NPT_9PATCH }; + // A horizontal 3-patch (NPT_3PATCH_HORIZONTAL) changes its sizes along the x axis only - NPatchInfo h3PatchInfo = {(Rectangle){0.0f, 64.0f, 64.0f, 64.0f}, 8, 8, 8, 8, NPT_3PATCH_HORIZONTAL }; + NPatchInfo h3PatchInfo = { (Rectangle){ 0.0f, 64.0f, 64.0f, 64.0f }, 8, 8, 8, 8, NPT_3PATCH_HORIZONTAL }; + // A vertical 3-patch (NPT_3PATCH_VERTICAL) changes its sizes along the y axis only - NPatchInfo v3PatchInfo = {(Rectangle){0.0f, 192.0f, 64.0f, 64.0f}, 6, 6, 6, 6, NPT_3PATCH_VERTICAL }; - + NPatchInfo v3PatchInfo = { (Rectangle){ 0.0f, 192.0f, 64.0f, 64.0f }, 6, 6, 6, 6, NPT_3PATCH_VERTICAL }; + SetTargetFPS(60); //--------------------------------------------------------------------------------------- @@ -50,7 +55,8 @@ int main() // Update //---------------------------------------------------------------------------------- mousePosition = GetMousePosition(); - // resize the n-patches based on mouse position. + + // Resize the n-patches based on mouse position dstRec1.width = mousePosition.x - dstRec1.x; dstRec1.height = mousePosition.y - dstRec1.y; dstRec2.width = mousePosition.x - dstRec2.x; @@ -58,7 +64,7 @@ int main() dstRecH.width = mousePosition.x - dstRecH.x; dstRecV.height = mousePosition.y - dstRecV.y; - // set a minimum width and/or height + // Set a minimum width and/or height if (dstRec1.width < 1.0f) dstRec1.width = 1.0f; if (dstRec1.width > 300.0f) dstRec1.width = 300.0f; if (dstRec1.height < 1.0f) dstRec1.height = 1.0f; @@ -80,18 +86,13 @@ int main() DrawTextureNPatch(nPatchTexture, ninePatchInfo1, dstRec1, origin, 0.0f, WHITE); DrawTextureNPatch(nPatchTexture, h3PatchInfo, dstRecH, origin, 0.0f, WHITE); DrawTextureNPatch(nPatchTexture, v3PatchInfo, dstRecV, origin, 0.0f, WHITE); - + // Draw the source texture - DrawRectangleLines( 5, 88, 74, 266, BLUE); + DrawRectangleLines(5, 88, 74, 266, BLUE); DrawTexture(nPatchTexture, 10, 93, WHITE); DrawText("TEXTURE", 15, 360, 10, DARKGRAY); - DrawRectangle( 10, 10, 250, 73, Fade(SKYBLUE, 0.5)); - DrawRectangleLines( 10, 10, 250, 73, BLUE); - - DrawText("9-Patch and 3-Patch example", 20, 20, 10, BLACK); - DrawText(" Move the mouse to stretch or", 40, 40, 10, DARKGRAY); - DrawText(" shrink the n-patches.", 40, 60, 10, DARKGRAY); + DrawText("Move the mouse to stretch or shrink the n-patches", 10, 20, 20, DARKGRAY); EndDrawing(); //---------------------------------------------------------------------------------- diff --git a/examples/textures/textures_npatch_drawing.png b/examples/textures/textures_npatch_drawing.png new file mode 100644 index 000000000..21df9caab Binary files /dev/null and b/examples/textures/textures_npatch_drawing.png differ diff --git a/examples/textures/textures_particles_blending.c b/examples/textures/textures_particles_blending.c index 3b7dcaa38..d094c6c2a 100644 --- a/examples/textures/textures_particles_blending.c +++ b/examples/textures/textures_particles_blending.c @@ -23,18 +23,18 @@ typedef struct { bool active; // NOTE: Use it to activate/deactive particle } Particle; -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [textures] example - particles blending"); - + // Particles pool, reuse them! - Particle mouseTail[MAX_PARTICLES]; - + Particle mouseTail[MAX_PARTICLES] = { 0 }; + // Initialize particles for (int i = 0; i < MAX_PARTICLES; i++) { @@ -45,13 +45,13 @@ int main() mouseTail[i].rotation = (float)GetRandomValue(0, 360); mouseTail[i].active = false; } - + float gravity = 3.0f; Texture2D smoke = LoadTexture("resources/smoke.png"); - + int blending = BLEND_ALPHA; - + SetTargetFPS(60); //-------------------------------------------------------------------------------------- @@ -60,7 +60,7 @@ int main() { // Update //---------------------------------------------------------------------------------- - + // Activate one particle every frame and Update active particles // NOTE: Particles initial position should be mouse position when activated // NOTE: Particles fall down with gravity and rotation... and disappear after 2 seconds (alpha = 0) @@ -82,13 +82,13 @@ int main() { mouseTail[i].position.y += gravity; mouseTail[i].alpha -= 0.01f; - + if (mouseTail[i].alpha <= 0.0f) mouseTail[i].active = false; - + mouseTail[i].rotation += 5.0f; } } - + if (IsKeyPressed(KEY_SPACE)) { if (blending == BLEND_ALPHA) blending = BLEND_ADDITIVE; @@ -101,25 +101,25 @@ int main() BeginDrawing(); ClearBackground(DARKGRAY); - + BeginBlendMode(blending); // Draw active particles for (int i = 0; i < MAX_PARTICLES; i++) { - if (mouseTail[i].active) DrawTexturePro(smoke, (Rectangle){ 0.0f, 0.0f, (float)smoke.width, (float)smoke.height }, + if (mouseTail[i].active) DrawTexturePro(smoke, (Rectangle){ 0.0f, 0.0f, (float)smoke.width, (float)smoke.height }, (Rectangle){ mouseTail[i].position.x, mouseTail[i].position.y, smoke.width*mouseTail[i].size, smoke.height*mouseTail[i].size }, (Vector2){ (float)(smoke.width*mouseTail[i].size/2.0f), (float)(smoke.height*mouseTail[i].size/2.0f) }, mouseTail[i].rotation, Fade(mouseTail[i].color, mouseTail[i].alpha)); } - + EndBlendMode(); - + DrawText("PRESS SPACE to CHANGE BLENDING MODE", 180, 20, 20, BLACK); - + if (blending == BLEND_ALPHA) DrawText("ALPHA BLENDING", 290, screenHeight - 40, 20, BLACK); else DrawText("ADDITIVE BLENDING", 280, screenHeight - 40, 20, RAYWHITE); - + EndDrawing(); //---------------------------------------------------------------------------------- } @@ -127,7 +127,7 @@ int main() // De-Initialization //-------------------------------------------------------------------------------------- UnloadTexture(smoke); - + CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/textures/textures_raw_data.c b/examples/textures/textures_raw_data.c index 481bd66a1..08269bf78 100644 --- a/examples/textures/textures_raw_data.c +++ b/examples/textures/textures_raw_data.c @@ -13,31 +13,31 @@ #include "raylib.h" -#include // Required for malloc() and free() +#include // Required for: malloc() and free() -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [textures] example - texture from raw data"); // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) - + // Load RAW image data (512x512, 32bit RGBA, no file header) Image fudesumiRaw = LoadImageRaw("resources/fudesumi.raw", 384, 512, UNCOMPRESSED_R8G8B8A8, 0); - Texture2D fudesumi = LoadTextureFromImage(fudesumiRaw); // Upload CPU (RAM) image to GPU (VRAM) - UnloadImage(fudesumiRaw); // Unload CPU (RAM) image data - - // Generate a checked texture by code (1024x1024 pixels) + Texture2D fudesumi = LoadTextureFromImage(fudesumiRaw); // Upload CPU (RAM) image to GPU (VRAM) + UnloadImage(fudesumiRaw); // Unload CPU (RAM) image data + + // Generate a checked texture by code int width = 960; int height = 480; - + // Dynamic memory allocation to store pixels data (Color type) Color *pixels = (Color *)malloc(width*height*sizeof(Color)); - + for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) @@ -46,14 +46,14 @@ int main() else pixels[y*width + x] = GOLD; } } - + // Load pixels data into an image structure and create texture Image checkedIm = LoadImageEx(pixels, width, height); Texture2D checked = LoadTextureFromImage(checkedIm); - UnloadImage(checkedIm); // Unload CPU (RAM) image data - + UnloadImage(checkedIm); // Unload CPU (RAM) image data + // Dynamic memory must be freed after using it - free(pixels); // Unload CPU (RAM) pixels data + free(pixels); // Unload CPU (RAM) pixels data //--------------------------------------------------------------------------------------- // Main game loop @@ -76,7 +76,7 @@ int main() DrawText("CHECKED TEXTURE ", 84, 85, 30, BROWN); DrawText("GENERATED by CODE", 72, 148, 30, BROWN); DrawText("and RAW IMAGE LOADING", 46, 210, 30, BROWN); - + DrawText("(c) Fudesumi sprite by Eiden Marsal", 310, screenHeight - 20, 10, BROWN); EndDrawing(); diff --git a/examples/textures/textures_rectangle.c b/examples/textures/textures_rectangle.c index e12477460..8be647a22 100644 --- a/examples/textures/textures_rectangle.c +++ b/examples/textures/textures_rectangle.c @@ -14,12 +14,12 @@ #define MAX_FRAME_SPEED 15 #define MIN_FRAME_SPEED 1 -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [texture] example - texture rectangle"); @@ -29,10 +29,10 @@ int main() Vector2 position = { 350.0f, 280.0f }; Rectangle frameRec = { 0.0f, 0.0f, (float)scarfy.width/6, (float)scarfy.height }; int currentFrame = 0; - + int framesCounter = 0; - int framesSpeed = 8; // Number of spritesheet frames shown by second - + int framesSpeed = 8; // Number of spritesheet frames shown by second + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- @@ -42,20 +42,20 @@ int main() // Update //---------------------------------------------------------------------------------- framesCounter++; - + if (framesCounter >= (60/framesSpeed)) { framesCounter = 0; currentFrame++; - + if (currentFrame > 5) currentFrame = 0; - + frameRec.x = (float)currentFrame*(float)scarfy.width/6; } - + if (IsKeyPressed(KEY_RIGHT)) framesSpeed++; else if (IsKeyPressed(KEY_LEFT)) framesSpeed--; - + if (framesSpeed > MAX_FRAME_SPEED) framesSpeed = MAX_FRAME_SPEED; else if (framesSpeed < MIN_FRAME_SPEED) framesSpeed = MIN_FRAME_SPEED; //---------------------------------------------------------------------------------- @@ -69,17 +69,17 @@ int main() DrawTexture(scarfy, 15, 40, WHITE); DrawRectangleLines(15, 40, scarfy.width, scarfy.height, LIME); DrawRectangleLines(15 + frameRec.x, 40 + frameRec.y, frameRec.width, frameRec.height, RED); - + DrawText("FRAME SPEED: ", 165, 210, 10, DARKGRAY); DrawText(FormatText("%02i FPS", framesSpeed), 575, 210, 10, DARKGRAY); DrawText("PRESS RIGHT/LEFT KEYS to CHANGE SPEED!", 290, 240, 10, DARKGRAY); - + for (int i = 0; i < MAX_FRAME_SPEED; i++) { if (i < framesSpeed) DrawRectangle(250 + 21*i, 205, 20, 20, RED); DrawRectangleLines(250 + 21*i, 205, 20, 20, MAROON); } - + DrawTextureRec(scarfy, frameRec, position, WHITE); // Draw part of the texture DrawText("(c) Scarfy sprite by Eiden Marsal", screenWidth - 200, screenHeight - 20, 10, GRAY); diff --git a/examples/textures/textures_sprite_button.c b/examples/textures/textures_sprite_button.c index bbd57328a..a5b2d8d13 100644 --- a/examples/textures/textures_sprite_button.c +++ b/examples/textures/textures_sprite_button.c @@ -13,35 +13,35 @@ #define NUM_FRAMES 3 // Number of frames (rectangles) for the button sprite texture -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- const int screenWidth = 800; const int screenHeight = 450; - + InitWindow(screenWidth, screenHeight, "raylib [textures] example - sprite button"); InitAudioDevice(); // Initialize audio device - + Sound fxButton = LoadSound("resources/buttonfx.wav"); // Load button sound Texture2D button = LoadTexture("resources/button.png"); // Load button texture - + // Define frame rectangle for drawing int frameHeight = button.height/NUM_FRAMES; Rectangle sourceRec = { 0, 0, button.width, frameHeight }; - + // Define button bounds on screen Rectangle btnBounds = { screenWidth/2 - button.width/2, screenHeight/2 - button.height/NUM_FRAMES/2, button.width, frameHeight }; - + int btnState = 0; // Button state: 0-NORMAL, 1-MOUSE_HOVER, 2-PRESSED bool btnAction = false; // Button action should be activated - + Vector2 mousePoint = { 0.0f, 0.0f }; - + SetTargetFPS(60); //-------------------------------------------------------------------------------------- - + // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { @@ -49,7 +49,7 @@ int main() //---------------------------------------------------------------------------------- mousePoint = GetMousePosition(); btnAction = false; - + // Check button state if (CheckCollisionPointRec(mousePoint, btnBounds)) { @@ -59,26 +59,26 @@ int main() if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) btnAction = true; } else btnState = 0; - + if (btnAction) { PlaySound(fxButton); - + // TODO: Any desired action } - + // Calculate button frame rectangle to draw depending on button state sourceRec.y = btnState*frameHeight; //---------------------------------------------------------------------------------- - + // Draw //---------------------------------------------------------------------------------- BeginDrawing(); - + ClearBackground(RAYWHITE); DrawTextureRec(button, sourceRec, (Vector2){ btnBounds.x, btnBounds.y }, WHITE); // Draw button frame - + EndDrawing(); //---------------------------------------------------------------------------------- } @@ -89,9 +89,9 @@ int main() UnloadSound(fxButton); // Unload sound CloseAudioDevice(); // Close audio device - + CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- - + return 0; } \ No newline at end of file diff --git a/examples/textures/textures_sprite_button.png b/examples/textures/textures_sprite_button.png new file mode 100644 index 000000000..dac519d4c Binary files /dev/null and b/examples/textures/textures_sprite_button.png differ diff --git a/examples/textures/textures_sprite_explosion.c b/examples/textures/textures_sprite_explosion.c index aa10a76cf..823c1b8ab 100644 --- a/examples/textures/textures_sprite_explosion.c +++ b/examples/textures/textures_sprite_explosion.c @@ -11,97 +11,97 @@ #include "raylib.h" -#define NUM_FRAMES 8 -#define NUM_LINES 6 +#define NUM_FRAMES 8 +#define NUM_LINES 6 -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- const int screenWidth = 800; const int screenHeight = 450; - + InitWindow(screenWidth, screenHeight, "raylib [textures] example - sprite explosion"); - + InitAudioDevice(); - + // Load explosion sound Sound fxBoom = LoadSound("resources/boom.wav"); - + // Load explosion texture - Texture2D explosion = LoadTexture("resources/explosion2.png"); + Texture2D explosion = LoadTexture("resources/explosion.png"); // Init variables for animation int frameWidth = explosion.width/NUM_FRAMES; // Sprite one frame rectangle width int frameHeight = explosion.height/NUM_LINES; // Sprite one frame rectangle height int currentFrame = 0; int currentLine = 0; - + Rectangle frameRec = { 0, 0, frameWidth, frameHeight }; - Vector2 position = { 0, 0 }; - + Vector2 position = { 0.0f, 0.0f }; + bool active = false; int framesCounter = 0; - + SetTargetFPS(120); //-------------------------------------------------------------------------------------- - + // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { // Update //---------------------------------------------------------------------------------- - + // Check for mouse button pressed and activate explosion (if not active) if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON) && !active) { position = GetMousePosition(); active = true; - + position.x -= frameWidth/2; position.y -= frameHeight/2; - + PlaySound(fxBoom); } - + // Compute explosion animation frames if (active) { framesCounter++; - + if (framesCounter > 2) { currentFrame++; - + if (currentFrame >= NUM_FRAMES) { currentFrame = 0; currentLine++; - + if (currentLine >= NUM_LINES) { currentLine = 0; active = false; } } - + framesCounter = 0; } } - + frameRec.x = frameWidth*currentFrame; frameRec.y = frameHeight*currentLine; //---------------------------------------------------------------------------------- - + // Draw //---------------------------------------------------------------------------------- BeginDrawing(); - + ClearBackground(RAYWHITE); - + // Draw explosion required frame rectangle if (active) DrawTextureRec(explosion, frameRec, position, WHITE); - + EndDrawing(); //---------------------------------------------------------------------------------- } @@ -109,12 +109,12 @@ int main() // De-Initialization //-------------------------------------------------------------------------------------- UnloadTexture(explosion); // Unload texture - UnloadSound(fxBoom); // Unload sound - + UnloadSound(fxBoom); // Unload sound + CloseAudioDevice(); - + CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- - + return 0; } \ No newline at end of file diff --git a/examples/textures/textures_sprite_explosion.png b/examples/textures/textures_sprite_explosion.png new file mode 100644 index 000000000..8a439c35d Binary files /dev/null and b/examples/textures/textures_sprite_explosion.png differ diff --git a/examples/textures/textures_srcrec_dstrec.c b/examples/textures/textures_srcrec_dstrec.c index 298a0c65e..e86b729d6 100644 --- a/examples/textures/textures_srcrec_dstrec.c +++ b/examples/textures/textures_srcrec_dstrec.c @@ -11,32 +11,33 @@ #include "raylib.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [textures] examples - texture source and destination rectangles"); // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) + Texture2D scarfy = LoadTexture("resources/scarfy.png"); // Texture loading int frameWidth = scarfy.width/6; int frameHeight = scarfy.height; - - // NOTE: Source rectangle (part of the texture to use for drawing) + + // Source rectangle (part of the texture to use for drawing) Rectangle sourceRec = { 0.0f, 0.0f, frameWidth, frameHeight }; - // NOTE: Destination rectangle (screen rectangle where drawing part of texture) + // Destination rectangle (screen rectangle where drawing part of texture) Rectangle destRec = { screenWidth/2, screenHeight/2, frameWidth*2, frameHeight*2 }; - // NOTE: Origin of the texture (rotation/scale point), it's relative to destination rectangle size + // Origin of the texture (rotation/scale point), it's relative to destination rectangle size Vector2 origin = { frameWidth, frameHeight }; - + int rotation = 0; - + SetTargetFPS(60); //-------------------------------------------------------------------------------------- @@ -63,7 +64,7 @@ int main() DrawLine((int)destRec.x, 0, (int)destRec.x, screenHeight, GRAY); DrawLine(0, (int)destRec.y, screenWidth, (int)destRec.y, GRAY); - + DrawText("(c) Scarfy sprite by Eiden Marsal", screenWidth - 200, screenHeight - 20, 10, GRAY); EndDrawing(); diff --git a/examples/textures/textures_to_image.c b/examples/textures/textures_to_image.c index 37c3b5a00..c0989bafe 100644 --- a/examples/textures/textures_to_image.c +++ b/examples/textures/textures_to_image.c @@ -1,6 +1,6 @@ /******************************************************************************************* * -* raylib [textures] example - Retrieve image data from texture: GetTextureData() +* raylib [textures] example - Retrieve image data from texture: GetTextureData() * * NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM) * @@ -13,12 +13,12 @@ #include "raylib.h" -int main() +int main(void) { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + const int screenWidth = 800; + const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [textures] example - texture to image"); @@ -27,10 +27,10 @@ int main() Image image = LoadImage("resources/raylib_logo.png"); // Load image data into CPU memory (RAM) Texture2D texture = LoadTextureFromImage(image); // Image converted to texture, GPU memory (RAM -> VRAM) UnloadImage(image); // Unload image data from CPU memory (RAM) - + image = GetTextureData(texture); // Retrieve image data from GPU memory (VRAM -> RAM) UnloadTexture(texture); // Unload texture from GPU memory (VRAM) - + texture = LoadTextureFromImage(image); // Recreate texture from retrieved image data (RAM -> VRAM) UnloadImage(image); // Unload retrieved image data from CPU memory (RAM) //--------------------------------------------------------------------------------------- diff --git a/games/CMakeLists.txt b/games/CMakeLists.txt index d3f9d9fcf..90a5ed08b 100644 --- a/games/CMakeLists.txt +++ b/games/CMakeLists.txt @@ -8,8 +8,13 @@ set(OUTPUT_EXT) if(${PLATFORM} MATCHES "Web") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Os -s USE_GLFW=3 -s ASSERTIONS=1 -s WASM=1 -s EMTERPRETIFY=1 -s EMTERPRETIFY_ASYNC=1") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --shell-file ${CMAKE_SOURCE_DIR}/templates/web_shell/shell.html") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --shell-file ${CMAKE_SOURCE_DIR}/src/shell.html") set(OUTPUT_EXT ".html") + + # Remove the -rdynamic flag because otherwise emscripten + # does not generate HTML+JS+WASM files, only a non-working + # and fat HTML + string(REPLACE "-rdynamic" "" CMAKE_SHARED_LIBRARY_LINK_C_FLAGS ${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS}) endif() if (NOT TARGET raylib) diff --git a/games/Makefile b/games/Makefile index 44e053c6b..9b06cc0a4 100644 --- a/games/Makefile +++ b/games/Makefile @@ -24,28 +24,43 @@ .PHONY: all clean # Define required raylib variables -# WARNING: To compile to HTML5, code must be redesigned to use emscripten.h and emscripten_set_main_loop() -PLATFORM ?= PLATFORM_DESKTOP -RAYLIB_PATH ?= .. -PROJECT_NAME ?= sample_game +PROJECT_NAME ?= raylib_examples +RAYLIB_VERSION ?= 2.5.0 +RAYLIB_API_VERSION ?= 2 +RAYLIB_PATH ?= .. -# Default path for raylib on Raspberry Pi, if installed in different path, update it! -ifeq ($(PLATFORM),PLATFORM_RPI) - RAYLIB_PATH ?= /home/pi/raylib -endif +# Define default options + +# One of PLATFORM_DESKTOP, PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB +PLATFORM ?= PLATFORM_DESKTOP + +# Locations of your newly installed library and associated headers. See ../src/Makefile +# On Linux, if you have installed raylib but cannot compile the examples, check that +# the *_INSTALL_PATH values here are the same as those in src/Makefile or point to known locations. +# To enable system-wide compile-time and runtime linking to libraylib.so, run ../src/$ sudo make install RAYLIB_LIBTYPE_SHARED. +# To enable compile-time linking to a special version of libraylib.so, change these variables here. +# To enable runtime linking to a special version of libraylib.so, see EXAMPLE_RUNTIME_PATH below. +# If there is a libraylib in both EXAMPLE_RUNTIME_PATH and RAYLIB_INSTALL_PATH, at runtime, +# the library at EXAMPLE_RUNTIME_PATH, if present, will take precedence over the one at RAYLIB_INSTALL_PATH. +# RAYLIB_INSTALL_PATH should be the desired full path to libraylib. No relative paths. +DESTDIR ?= /usr/local +RAYLIB_INSTALL_PATH ?= $(DESTDIR)/lib +# RAYLIB_H_INSTALL_PATH locates the installed raylib header and associated source files. +RAYLIB_H_INSTALL_PATH ?= $(DESTDIR)/include # Library type used for raylib: STATIC (.a) or SHARED (.so/.dll) -RAYLIB_LIBTYPE ?= STATIC +RAYLIB_LIBTYPE ?= STATIC + +# Build mode for project: DEBUG or RELEASE +BUILD_MODE ?= RELEASE # Use external GLFW library instead of rglfw module -USE_EXTERNAL_GLFW ?= FALSE +# TODO: Review usage on Linux. Target version of choice. Switch on -lglfw or -lglfw3 +USE_EXTERNAL_GLFW ?= FALSE # Use Wayland display server protocol on Linux desktop # by default it uses X11 windowing system -USE_WAYLAND_DISPLAY ?= FALSE - -# NOTE: On PLATFORM_WEB OpenAL Soft backend is used by default (check raylib/src/Makefile) - +USE_WAYLAND_DISPLAY ?= FALSE # Determine PLATFORM_OS in case PLATFORM_DESKTOP selected ifeq ($(PLATFORM),PLATFORM_DESKTOP) @@ -82,40 +97,50 @@ ifeq ($(PLATFORM),PLATFORM_RPI) endif endif +# RAYLIB_PATH adjustment for different platforms. +# If using GNU make, we can get the full path to the top of the tree. Windows? BSD? +# Required for ldconfig or other tools that do not perform path expansion. +ifeq ($(PLATFORM),PLATFORM_DESKTOP) + ifeq ($(PLATFORM_OS),LINUX) + RAYLIB_PREFIX ?= .. + RAYLIB_PATH = $(realpath $(RAYLIB_PREFIX)) + endif +endif +# Default path for raylib on Raspberry Pi, if installed in different path, update it! +# This is not currently used by src/Makefile. Not sure of its origin or usage. Refer to wiki. +# TODO: update install: target in src/Makefile for RPI, consider relation to LINUX. +ifeq ($(PLATFORM),PLATFORM_RPI) + RAYLIB_PATH ?= /home/pi/raylib +endif + ifeq ($(PLATFORM),PLATFORM_WEB) # Emscripten required variables - EMSDK_PATH = C:/emsdk - EMSCRIPTEN_VERSION = 1.38.8 - CLANG_VERSION = e1.38.8_64bit + EMSDK_PATH ?= D:/emsdk + EMSCRIPTEN_VERSION ?= 1.38.31 + CLANG_VERSION = e$(EMSCRIPTEN_VERSION)_64bit PYTHON_VERSION = 2.7.13.1_64bit\python-2.7.13.amd64 NODE_VERSION = 8.9.1_64bit export PATH = $(EMSDK_PATH);$(EMSDK_PATH)\clang\$(CLANG_VERSION);$(EMSDK_PATH)\node\$(NODE_VERSION)\bin;$(EMSDK_PATH)\python\$(PYTHON_VERSION);$(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION);C:\raylib\MinGW\bin:$$(PATH) EMSCRIPTEN = $(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION) endif -RAYLIB_RELEASE_PATH ?= $(RAYLIB_PATH)/release/libs +# Define raylib release directory for compiled library. +# RAYLIB_RELEASE_PATH points to provided binaries or your freshly built version +RAYLIB_RELEASE_PATH ?= $(RAYLIB_PATH)/src -# Define raylib release directory for compiled library -ifeq ($(PLATFORM),PLATFORM_DESKTOP) - ifeq ($(PLATFORM_OS),WINDOWS) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/win32/mingw32 - endif - ifeq ($(PLATFORM_OS),LINUX) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/linux - endif - ifeq ($(PLATFORM_OS),OSX) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/osx - endif - ifeq ($(PLATFORM_OS),BSD) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/bsd - endif -endif -ifeq ($(PLATFORM),PLATFORM_RPI) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/rpi -endif -ifeq ($(PLATFORM),PLATFORM_WEB) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/html5 -endif +# EXAMPLE_RUNTIME_PATH embeds a custom runtime location of libraylib.so or other desired libraries +# into each example binary compiled with RAYLIB_LIBTYPE=SHARED. It defaults to RAYLIB_RELEASE_PATH +# so that these examples link at runtime with your version of libraylib.so in ../release/libs/linux +# without formal installation from ../src/Makefile. It aids portability and is useful if you have +# multiple versions of raylib, have raylib installed to a non-standard location, or want to +# bundle libraylib.so with your game. Change it to your liking. +# NOTE: If, at runtime, there is a libraylib.so at both EXAMPLE_RUNTIME_PATH and RAYLIB_INSTALL_PATH, +# The library at EXAMPLE_RUNTIME_PATH, if present, will take precedence over RAYLIB_INSTALL_PATH, +# Implemented for LINUX below with CFLAGS += -Wl,-rpath,$(EXAMPLE_RUNTIME_PATH) +# To see the result, run readelf -d core/core_basic_window; looking at the RPATH or RUNPATH attribute. +# To see which libraries a built example is linking to, ldd core/core_basic_window; +# Look for libraylib.so.1 => $(RAYLIB_INSTALL_PATH)/libraylib.so.1 or similar listing. +EXAMPLE_RUNTIME_PATH ?= $(RAYLIB_RELEASE_PATH) # Define default C compiler: gcc # NOTE: define g++ compiler if using C++ @@ -140,6 +165,8 @@ ifeq ($(PLATFORM),PLATFORM_RPI) endif ifeq ($(PLATFORM),PLATFORM_WEB) # HTML5 emscripten compiler + # WARNING: To compile to HTML5, code must be redesigned + # to use emscripten.h and emscripten_set_main_loop() CC = emcc endif @@ -154,7 +181,7 @@ endif # Define compiler flags: # -O1 defines optimization level -# -g enable debugging +# -g include debug information on compilation # -s strip unnecessary data from build # -Wall turns on most, but not all, compiler warnings # -std=c99 defines C language mode (standard C from 1999 revision) @@ -163,56 +190,92 @@ endif # -D_DEFAULT_SOURCE use with -std=c99 on Linux and PLATFORM_WEB, required for timespec CFLAGS += -O1 -s -Wall -std=c99 -D_DEFAULT_SOURCE -Wno-missing-braces +ifeq ($(BUILD_MODE),DEBUG) + CFLAGS += -g +endif + # Additional flags for compiler (if desired) #CFLAGS += -Wextra -Wmissing-prototypes -Wstrict-prototypes ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),WINDOWS) - # resources file contains windows exe icon + # resource file contains windows executable icon and properties # -Wl,--subsystem,windows hides the console window - CFLAGS += $(RAYLIB_PATH)/raylib.rc.data -Wl,--subsystem,windows + CFLAGS += $(RAYLIB_PATH)/src/raylib.rc.data -Wl,--subsystem,windows endif ifeq ($(PLATFORM_OS),LINUX) - CFLAGS += -D_DEFAULT_SOURCE + ifeq ($(RAYLIB_LIBTYPE),STATIC) + CFLAGS += -D_DEFAULT_SOURCE + endif + ifeq ($(RAYLIB_LIBTYPE),SHARED) + # Explicitly enable runtime link to libraylib.so + CFLAGS += -Wl,-rpath,$(EXAMPLE_RUNTIME_PATH) + endif endif endif ifeq ($(PLATFORM),PLATFORM_RPI) CFLAGS += -std=gnu99 endif ifeq ($(PLATFORM),PLATFORM_WEB) - # -O2 # if used, also set --memory-init-file 0 - # --memory-init-file 0 # to avoid an external memory initialization code file (.mem) - # -s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing + # -Os # size optimization + # -O2 # optimization level 2, if used, also set --memory-init-file 0 + # -s USE_GLFW=3 # Use glfw3 library (context/input management) + # -s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing -> WARNING: Audio buffers could FAIL! # -s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB) # -s USE_PTHREADS=1 # multithreading support - # -s WASM=1 # support Web Assembly (https://github.com/kripken/emscripten/wiki/WebAssembly) + # -s WASM=0 # disable Web Assembly, emitted by default + # -s EMTERPRETIFY=1 # enable emscripten code interpreter (very slow) + # -s EMTERPRETIFY_ASYNC=1 # support synchronous loops by emterpreter + # -s FORCE_FILESYSTEM=1 # force filesystem to load/save files data + # -s ASSERTIONS=1 # enable runtime checks for common memory allocation errors (-O1 and above turn it off) + # --profiling # include information for code profiling + # --memory-init-file 0 # to avoid an external memory initialization code file (.mem) # --preload-file resources # specify a resources folder for data compilation - CFLAGS += -s USE_GLFW=3 -s ASSERTIONS=1 -s WASM=1 --profiling --preload-file resources - + CFLAGS += -Os -s USE_GLFW=3 + ifeq ($(BUILD_MODE), DEBUG) + CFLAGS += -s ASSERTIONS=1 --profiling + endif + # Define a custom shell .html and output extension - CFLAGS += --shell-file $(RAYLIB_PATH)\templates\web_shell\shell.html + CFLAGS += --shell-file $(RAYLIB_PATH)/src/shell.html EXT = .html endif # Define include paths for required headers # NOTE: Several external required libraries (stb and others) -INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/release/include -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external +INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external # Define additional directories containing required header files ifeq ($(PLATFORM),PLATFORM_RPI) - # RPI requried libraries + # RPI required libraries INCLUDE_PATHS += -I/opt/vc/include INCLUDE_PATHS += -I/opt/vc/include/interface/vmcs_host/linux INCLUDE_PATHS += -I/opt/vc/include/interface/vcos/pthreads endif +ifeq ($(PLATFORM),PLATFORM_DESKTOP) + ifeq ($(PLATFORM_OS),BSD) + # Consider -L$(RAYLIB_H_INSTALL_PATH) + INCLUDE_PATHS += -I/usr/local/include + endif + ifeq ($(PLATFORM_OS),LINUX) + # Reset everything. + # Precedence: immediately local, installed version, raysan5 provided libs -I$(RAYLIB_H_INSTALL_PATH) -I$(RAYLIB_PATH)/release/include + INCLUDE_PATHS = -I$(RAYLIB_H_INSTALL_PATH) -isystem. -isystem$(RAYLIB_PATH)/src -isystem$(RAYLIB_PATH)/release/include -isystem$(RAYLIB_PATH)/src/external + endif +endif -# Define library paths containing required libs -LDFLAGS = -L. -L$(RAYLIB_RELEASE_PATH) -L$(RAYLIB_PATH)/src +# Define library paths containing required libs. +LDFLAGS = -L. -L$(RAYLIB_RELEASE_PATH) -L$(RAYLIB_PATH)/src ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),BSD) - INCLUDE_PATHS += -I/usr/local/include + # Consider -L$(RAYLIB_INSTALL_PATH) LDFLAGS += -L. -Lsrc -L/usr/local/lib endif + ifeq ($(PLATFORM_OS),LINUX) + # Reset everything. + # Precedence: immediately local, installed version, raysan5 provided libs + LDFLAGS = -L. -L$(RAYLIB_INSTALL_PATH) -L$(RAYLIB_RELEASE_PATH) + endif endif ifeq ($(PLATFORM),PLATFORM_RPI) @@ -224,7 +287,10 @@ endif ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),WINDOWS) # Libraries for Windows desktop compilation - LDLIBS = -lraylib -lopengl32 -lgdi32 + # NOTE: WinMM library required to set high-res timer resolution + LDLIBS = -lraylib -lopengl32 -lgdi32 -lwinmm + # Required for physac examples + LDLIBS += -static -lpthread endif ifeq ($(PLATFORM_OS),LINUX) # Libraries for Debian GNU/Linux desktop compiling @@ -240,6 +306,10 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(USE_WAYLAND_DISPLAY),TRUE) LDLIBS += -lwayland-client -lwayland-cursor -lwayland-egl -lxkbcommon endif + # Explicit link to libc + ifeq ($(RAYLIB_LIBTYPE),SHARED) + LDLIBS += -lc + endif endif ifeq ($(PLATFORM_OS),OSX) # Libraries for OSX 10.9 desktop compiling @@ -286,6 +356,8 @@ SAMPLES = \ # typing 'make' will invoke the default target entry all: $(SAMPLES) +# Generic compilation pattern +# NOTE: Examples must be ready for Android compilation! %: %.c ifeq ($(PLATFORM),PLATFORM_ANDROID) $(MAKE) -f Makefile.Android PROJECT_NAME=$@ PROJECT_SOURCE_FILES=$< @@ -300,7 +372,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) del *.o *.exe /s endif ifeq ($(PLATFORM_OS),LINUX) - find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -f + find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -fv endif ifeq ($(PLATFORM_OS),OSX) find . -type f -perm +ugo+x -delete @@ -309,7 +381,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) endif ifeq ($(PLATFORM),PLATFORM_RPI) find . -type f -executable -delete - rm -f *.o + rm -fv *.o endif ifeq ($(PLATFORM),PLATFORM_WEB) del *.o *.html *.js diff --git a/games/Makefile.Android b/games/Makefile.Android index b6c68417f..29d437b1b 100644 --- a/games/Makefile.Android +++ b/games/Makefile.Android @@ -22,33 +22,33 @@ #************************************************************************************************** # Define required raylib variables -PLATFORM ?= PLATFORM_ANDROID -RAYLIB_PATH ?= ..\.. +PLATFORM ?= PLATFORM_ANDROID +RAYLIB_PATH ?= ..\.. # Define Android architecture (armeabi-v7a, arm64-v8a, x86, x86-64) and API version -ANDROID_ARCH ?= ARM -ANDROID_API_VERSION = 21 +ANDROID_ARCH ?= ARM +ANDROID_API_VERSION = 21 ifeq ($(ANDROID_ARCH),ARM) - ANDROID_ARCH_NAME = armeabi-v7a + ANDROID_ARCH_NAME = armeabi-v7a endif ifeq ($(ANDROID_ARCH),ARM64) - ANDROID_ARCH_NAME = arm64-v8a + ANDROID_ARCH_NAME = arm64-v8a endif # Required path variables # NOTE: JAVA_HOME must be set to JDK -JAVA_HOME ?= C:/JavaJDK -ANDROID_HOME = C:/android-sdk -ANDROID_TOOLCHAIN = C:/android_toolchain_$(ANDROID_ARCH)_API$(ANDROID_API_VERSION) -ANDROID_BUILD_TOOLS = $(ANDROID_HOME)/build-tools/28.0.1 -ANDROID_PLATFORM_TOOLS = $(ANDROID_HOME)/platform-tools +JAVA_HOME ?= C:/JavaJDK +ANDROID_HOME = C:/android-sdk +ANDROID_TOOLCHAIN = C:/android_toolchain_$(ANDROID_ARCH)_API$(ANDROID_API_VERSION) +ANDROID_BUILD_TOOLS = $(ANDROID_HOME)/build-tools/28.0.1 +ANDROID_PLATFORM_TOOLS = $(ANDROID_HOME)/platform-tools # Android project configuration variables -PROJECT_NAME ?= raylib_game -PROJECT_LIBRARY_NAME ?= main -PROJECT_BUILD_PATH ?= android.$(PROJECT_NAME) +PROJECT_NAME ?= raylib_game +PROJECT_LIBRARY_NAME ?= main +PROJECT_BUILD_PATH ?= android.$(PROJECT_NAME) PROJECT_RESOURCES_PATH ?= resources -PROJECT_SOURCE_FILES ?= raylib_game.c +PROJECT_SOURCE_FILES ?= raylib_game.c # Some source files are placed in directories, when compiling to some # output directory other than source, that directory must pre-exist. @@ -70,7 +70,9 @@ APP_KEYSTORE_PASS ?= raylib # Library type used for raylib: STATIC (.a) or SHARED (.so/.dll) RAYLIB_LIBTYPE ?= STATIC -RAYLIB_LIB_PATH = $(RAYLIB_PATH)\release\libs\android\$(ANDROID_ARCH_NAME) + +# Library path for libraylib.a/libraylib.so +RAYLIB_LIB_PATH = $(RAYLIB_PATH)\src # Shared libs must be added to APK if required # NOTE: Generated NativeLoader.java automatically load those libraries @@ -104,7 +106,7 @@ CFLAGS += -Wall -Wa,--noexecstack -Wformat -Werror=format-security -no-canonical CFLAGS += -DANDROID -DPLATFORM_ANDROID -D__ANDROID_API__=$(ANDROID_API_VERSION) # Paths containing required header files -INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/release/include -I$(RAYLIB_PATH)/src/external/android/native_app_glue +INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external/android/native_app_glue # Linker options LDFLAGS = -Wl,-soname,lib$(PROJECT_LIBRARY_NAME).so -Wl,--exclude-libs,libatomic.a diff --git a/games/arkanoid.c b/games/arkanoid.c index 2a4a2e536..f72d85b31 100644 --- a/games/arkanoid.c +++ b/games/arkanoid.c @@ -25,7 +25,6 @@ //---------------------------------------------------------------------------------- // Some Defines //---------------------------------------------------------------------------------- - #define PLAYER_MAX_LIFE 5 #define LINES_OF_BRICKS 5 #define BRICKS_PER_LINE 20 @@ -56,16 +55,16 @@ typedef struct Brick { //------------------------------------------------------------------------------------ // Global Variables Declaration //------------------------------------------------------------------------------------ -static int screenWidth = 800; -static int screenHeight = 450; +static const int screenWidth = 800; +static const int screenHeight = 450; -static bool gameOver; -static bool pause; +static bool gameOver = false; +static bool pause = false; -static Player player; -static Ball ball; -static Brick brick[LINES_OF_BRICKS][BRICKS_PER_LINE]; -static Vector2 brickSize; +static Player player = { 0 }; +static Ball ball = { 0 }; +static Brick brick[LINES_OF_BRICKS][BRICKS_PER_LINE] = { 0 }; +static Vector2 brickSize = { 0 }; //------------------------------------------------------------------------------------ // Module Functions Declaration (local) @@ -90,7 +89,6 @@ int main(void) #if defined(PLATFORM_WEB) emscripten_set_main_loop(UpdateDrawFrame, 0, 1); #else - SetTargetFPS(60); //-------------------------------------------------------------------------------------- @@ -103,7 +101,6 @@ int main(void) //---------------------------------------------------------------------------------- } #endif - // De-Initialization //-------------------------------------------------------------------------------------- UnloadGame(); // Unload loaded data (textures, sounds, models...) @@ -272,8 +269,6 @@ void UpdateGame(void) gameOver = false; } } - - } // Draw game (one frame) diff --git a/games/asteroids.c b/games/asteroids.c index 80096de66..93d5065b4 100644 --- a/games/asteroids.c +++ b/games/asteroids.c @@ -34,7 +34,6 @@ //---------------------------------------------------------------------------------- // Types and Structures Definition //---------------------------------------------------------------------------------- - typedef struct Player { Vector2 position; Vector2 speed; @@ -65,25 +64,25 @@ typedef struct Meteor { //------------------------------------------------------------------------------------ // Global Variables Declaration //------------------------------------------------------------------------------------ -static int screenWidth = 800; -static int screenHeight = 450; +static const int screenWidth = 800; +static const int screenHeight = 450; -static bool gameOver; -static bool pause; -static bool victory; +static bool gameOver = false; +static bool pause = false; +static bool victory = false; // NOTE: Defined triangle is isosceles with common angles of 70 degrees. -static float shipHeight; +static float shipHeight = 0.0f; -static Player player; -static Shoot shoot[PLAYER_MAX_SHOOTS]; -static Meteor bigMeteor[MAX_BIG_METEORS]; -static Meteor mediumMeteor[MAX_MEDIUM_METEORS]; -static Meteor smallMeteor[MAX_SMALL_METEORS]; +static Player player = { 0 }; +static Shoot shoot[PLAYER_MAX_SHOOTS] = { 0 }; +static Meteor bigMeteor[MAX_BIG_METEORS] = { 0 }; +static Meteor mediumMeteor[MAX_MEDIUM_METEORS] = { 0 }; +static Meteor smallMeteor[MAX_SMALL_METEORS] = { 0 }; -static int midMeteorsCount; -static int smallMeteorsCount; -static int destroyedMeteorsCount; +static int midMeteorsCount = 0; +static int smallMeteorsCount = 0; +static int destroyedMeteorsCount = 0; //------------------------------------------------------------------------------------ // Module Functions Declaration (local) @@ -108,7 +107,6 @@ int main(void) #if defined(PLATFORM_WEB) emscripten_set_main_loop(UpdateDrawFrame, 0, 1); #else - SetTargetFPS(60); //-------------------------------------------------------------------------------------- @@ -121,7 +119,6 @@ int main(void) //---------------------------------------------------------------------------------- } #endif - // De-Initialization //-------------------------------------------------------------------------------------- UnloadGame(); // Unload loaded data (textures, sounds, models...) diff --git a/games/asteroids_survival.c b/games/asteroids_survival.c index 8086433e4..def310d1b 100644 --- a/games/asteroids_survival.c +++ b/games/asteroids_survival.c @@ -33,7 +33,6 @@ //---------------------------------------------------------------------------------- // Types and Structures Definition //---------------------------------------------------------------------------------- - typedef struct Player { Vector2 position; Vector2 speed; @@ -54,19 +53,19 @@ typedef struct Meteor { //------------------------------------------------------------------------------------ // Global Variables Declaration //------------------------------------------------------------------------------------ -static int screenWidth = 800; -static int screenHeight = 450; +static const int screenWidth = 800; +static const int screenHeight = 450; -static int framesCounter; -static bool gameOver; -static bool pause; +static int framesCounter = 0; +static bool gameOver = false; +static bool pause = false; // NOTE: Defined triangle is isosceles with common angles of 70 degrees. -static float shipHeight; +static float shipHeight = 0.0f; -static Player player; -static Meteor mediumMeteor[MAX_MEDIUM_METEORS]; -static Meteor smallMeteor[MAX_SMALL_METEORS]; +static Player player = { 0 }; +static Meteor mediumMeteor[MAX_MEDIUM_METEORS] = { 0 }; +static Meteor smallMeteor[MAX_SMALL_METEORS] = { 0 }; //------------------------------------------------------------------------------------ // Module Functions Declaration (local) @@ -91,7 +90,6 @@ int main(void) #if defined(PLATFORM_WEB) emscripten_set_main_loop(UpdateDrawFrame, 0, 1); #else - SetTargetFPS(60); //-------------------------------------------------------------------------------------- @@ -104,7 +102,6 @@ int main(void) //---------------------------------------------------------------------------------- } #endif - // De-Initialization //-------------------------------------------------------------------------------------- UnloadGame(); // Unload loaded data (textures, sounds, models...) @@ -354,7 +351,7 @@ void DrawGame(void) else DrawCircleV(smallMeteor[i].position, smallMeteor[i].radius, Fade(LIGHTGRAY, 0.3f)); } - DrawText(FormatText("TIME: %.02f", (float)framesCounter/60), 10, 10, 20, BLACK); + DrawText(TextFormat("TIME: %.02f", (float)framesCounter/60), 10, 10, 20, BLACK); if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); } diff --git a/games/cat_vs_roomba/Makefile b/games/cat_vs_roomba/Makefile index b13046569..00041d1d8 100644 --- a/games/cat_vs_roomba/Makefile +++ b/games/cat_vs_roomba/Makefile @@ -24,28 +24,43 @@ .PHONY: all clean # Define required raylib variables -# WARNING: To compile to HTML5, code must be redesigned to use emscripten.h and emscripten_set_main_loop() -PLATFORM ?= PLATFORM_DESKTOP -RAYLIB_PATH ?= C:/GitHub/raylib -PROJECT_NAME ?= roomba +PROJECT_NAME ?= roomba +RAYLIB_VERSION ?= 2.5.0 +RAYLIB_API_VERSION ?= 2 +RAYLIB_PATH ?= C:\GitHub\raylib -# Default path for raylib on Raspberry Pi, if installed in different path, update it! -ifeq ($(PLATFORM),PLATFORM_RPI) - RAYLIB_PATH ?= /home/pi/raylib -endif +# Define default options + +# One of PLATFORM_DESKTOP, PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB +PLATFORM ?= PLATFORM_DESKTOP + +# Locations of your newly installed library and associated headers. See ../src/Makefile +# On Linux, if you have installed raylib but cannot compile the examples, check that +# the *_INSTALL_PATH values here are the same as those in src/Makefile or point to known locations. +# To enable system-wide compile-time and runtime linking to libraylib.so, run ../src/$ sudo make install RAYLIB_LIBTYPE_SHARED. +# To enable compile-time linking to a special version of libraylib.so, change these variables here. +# To enable runtime linking to a special version of libraylib.so, see EXAMPLE_RUNTIME_PATH below. +# If there is a libraylib in both EXAMPLE_RUNTIME_PATH and RAYLIB_INSTALL_PATH, at runtime, +# the library at EXAMPLE_RUNTIME_PATH, if present, will take precedence over the one at RAYLIB_INSTALL_PATH. +# RAYLIB_INSTALL_PATH should be the desired full path to libraylib. No relative paths. +DESTDIR ?= /usr/local +RAYLIB_INSTALL_PATH ?= $(DESTDIR)/lib +# RAYLIB_H_INSTALL_PATH locates the installed raylib header and associated source files. +RAYLIB_H_INSTALL_PATH ?= $(DESTDIR)/include # Library type used for raylib: STATIC (.a) or SHARED (.so/.dll) -RAYLIB_LIBTYPE ?= STATIC +RAYLIB_LIBTYPE ?= STATIC + +# Build mode for project: DEBUG or RELEASE +BUILD_MODE ?= RELEASE # Use external GLFW library instead of rglfw module -USE_EXTERNAL_GLFW ?= FALSE +# TODO: Review usage on Linux. Target version of choice. Switch on -lglfw or -lglfw3 +USE_EXTERNAL_GLFW ?= FALSE # Use Wayland display server protocol on Linux desktop # by default it uses X11 windowing system -USE_WAYLAND_DISPLAY ?= FALSE - -# NOTE: On PLATFORM_WEB OpenAL Soft backend is used by default (check raylib/src/Makefile) - +USE_WAYLAND_DISPLAY ?= FALSE # Determine PLATFORM_OS in case PLATFORM_DESKTOP selected ifeq ($(PLATFORM),PLATFORM_DESKTOP) @@ -82,40 +97,50 @@ ifeq ($(PLATFORM),PLATFORM_RPI) endif endif +# RAYLIB_PATH adjustment for different platforms. +# If using GNU make, we can get the full path to the top of the tree. Windows? BSD? +# Required for ldconfig or other tools that do not perform path expansion. +ifeq ($(PLATFORM),PLATFORM_DESKTOP) + ifeq ($(PLATFORM_OS),LINUX) + RAYLIB_PREFIX ?= .. + RAYLIB_PATH = $(realpath $(RAYLIB_PREFIX)) + endif +endif +# Default path for raylib on Raspberry Pi, if installed in different path, update it! +# This is not currently used by src/Makefile. Not sure of its origin or usage. Refer to wiki. +# TODO: update install: target in src/Makefile for RPI, consider relation to LINUX. +ifeq ($(PLATFORM),PLATFORM_RPI) + RAYLIB_PATH ?= /home/pi/raylib +endif + ifeq ($(PLATFORM),PLATFORM_WEB) # Emscripten required variables - EMSDK_PATH = C:/emsdk - EMSCRIPTEN_VERSION = 1.38.20 - CLANG_VERSION = e1.38.20_64bit + EMSDK_PATH ?= C:/emsdk + EMSCRIPTEN_VERSION ?= 1.38.31 + CLANG_VERSION = e$(EMSCRIPTEN_VERSION)_64bit PYTHON_VERSION = 2.7.13.1_64bit\python-2.7.13.amd64 NODE_VERSION = 8.9.1_64bit export PATH = $(EMSDK_PATH);$(EMSDK_PATH)\clang\$(CLANG_VERSION);$(EMSDK_PATH)\node\$(NODE_VERSION)\bin;$(EMSDK_PATH)\python\$(PYTHON_VERSION);$(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION);C:\raylib\MinGW\bin:$$(PATH) EMSCRIPTEN = $(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION) endif -RAYLIB_RELEASE_PATH ?= $(RAYLIB_PATH)/release/libs +# Define raylib release directory for compiled library. +# RAYLIB_RELEASE_PATH points to provided binaries or your freshly built version +RAYLIB_RELEASE_PATH ?= $(RAYLIB_PATH)/src -# Define raylib release directory for compiled library -ifeq ($(PLATFORM),PLATFORM_DESKTOP) - ifeq ($(PLATFORM_OS),WINDOWS) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/win32/mingw32 - endif - ifeq ($(PLATFORM_OS),LINUX) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/linux - endif - ifeq ($(PLATFORM_OS),OSX) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/osx - endif - ifeq ($(PLATFORM_OS),BSD) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/bsd - endif -endif -ifeq ($(PLATFORM),PLATFORM_RPI) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/rpi -endif -ifeq ($(PLATFORM),PLATFORM_WEB) - RAYLIB_RELEASE_PATH = . -endif +# EXAMPLE_RUNTIME_PATH embeds a custom runtime location of libraylib.so or other desired libraries +# into each example binary compiled with RAYLIB_LIBTYPE=SHARED. It defaults to RAYLIB_RELEASE_PATH +# so that these examples link at runtime with your version of libraylib.so in ../release/libs/linux +# without formal installation from ../src/Makefile. It aids portability and is useful if you have +# multiple versions of raylib, have raylib installed to a non-standard location, or want to +# bundle libraylib.so with your game. Change it to your liking. +# NOTE: If, at runtime, there is a libraylib.so at both EXAMPLE_RUNTIME_PATH and RAYLIB_INSTALL_PATH, +# The library at EXAMPLE_RUNTIME_PATH, if present, will take precedence over RAYLIB_INSTALL_PATH, +# Implemented for LINUX below with CFLAGS += -Wl,-rpath,$(EXAMPLE_RUNTIME_PATH) +# To see the result, run readelf -d core/core_basic_window; looking at the RPATH or RUNPATH attribute. +# To see which libraries a built example is linking to, ldd core/core_basic_window; +# Look for libraylib.so.1 => $(RAYLIB_INSTALL_PATH)/libraylib.so.1 or similar listing. +EXAMPLE_RUNTIME_PATH ?= $(RAYLIB_RELEASE_PATH) # Define default C compiler: gcc # NOTE: define g++ compiler if using C++ @@ -140,6 +165,8 @@ ifeq ($(PLATFORM),PLATFORM_RPI) endif ifeq ($(PLATFORM),PLATFORM_WEB) # HTML5 emscripten compiler + # WARNING: To compile to HTML5, code must be redesigned + # to use emscripten.h and emscripten_set_main_loop() CC = emcc endif @@ -154,7 +181,7 @@ endif # Define compiler flags: # -O1 defines optimization level -# -g enable debugging +# -g include debug information on compilation # -s strip unnecessary data from build # -Wall turns on most, but not all, compiler warnings # -std=c99 defines C language mode (standard C from 1999 revision) @@ -163,57 +190,92 @@ endif # -D_DEFAULT_SOURCE use with -std=c99 on Linux and PLATFORM_WEB, required for timespec CFLAGS += -O1 -s -Wall -std=c99 -D_DEFAULT_SOURCE -Wno-missing-braces +ifeq ($(BUILD_MODE),DEBUG) + CFLAGS += -g +endif + # Additional flags for compiler (if desired) #CFLAGS += -Wextra -Wmissing-prototypes -Wstrict-prototypes ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),WINDOWS) - # resources file contains windows exe icon + # resource file contains windows executable icon and properties # -Wl,--subsystem,windows hides the console window CFLAGS += $(RAYLIB_PATH)/raylib.rc.data -Wl,--subsystem,windows endif ifeq ($(PLATFORM_OS),LINUX) - CFLAGS += -D_DEFAULT_SOURCE + ifeq ($(RAYLIB_LIBTYPE),STATIC) + CFLAGS += -D_DEFAULT_SOURCE + endif + ifeq ($(RAYLIB_LIBTYPE),SHARED) + # Explicitly enable runtime link to libraylib.so + CFLAGS += -Wl,-rpath,$(EXAMPLE_RUNTIME_PATH) + endif endif endif ifeq ($(PLATFORM),PLATFORM_RPI) CFLAGS += -std=gnu99 endif ifeq ($(PLATFORM),PLATFORM_WEB) - # -O2 # if used, also set --memory-init-file 0 - # --memory-init-file 0 # to avoid an external memory initialization code file (.mem) - # -s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing + # -Os # size optimization + # -O2 # optimization level 2, if used, also set --memory-init-file 0 + # -s USE_GLFW=3 # Use glfw3 library (context/input management) + # -s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing -> WARNING: Audio buffers could FAIL! # -s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB) # -s USE_PTHREADS=1 # multithreading support - # -s WASM=1 # support Web Assembly (https://github.com/kripken/emscripten/wiki/WebAssembly) + # -s WASM=0 # disable Web Assembly, emitted by default + # -s EMTERPRETIFY=1 # enable emscripten code interpreter (very slow) + # -s EMTERPRETIFY_ASYNC=1 # support synchronous loops by emterpreter + # -s FORCE_FILESYSTEM=1 # force filesystem to load/save files data + # -s ASSERTIONS=1 # enable runtime checks for common memory allocation errors (-O1 and above turn it off) + # --profiling # include information for code profiling + # --memory-init-file 0 # to avoid an external memory initialization code file (.mem) # --preload-file resources # specify a resources folder for data compilation - # -s ASSERTIONS=1 --profiling - CFLAGS += -s USE_GLFW=3 -s WASM=1 -s TOTAL_MEMORY=16777216 --preload-file resources - + CFLAGS += -Os -s USE_GLFW=3 -s TOTAL_MEMORY=16777216 --preload-file resources + ifeq ($(BUILD_MODE), DEBUG) + CFLAGS += -s ASSERTIONS=1 --profiling + endif + # Define a custom shell .html and output extension - CFLAGS += --shell-file $(RAYLIB_PATH)\templates\web_shell\shell.html + CFLAGS += --shell-file $(RAYLIB_PATH)/src/shell.html EXT = .html endif # Define include paths for required headers # NOTE: Several external required libraries (stb and others) -INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/release/include -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external +INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external # Define additional directories containing required header files ifeq ($(PLATFORM),PLATFORM_RPI) - # RPI requried libraries + # RPI required libraries INCLUDE_PATHS += -I/opt/vc/include INCLUDE_PATHS += -I/opt/vc/include/interface/vmcs_host/linux INCLUDE_PATHS += -I/opt/vc/include/interface/vcos/pthreads endif +ifeq ($(PLATFORM),PLATFORM_DESKTOP) + ifeq ($(PLATFORM_OS),BSD) + # Consider -L$(RAYLIB_H_INSTALL_PATH) + INCLUDE_PATHS += -I/usr/local/include + endif + ifeq ($(PLATFORM_OS),LINUX) + # Reset everything. + # Precedence: immediately local, installed version, raysan5 provided libs -I$(RAYLIB_H_INSTALL_PATH) -I$(RAYLIB_PATH)/release/include + INCLUDE_PATHS = -I$(RAYLIB_H_INSTALL_PATH) -isystem. -isystem$(RAYLIB_PATH)/src -isystem$(RAYLIB_PATH)/release/include -isystem$(RAYLIB_PATH)/src/external + endif +endif -# Define library paths containing required libs -LDFLAGS = -L. -L$(RAYLIB_RELEASE_PATH) -L$(RAYLIB_PATH)/src +# Define library paths containing required libs. +LDFLAGS = -L. -L$(RAYLIB_RELEASE_PATH) -L$(RAYLIB_PATH)/src ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),BSD) - INCLUDE_PATHS += -I/usr/local/include + # Consider -L$(RAYLIB_INSTALL_PATH) LDFLAGS += -L. -Lsrc -L/usr/local/lib endif + ifeq ($(PLATFORM_OS),LINUX) + # Reset everything. + # Precedence: immediately local, installed version, raysan5 provided libs + LDFLAGS = -L. -L$(RAYLIB_INSTALL_PATH) -L$(RAYLIB_RELEASE_PATH) + endif endif ifeq ($(PLATFORM),PLATFORM_RPI) @@ -225,8 +287,8 @@ endif ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),WINDOWS) # Libraries for Windows desktop compilation - LDLIBS = -lraylib -lopengl32 -lgdi32 - + # NOTE: WinMM library required to set high-res timer resolution + LDLIBS = -lraylib -lopengl32 -lgdi32 -lwinmm # Required for physac examples #LDLIBS += -static -lpthread endif @@ -244,6 +306,10 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(USE_WAYLAND_DISPLAY),TRUE) LDLIBS += -lwayland-client -lwayland-cursor -lwayland-egl -lxkbcommon endif + # Explicit link to libc + ifeq ($(RAYLIB_LIBTYPE),SHARED) + LDLIBS += -lc + endif endif ifeq ($(PLATFORM_OS),OSX) # Libraries for OSX 10.9 desktop compiling @@ -274,11 +340,12 @@ ifeq ($(PLATFORM),PLATFORM_WEB) endif # Define all source files required -PROJECT_SOURCE_FILES ?= roomba.c \ - screens/screen_logo.c \ - screens/screen_title.c \ - screens/screen_gameplay.c \ - screens/screen_ending.c +PROJECT_SOURCE_FILES ?= \ + roomba.c \ + screens/screen_logo.c \ + screens/screen_title.c \ + screens/screen_gameplay.c \ + screens/screen_ending.c # Define all object files from source files OBJS = $(patsubst %.c, %.o, $(PROJECT_SOURCE_FILES)) @@ -313,7 +380,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) del *.o *.exe /s endif ifeq ($(PLATFORM_OS),LINUX) - find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -f + find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -fv endif ifeq ($(PLATFORM_OS),OSX) find . -type f -perm +ugo+x -delete @@ -322,7 +389,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) endif ifeq ($(PLATFORM),PLATFORM_RPI) find . -type f -executable -delete - rm -f *.o + rm -fv *.o endif ifeq ($(PLATFORM),PLATFORM_WEB) del *.o *.html *.js diff --git a/games/cat_vs_roomba/Makefile.Android b/games/cat_vs_roomba/Makefile.Android index b6c68417f..29d437b1b 100644 --- a/games/cat_vs_roomba/Makefile.Android +++ b/games/cat_vs_roomba/Makefile.Android @@ -22,33 +22,33 @@ #************************************************************************************************** # Define required raylib variables -PLATFORM ?= PLATFORM_ANDROID -RAYLIB_PATH ?= ..\.. +PLATFORM ?= PLATFORM_ANDROID +RAYLIB_PATH ?= ..\.. # Define Android architecture (armeabi-v7a, arm64-v8a, x86, x86-64) and API version -ANDROID_ARCH ?= ARM -ANDROID_API_VERSION = 21 +ANDROID_ARCH ?= ARM +ANDROID_API_VERSION = 21 ifeq ($(ANDROID_ARCH),ARM) - ANDROID_ARCH_NAME = armeabi-v7a + ANDROID_ARCH_NAME = armeabi-v7a endif ifeq ($(ANDROID_ARCH),ARM64) - ANDROID_ARCH_NAME = arm64-v8a + ANDROID_ARCH_NAME = arm64-v8a endif # Required path variables # NOTE: JAVA_HOME must be set to JDK -JAVA_HOME ?= C:/JavaJDK -ANDROID_HOME = C:/android-sdk -ANDROID_TOOLCHAIN = C:/android_toolchain_$(ANDROID_ARCH)_API$(ANDROID_API_VERSION) -ANDROID_BUILD_TOOLS = $(ANDROID_HOME)/build-tools/28.0.1 -ANDROID_PLATFORM_TOOLS = $(ANDROID_HOME)/platform-tools +JAVA_HOME ?= C:/JavaJDK +ANDROID_HOME = C:/android-sdk +ANDROID_TOOLCHAIN = C:/android_toolchain_$(ANDROID_ARCH)_API$(ANDROID_API_VERSION) +ANDROID_BUILD_TOOLS = $(ANDROID_HOME)/build-tools/28.0.1 +ANDROID_PLATFORM_TOOLS = $(ANDROID_HOME)/platform-tools # Android project configuration variables -PROJECT_NAME ?= raylib_game -PROJECT_LIBRARY_NAME ?= main -PROJECT_BUILD_PATH ?= android.$(PROJECT_NAME) +PROJECT_NAME ?= raylib_game +PROJECT_LIBRARY_NAME ?= main +PROJECT_BUILD_PATH ?= android.$(PROJECT_NAME) PROJECT_RESOURCES_PATH ?= resources -PROJECT_SOURCE_FILES ?= raylib_game.c +PROJECT_SOURCE_FILES ?= raylib_game.c # Some source files are placed in directories, when compiling to some # output directory other than source, that directory must pre-exist. @@ -70,7 +70,9 @@ APP_KEYSTORE_PASS ?= raylib # Library type used for raylib: STATIC (.a) or SHARED (.so/.dll) RAYLIB_LIBTYPE ?= STATIC -RAYLIB_LIB_PATH = $(RAYLIB_PATH)\release\libs\android\$(ANDROID_ARCH_NAME) + +# Library path for libraylib.a/libraylib.so +RAYLIB_LIB_PATH = $(RAYLIB_PATH)\src # Shared libs must be added to APK if required # NOTE: Generated NativeLoader.java automatically load those libraries @@ -104,7 +106,7 @@ CFLAGS += -Wall -Wa,--noexecstack -Wformat -Werror=format-security -no-canonical CFLAGS += -DANDROID -DPLATFORM_ANDROID -D__ANDROID_API__=$(ANDROID_API_VERSION) # Paths containing required header files -INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/release/include -I$(RAYLIB_PATH)/src/external/android/native_app_glue +INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external/android/native_app_glue # Linker options LDFLAGS = -Wl,-soname,lib$(PROJECT_LIBRARY_NAME).so -Wl,--exclude-libs,libatomic.a diff --git a/games/cat_vs_roomba/roomba.c b/games/cat_vs_roomba/roomba.c index eeee7a719..4a27cbcce 100644 --- a/games/cat_vs_roomba/roomba.c +++ b/games/cat_vs_roomba/roomba.c @@ -1,14 +1,14 @@ /******************************************************************************************* * -* raylib - Advance Game template +* CAT VS ROOMBA [GLOBAL GAME JAM 2019] * -* -* +* Ah! Home, sweet home! Time for some automatic cleaning... +* if the worst enemy of Roomba allows it... be careful with Cat! * -* This game has been created using raylib (www.raylib.com) +* This game has been created using raylib 2.0 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * -* Copyright (c) 2014-2019 Ramon Santamaria (@raysan5) +* Copyright (c) 2019 Ramon Santamaria (@raysan5) * ********************************************************************************************/ @@ -57,7 +57,7 @@ int main(void) { // Initialization (Note windowTitle is unused on Android) //--------------------------------------------------------- - InitWindow(screenWidth, screenHeight, "raylib template - advance game"); + InitWindow(screenWidth, screenHeight, "CAT VS ROOMBA [GGJ19]"); // Global data loading (assets that must be available in all screens, i.e. fonts) InitAudioDevice(); diff --git a/games/cat_vs_roomba/screens/screen_logo.c b/games/cat_vs_roomba/screens/screen_logo.c index a697013ef..1d8fa9783 100644 --- a/games/cat_vs_roomba/screens/screen_logo.c +++ b/games/cat_vs_roomba/screens/screen_logo.c @@ -33,22 +33,22 @@ //---------------------------------------------------------------------------------- // Logo screen global variables -static int framesCounter; -static int finishScreen; +static int framesCounter = 0; +static int finishScreen = 0; -static int logoPositionX; -static int logoPositionY; +static int logoPositionX = 0; +static int logoPositionY = 0; -static int lettersCount; +static int lettersCount = 0; -static int topSideRecWidth; -static int leftSideRecHeight; +static int topSideRecWidth = 0; +static int leftSideRecHeight = 0; -static int bottomSideRecWidth; -static int rightSideRecHeight; +static int bottomSideRecWidth = 0; +static int rightSideRecHeight = 0; -static char raylib[8]; // raylib text array, max 8 letters -static int state; // Tracking animation states (State Machine) +static char raylib[8] = { 0 }; // raylib text array, max 8 letters +static int state = 0; // Tracking animation states (State Machine) static float alpha = 1.0f; // Useful for fading //---------------------------------------------------------------------------------- diff --git a/games/drturtle/Makefile b/games/drturtle/Makefile index 4cd5033ea..5368393f9 100644 --- a/games/drturtle/Makefile +++ b/games/drturtle/Makefile @@ -24,28 +24,43 @@ .PHONY: all clean # Define required raylib variables -# WARNING: To compile to HTML5, code must be redesigned to use emscripten.h and emscripten_set_main_loop() -PLATFORM ?= PLATFORM_DESKTOP -RAYLIB_PATH ?= ..\.. -PROJECT_NAME ?= drturtle +PROJECT_NAME ?= drturtle +RAYLIB_VERSION ?= 2.5.0 +RAYLIB_API_VERSION ?= 2 +RAYLIB_PATH ?= C:\GitHub\raylib -# Default path for raylib on Raspberry Pi, if installed in different path, update it! -ifeq ($(PLATFORM),PLATFORM_RPI) - RAYLIB_PATH ?= /home/pi/raylib -endif +# Define default options + +# One of PLATFORM_DESKTOP, PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB +PLATFORM ?= PLATFORM_DESKTOP + +# Locations of your newly installed library and associated headers. See ../src/Makefile +# On Linux, if you have installed raylib but cannot compile the examples, check that +# the *_INSTALL_PATH values here are the same as those in src/Makefile or point to known locations. +# To enable system-wide compile-time and runtime linking to libraylib.so, run ../src/$ sudo make install RAYLIB_LIBTYPE_SHARED. +# To enable compile-time linking to a special version of libraylib.so, change these variables here. +# To enable runtime linking to a special version of libraylib.so, see EXAMPLE_RUNTIME_PATH below. +# If there is a libraylib in both EXAMPLE_RUNTIME_PATH and RAYLIB_INSTALL_PATH, at runtime, +# the library at EXAMPLE_RUNTIME_PATH, if present, will take precedence over the one at RAYLIB_INSTALL_PATH. +# RAYLIB_INSTALL_PATH should be the desired full path to libraylib. No relative paths. +DESTDIR ?= /usr/local +RAYLIB_INSTALL_PATH ?= $(DESTDIR)/lib +# RAYLIB_H_INSTALL_PATH locates the installed raylib header and associated source files. +RAYLIB_H_INSTALL_PATH ?= $(DESTDIR)/include # Library type used for raylib: STATIC (.a) or SHARED (.so/.dll) -RAYLIB_LIBTYPE ?= STATIC +RAYLIB_LIBTYPE ?= STATIC + +# Build mode for project: DEBUG or RELEASE +BUILD_MODE ?= RELEASE # Use external GLFW library instead of rglfw module -USE_EXTERNAL_GLFW ?= FALSE +# TODO: Review usage on Linux. Target version of choice. Switch on -lglfw or -lglfw3 +USE_EXTERNAL_GLFW ?= FALSE # Use Wayland display server protocol on Linux desktop # by default it uses X11 windowing system -USE_WAYLAND_DISPLAY ?= FALSE - -# NOTE: On PLATFORM_WEB OpenAL Soft backend is used by default (check raylib/src/Makefile) - +USE_WAYLAND_DISPLAY ?= FALSE # Determine PLATFORM_OS in case PLATFORM_DESKTOP selected ifeq ($(PLATFORM),PLATFORM_DESKTOP) @@ -82,40 +97,50 @@ ifeq ($(PLATFORM),PLATFORM_RPI) endif endif +# RAYLIB_PATH adjustment for different platforms. +# If using GNU make, we can get the full path to the top of the tree. Windows? BSD? +# Required for ldconfig or other tools that do not perform path expansion. +ifeq ($(PLATFORM),PLATFORM_DESKTOP) + ifeq ($(PLATFORM_OS),LINUX) + RAYLIB_PREFIX ?= .. + RAYLIB_PATH = $(realpath $(RAYLIB_PREFIX)) + endif +endif +# Default path for raylib on Raspberry Pi, if installed in different path, update it! +# This is not currently used by src/Makefile. Not sure of its origin or usage. Refer to wiki. +# TODO: update install: target in src/Makefile for RPI, consider relation to LINUX. +ifeq ($(PLATFORM),PLATFORM_RPI) + RAYLIB_PATH ?= /home/pi/raylib +endif + ifeq ($(PLATFORM),PLATFORM_WEB) # Emscripten required variables - EMSDK_PATH = C:/emsdk - EMSCRIPTEN_VERSION = 1.37.28 - CLANG_VERSION=e1.37.28_64bit - PYTHON_VERSION=2.7.5.3_64bit - NODE_VERSION=4.1.1_64bit - export PATH=$(EMSDK_PATH);$(EMSDK_PATH)\clang\$(CLANG_VERSION);$(EMSDK_PATH)\node\$(NODE_VERSION)\bin;$(EMSDK_PATH)\python\$(PYTHON_VERSION);$(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION);C:\raylib\MinGW\bin:$$(PATH) - EMSCRIPTEN=$(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION) + EMSDK_PATH ?= C:/emsdk + EMSCRIPTEN_VERSION ?= 1.38.32 + CLANG_VERSION = e$(EMSCRIPTEN_VERSION)_64bit + PYTHON_VERSION = 2.7.13.1_64bit\python-2.7.13.amd64 + NODE_VERSION = 8.9.1_64bit + export PATH = $(EMSDK_PATH);$(EMSDK_PATH)\clang\$(CLANG_VERSION);$(EMSDK_PATH)\node\$(NODE_VERSION)\bin;$(EMSDK_PATH)\python\$(PYTHON_VERSION);$(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION);C:\raylib\MinGW\bin:$$(PATH) + EMSCRIPTEN = $(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION) endif -RAYLIB_RELEASE_PATH ?= $(RAYLIB_PATH)/release/libs +# Define raylib release directory for compiled library. +# RAYLIB_RELEASE_PATH points to provided binaries or your freshly built version +RAYLIB_RELEASE_PATH ?= $(RAYLIB_PATH)/src -# Define raylib release directory for compiled library -ifeq ($(PLATFORM),PLATFORM_DESKTOP) - ifeq ($(PLATFORM_OS),WINDOWS) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/win32/mingw32 - endif - ifeq ($(PLATFORM_OS),LINUX) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/linux - endif - ifeq ($(PLATFORM_OS),OSX) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/osx - endif - ifeq ($(PLATFORM_OS),BSD) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/bsd - endif -endif -ifeq ($(PLATFORM),PLATFORM_RPI) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/rpi -endif -ifeq ($(PLATFORM),PLATFORM_WEB) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/html5 -endif +# EXAMPLE_RUNTIME_PATH embeds a custom runtime location of libraylib.so or other desired libraries +# into each example binary compiled with RAYLIB_LIBTYPE=SHARED. It defaults to RAYLIB_RELEASE_PATH +# so that these examples link at runtime with your version of libraylib.so in ../release/libs/linux +# without formal installation from ../src/Makefile. It aids portability and is useful if you have +# multiple versions of raylib, have raylib installed to a non-standard location, or want to +# bundle libraylib.so with your game. Change it to your liking. +# NOTE: If, at runtime, there is a libraylib.so at both EXAMPLE_RUNTIME_PATH and RAYLIB_INSTALL_PATH, +# The library at EXAMPLE_RUNTIME_PATH, if present, will take precedence over RAYLIB_INSTALL_PATH, +# Implemented for LINUX below with CFLAGS += -Wl,-rpath,$(EXAMPLE_RUNTIME_PATH) +# To see the result, run readelf -d core/core_basic_window; looking at the RPATH or RUNPATH attribute. +# To see which libraries a built example is linking to, ldd core/core_basic_window; +# Look for libraylib.so.1 => $(RAYLIB_INSTALL_PATH)/libraylib.so.1 or similar listing. +EXAMPLE_RUNTIME_PATH ?= $(RAYLIB_RELEASE_PATH) # Define default C compiler: gcc # NOTE: define g++ compiler if using C++ @@ -140,6 +165,8 @@ ifeq ($(PLATFORM),PLATFORM_RPI) endif ifeq ($(PLATFORM),PLATFORM_WEB) # HTML5 emscripten compiler + # WARNING: To compile to HTML5, code must be redesigned + # to use emscripten.h and emscripten_set_main_loop() CC = emcc endif @@ -154,7 +181,7 @@ endif # Define compiler flags: # -O1 defines optimization level -# -g enable debugging +# -g include debug information on compilation # -s strip unnecessary data from build # -Wall turns on most, but not all, compiler warnings # -std=c99 defines C language mode (standard C from 1999 revision) @@ -163,56 +190,92 @@ endif # -D_DEFAULT_SOURCE use with -std=c99 on Linux and PLATFORM_WEB, required for timespec CFLAGS += -O1 -s -Wall -std=c99 -D_DEFAULT_SOURCE -Wno-missing-braces +ifeq ($(BUILD_MODE),DEBUG) + CFLAGS += -g +endif + # Additional flags for compiler (if desired) #CFLAGS += -Wextra -Wmissing-prototypes -Wstrict-prototypes ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),WINDOWS) - # resources file contains windows exe icon + # resource file contains windows executable icon and properties # -Wl,--subsystem,windows hides the console window CFLAGS += $(RAYLIB_PATH)/raylib.rc.data -Wl,--subsystem,windows endif ifeq ($(PLATFORM_OS),LINUX) - CFLAGS += -D_DEFAULT_SOURCE + ifeq ($(RAYLIB_LIBTYPE),STATIC) + CFLAGS += -D_DEFAULT_SOURCE + endif + ifeq ($(RAYLIB_LIBTYPE),SHARED) + # Explicitly enable runtime link to libraylib.so + CFLAGS += -Wl,-rpath,$(EXAMPLE_RUNTIME_PATH) + endif endif endif ifeq ($(PLATFORM),PLATFORM_RPI) CFLAGS += -std=gnu99 endif ifeq ($(PLATFORM),PLATFORM_WEB) - # -O2 # if used, also set --memory-init-file 0 - # --memory-init-file 0 # to avoid an external memory initialization code file (.mem) - # -s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing + # -Os # size optimization + # -O2 # optimization level 2, if used, also set --memory-init-file 0 + # -s USE_GLFW=3 # Use glfw3 library (context/input management) + # -s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing -> WARNING: Audio buffers could FAIL! # -s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB) # -s USE_PTHREADS=1 # multithreading support - # -s WASM=1 # support Web Assembly (https://github.com/kripken/emscripten/wiki/WebAssembly) + # -s WASM=0 # disable Web Assembly, emitted by default + # -s EMTERPRETIFY=1 # enable emscripten code interpreter (very slow) + # -s EMTERPRETIFY_ASYNC=1 # support synchronous loops by emterpreter + # -s FORCE_FILESYSTEM=1 # force filesystem to load/save files data + # -s ASSERTIONS=1 # enable runtime checks for common memory allocation errors (-O1 and above turn it off) + # --profiling # include information for code profiling + # --memory-init-file 0 # to avoid an external memory initialization code file (.mem) # --preload-file resources # specify a resources folder for data compilation - CFLAGS += -s USE_GLFW=3 -s ASSERTIONS=1 -s WASM=1 --profiling --preload-file resources - + CFLAGS += -Os -s USE_GLFW=3 -s TOTAL_MEMORY=67108864 --preload-file resources + ifeq ($(BUILD_MODE), DEBUG) + CFLAGS += -s ASSERTIONS=1 --profiling + endif + # Define a custom shell .html and output extension - CFLAGS += --shell-file $(RAYLIB_PATH)\templates\web_shell\shell.html + CFLAGS += --shell-file $(RAYLIB_PATH)/src/shell.html EXT = .html endif # Define include paths for required headers # NOTE: Several external required libraries (stb and others) -INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/release/include -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external +INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external # Define additional directories containing required header files ifeq ($(PLATFORM),PLATFORM_RPI) - # RPI requried libraries + # RPI required libraries INCLUDE_PATHS += -I/opt/vc/include INCLUDE_PATHS += -I/opt/vc/include/interface/vmcs_host/linux INCLUDE_PATHS += -I/opt/vc/include/interface/vcos/pthreads endif +ifeq ($(PLATFORM),PLATFORM_DESKTOP) + ifeq ($(PLATFORM_OS),BSD) + # Consider -L$(RAYLIB_H_INSTALL_PATH) + INCLUDE_PATHS += -I/usr/local/include + endif + ifeq ($(PLATFORM_OS),LINUX) + # Reset everything. + # Precedence: immediately local, installed version, raysan5 provided libs -I$(RAYLIB_H_INSTALL_PATH) -I$(RAYLIB_PATH)/release/include + INCLUDE_PATHS = -I$(RAYLIB_H_INSTALL_PATH) -isystem. -isystem$(RAYLIB_PATH)/src -isystem$(RAYLIB_PATH)/release/include -isystem$(RAYLIB_PATH)/src/external + endif +endif -# Define library paths containing required libs -LDFLAGS = -L. -L$(RAYLIB_RELEASE_PATH) -L$(RAYLIB_PATH)/src +# Define library paths containing required libs. +LDFLAGS = -L. -L$(RAYLIB_RELEASE_PATH) -L$(RAYLIB_PATH)/src ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),BSD) - INCLUDE_PATHS += -I/usr/local/include + # Consider -L$(RAYLIB_INSTALL_PATH) LDFLAGS += -L. -Lsrc -L/usr/local/lib endif + ifeq ($(PLATFORM_OS),LINUX) + # Reset everything. + # Precedence: immediately local, installed version, raysan5 provided libs + LDFLAGS = -L. -L$(RAYLIB_INSTALL_PATH) -L$(RAYLIB_RELEASE_PATH) + endif endif ifeq ($(PLATFORM),PLATFORM_RPI) @@ -224,7 +287,10 @@ endif ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),WINDOWS) # Libraries for Windows desktop compilation - LDLIBS = -lraylib -lopengl32 -lgdi32 + # NOTE: WinMM library required to set high-res timer resolution + LDLIBS = -lraylib -lopengl32 -lgdi32 -lwinmm + # Required for physac examples + #LDLIBS += -static -lpthread endif ifeq ($(PLATFORM_OS),LINUX) # Libraries for Debian GNU/Linux desktop compiling @@ -240,6 +306,10 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(USE_WAYLAND_DISPLAY),TRUE) LDLIBS += -lwayland-client -lwayland-cursor -lwayland-egl -lxkbcommon endif + # Explicit link to libc + ifeq ($(RAYLIB_LIBTYPE),SHARED) + LDLIBS += -lc + endif endif ifeq ($(PLATFORM_OS),OSX) # Libraries for OSX 10.9 desktop compiling @@ -279,7 +349,7 @@ all: $(SCREENS) ifeq ($(PLATFORM),PLATFORM_ANDROID) $(MAKE) -f Makefile.Android PROJECT_NAME=$@ PROJECT_SOURCE_FILES=$< else - $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) + $(CC) -o $(PROJECT_NAME)$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) endif # Clean everything @@ -289,7 +359,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) del *.o *.exe /s endif ifeq ($(PLATFORM_OS),LINUX) - find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -f + find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -fv endif ifeq ($(PLATFORM_OS),OSX) find . -type f -perm +ugo+x -delete @@ -298,7 +368,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) endif ifeq ($(PLATFORM),PLATFORM_RPI) find . -type f -executable -delete - rm -f *.o + rm -fv *.o endif ifeq ($(PLATFORM),PLATFORM_WEB) del *.o *.html *.js diff --git a/games/floppy.c b/games/floppy.c index 2ca91a141..7455a9c86 100644 --- a/games/floppy.c +++ b/games/floppy.c @@ -42,19 +42,19 @@ typedef struct Tubes { //------------------------------------------------------------------------------------ // Global Variables Declaration //------------------------------------------------------------------------------------ -static int screenWidth = 800; -static int screenHeight = 450; +static const int screenWidth = 800; +static const int screenHeight = 450; -static bool gameOver; -static bool pause; -static int score; +static bool gameOver = false; +static bool pause = false; +static int score = 0; static int hiScore = 0; -static Floppy floppy; -static Tubes tubes[MAX_TUBES*2]; -static Vector2 tubesPos[MAX_TUBES]; -static int tubesSpeedX; -static bool superfx; +static Floppy floppy = { 0 }; +static Tubes tubes[MAX_TUBES*2] = { 0 }; +static Vector2 tubesPos[MAX_TUBES] = { 0 }; +static int tubesSpeedX = 0; +static bool superfx = false; //------------------------------------------------------------------------------------ // Module Functions Declaration (local) @@ -79,7 +79,6 @@ int main(void) #if defined(PLATFORM_WEB) emscripten_set_main_loop(UpdateDrawFrame, 0, 1); #else - SetTargetFPS(60); //-------------------------------------------------------------------------------------- @@ -92,7 +91,6 @@ int main(void) //---------------------------------------------------------------------------------- } #endif - // De-Initialization //-------------------------------------------------------------------------------------- UnloadGame(); // Unload loaded data (textures, sounds, models...) @@ -216,8 +214,8 @@ void DrawGame(void) superfx = false; } - DrawText(FormatText("%04i", score), 20, 20, 40, GRAY); - DrawText(FormatText("HI-SCORE: %04i", hiScore), 20, 70, 20, LIGHTGRAY); + DrawText(TextFormat("%04i", score), 20, 20, 40, GRAY); + DrawText(TextFormat("HI-SCORE: %04i", hiScore), 20, 70, 20, LIGHTGRAY); if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); } diff --git a/games/gold_fever.c b/games/gold_fever.c index c5f36efa5..30bc9c9e7 100644 --- a/games/gold_fever.c +++ b/games/gold_fever.c @@ -31,7 +31,7 @@ typedef struct Enemy { Vector2 speed; int radius; int radiusBounds; - bool moveRight; // RAY: o__O + bool moveRight; } Enemy; typedef struct Points { @@ -51,19 +51,19 @@ typedef struct Home { //------------------------------------------------------------------------------------ // Global Variables Declaration //------------------------------------------------------------------------------------ -static int screenWidth = 800; -static int screenHeight = 450; +static const int screenWidth = 800; +static const int screenHeight = 450; -static bool gameOver; -static bool pause; -static int score; +static bool gameOver = false; +static bool pause = false; +static int score = 0; static int hiScore = 0; -static Player player; -static Enemy enemy; -static Points points; -static Home home; -static bool follow; +static Player player = { 0 }; +static Enemy enemy = { 0 }; +static Points points = { 0 }; +static Home home = { 0 }; +static bool follow = false; //------------------------------------------------------------------------------------ // Module Functions Declaration (local) @@ -88,7 +88,6 @@ int main(void) #if defined(PLATFORM_WEB) emscripten_set_main_loop(UpdateDrawFrame, 0, 1); #else - SetTargetFPS(60); //-------------------------------------------------------------------------------------- @@ -101,7 +100,6 @@ int main(void) //---------------------------------------------------------------------------------- } #endif - // De-Initialization //-------------------------------------------------------------------------------------- UnloadGame(); // Unload loaded data (textures, sounds, models...) @@ -155,19 +153,19 @@ void UpdateGame(void) if (!pause) { - //Control player + // Control player if (IsKeyDown(KEY_RIGHT)) player.position.x += player.speed.x; if (IsKeyDown(KEY_LEFT)) player.position.x -= player.speed.x; if (IsKeyDown(KEY_UP)) player.position.y -= player.speed.y; if (IsKeyDown(KEY_DOWN)) player.position.y += player.speed.y; - //wall behaviour player + // Wall behaviour player if (player.position.x - player.radius <= 0) player.position.x = player.radius; if (player.position.x + player.radius >= screenWidth) player.position.x = screenWidth - player.radius; if (player.position.y - player.radius <= 0) player.position.y = player.radius; if (player.position.y + player.radius >= screenHeight) player.position.y = screenHeight - player.radius; - //IA Enemy + // IA Enemy if ( (follow || CheckCollisionCircles(player.position, player.radius, enemy.position, enemy.radiusBounds)) && !home.save) { if (player.position.x > enemy.position.x) enemy.position.x += enemy.speed.x; @@ -182,7 +180,7 @@ void UpdateGame(void) else enemy.position.x -= enemy.speed.x; } - //wall behaviour enemy + // Wall behaviour enemy if (enemy.position.x - enemy.radius <= 0) enemy.moveRight = true; if (enemy.position.x + enemy.radius >= screenWidth) enemy.moveRight = false; @@ -191,7 +189,7 @@ void UpdateGame(void) if (enemy.position.y - enemy.radius <= 0) enemy.position.y = enemy.radius; if (enemy.position.y + enemy.radius >= screenHeight) enemy.position.y = screenHeight - enemy.radius; - //Collisions + // Collisions if (CheckCollisionCircles(player.position, player.radius, points.position, points.radius) && points.active) { follow = true; @@ -257,8 +255,8 @@ void DrawGame(void) DrawCircleV(player.position, player.radius, GRAY); if (points.active) DrawCircleV(points.position, points.radius, GOLD); - DrawText(FormatText("SCORE: %04i", score), 20, 15, 20, GRAY); - DrawText(FormatText("HI-SCORE: %04i", hiScore), 300, 15, 20, GRAY); + DrawText(TextFormat("SCORE: %04i", score), 20, 15, 20, GRAY); + DrawText(TextFormat("HI-SCORE: %04i", hiScore), 300, 15, 20, GRAY); if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); } diff --git a/games/gorilas.c b/games/gorilas.c index 9ef71b552..7fd032dcc 100644 --- a/games/gorilas.c +++ b/games/gorilas.c @@ -84,16 +84,16 @@ typedef struct Ball { //------------------------------------------------------------------------------------ // Global Variables Declaration //------------------------------------------------------------------------------------ -static int screenWidth = 800; -static int screenHeight = 450; +static const int screenWidth = 800; +static const int screenHeight = 450; static bool gameOver = false; static bool pause = false; -static Player player[MAX_PLAYERS]; -static Building building[MAX_BUILDINGS]; -static Explosion explosion[MAX_EXPLOSIONS]; -static Ball ball; +static Player player[MAX_PLAYERS] = { 0 }; +static Building building[MAX_BUILDINGS] = { 0 }; +static Explosion explosion[MAX_EXPLOSIONS] = { 0 }; +static Ball ball = { 0 }; static int playerTurn = 0; static bool ballOnAir = false; @@ -272,21 +272,21 @@ void DrawGame(void) /* if (player[playerTurn].isLeftTeam) { - DrawText(FormatText("Previous Point %i, %i", (int)player[playerTurn].previousPoint.x, (int)player[playerTurn].previousPoint.y), 20, 20, 20, DARKBLUE); - DrawText(FormatText("Previous Angle %i", player[playerTurn].previousAngle), 20, 50, 20, DARKBLUE); - DrawText(FormatText("Previous Power %i", player[playerTurn].previousPower), 20, 80, 20, DARKBLUE); - DrawText(FormatText("Aiming Point %i, %i", (int)player[playerTurn].aimingPoint.x, (int)player[playerTurn].aimingPoint.y), 20, 110, 20, DARKBLUE); - DrawText(FormatText("Aiming Angle %i", player[playerTurn].aimingAngle), 20, 140, 20, DARKBLUE); - DrawText(FormatText("Aiming Power %i", player[playerTurn].aimingPower), 20, 170, 20, DARKBLUE); + DrawText(TextFormat("Previous Point %i, %i", (int)player[playerTurn].previousPoint.x, (int)player[playerTurn].previousPoint.y), 20, 20, 20, DARKBLUE); + DrawText(TextFormat("Previous Angle %i", player[playerTurn].previousAngle), 20, 50, 20, DARKBLUE); + DrawText(TextFormat("Previous Power %i", player[playerTurn].previousPower), 20, 80, 20, DARKBLUE); + DrawText(TextFormat("Aiming Point %i, %i", (int)player[playerTurn].aimingPoint.x, (int)player[playerTurn].aimingPoint.y), 20, 110, 20, DARKBLUE); + DrawText(TextFormat("Aiming Angle %i", player[playerTurn].aimingAngle), 20, 140, 20, DARKBLUE); + DrawText(TextFormat("Aiming Power %i", player[playerTurn].aimingPower), 20, 170, 20, DARKBLUE); } else { - DrawText(FormatText("Previous Point %i, %i", (int)player[playerTurn].previousPoint.x, (int)player[playerTurn].previousPoint.y), screenWidth*3/4, 20, 20, DARKBLUE); - DrawText(FormatText("Previous Angle %i", player[playerTurn].previousAngle), screenWidth*3/4, 50, 20, DARKBLUE); - DrawText(FormatText("Previous Power %i", player[playerTurn].previousPower), screenWidth*3/4, 80, 20, DARKBLUE); - DrawText(FormatText("Aiming Point %i, %i", (int)player[playerTurn].aimingPoint.x, (int)player[playerTurn].aimingPoint.y), screenWidth*3/4, 110, 20, DARKBLUE); - DrawText(FormatText("Aiming Angle %i", player[playerTurn].aimingAngle), screenWidth*3/4, 140, 20, DARKBLUE); - DrawText(FormatText("Aiming Power %i", player[playerTurn].aimingPower), screenWidth*3/4, 170, 20, DARKBLUE); + DrawText(TextFormat("Previous Point %i, %i", (int)player[playerTurn].previousPoint.x, (int)player[playerTurn].previousPoint.y), screenWidth*3/4, 20, 20, DARKBLUE); + DrawText(TextFormat("Previous Angle %i", player[playerTurn].previousAngle), screenWidth*3/4, 50, 20, DARKBLUE); + DrawText(TextFormat("Previous Power %i", player[playerTurn].previousPower), screenWidth*3/4, 80, 20, DARKBLUE); + DrawText(TextFormat("Aiming Point %i, %i", (int)player[playerTurn].aimingPoint.x, (int)player[playerTurn].aimingPoint.y), screenWidth*3/4, 110, 20, DARKBLUE); + DrawText(TextFormat("Aiming Angle %i", player[playerTurn].aimingAngle), screenWidth*3/4, 140, 20, DARKBLUE); + DrawText(TextFormat("Aiming Power %i", player[playerTurn].aimingPower), screenWidth*3/4, 170, 20, DARKBLUE); } */ diff --git a/games/just_do/Makefile b/games/just_do/Makefile index af9b31c12..ee4de401f 100644 --- a/games/just_do/Makefile +++ b/games/just_do/Makefile @@ -24,28 +24,43 @@ .PHONY: all clean # Define required raylib variables -# WARNING: To compile to HTML5, code must be redesigned to use emscripten.h and emscripten_set_main_loop() -PLATFORM ?= PLATFORM_DESKTOP -RAYLIB_PATH ?= ..\.. -PROJECT_NAME ?= just_do +PROJECT_NAME ?= just_do +RAYLIB_VERSION ?= 2.5.0 +RAYLIB_API_VERSION ?= 2 +RAYLIB_PATH ?= C:\GitHub\raylib -# Default path for raylib on Raspberry Pi, if installed in different path, update it! -ifeq ($(PLATFORM),PLATFORM_RPI) - RAYLIB_PATH ?= /home/pi/raylib -endif +# Define default options + +# One of PLATFORM_DESKTOP, PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB +PLATFORM ?= PLATFORM_DESKTOP + +# Locations of your newly installed library and associated headers. See ../src/Makefile +# On Linux, if you have installed raylib but cannot compile the examples, check that +# the *_INSTALL_PATH values here are the same as those in src/Makefile or point to known locations. +# To enable system-wide compile-time and runtime linking to libraylib.so, run ../src/$ sudo make install RAYLIB_LIBTYPE_SHARED. +# To enable compile-time linking to a special version of libraylib.so, change these variables here. +# To enable runtime linking to a special version of libraylib.so, see EXAMPLE_RUNTIME_PATH below. +# If there is a libraylib in both EXAMPLE_RUNTIME_PATH and RAYLIB_INSTALL_PATH, at runtime, +# the library at EXAMPLE_RUNTIME_PATH, if present, will take precedence over the one at RAYLIB_INSTALL_PATH. +# RAYLIB_INSTALL_PATH should be the desired full path to libraylib. No relative paths. +DESTDIR ?= /usr/local +RAYLIB_INSTALL_PATH ?= $(DESTDIR)/lib +# RAYLIB_H_INSTALL_PATH locates the installed raylib header and associated source files. +RAYLIB_H_INSTALL_PATH ?= $(DESTDIR)/include # Library type used for raylib: STATIC (.a) or SHARED (.so/.dll) -RAYLIB_LIBTYPE ?= STATIC +RAYLIB_LIBTYPE ?= STATIC + +# Build mode for project: DEBUG or RELEASE +BUILD_MODE ?= RELEASE # Use external GLFW library instead of rglfw module -USE_EXTERNAL_GLFW ?= FALSE +# TODO: Review usage on Linux. Target version of choice. Switch on -lglfw or -lglfw3 +USE_EXTERNAL_GLFW ?= FALSE # Use Wayland display server protocol on Linux desktop # by default it uses X11 windowing system -USE_WAYLAND_DISPLAY ?= FALSE - -# NOTE: On PLATFORM_WEB OpenAL Soft backend is used by default (check raylib/src/Makefile) - +USE_WAYLAND_DISPLAY ?= FALSE # Determine PLATFORM_OS in case PLATFORM_DESKTOP selected ifeq ($(PLATFORM),PLATFORM_DESKTOP) @@ -82,40 +97,50 @@ ifeq ($(PLATFORM),PLATFORM_RPI) endif endif +# RAYLIB_PATH adjustment for different platforms. +# If using GNU make, we can get the full path to the top of the tree. Windows? BSD? +# Required for ldconfig or other tools that do not perform path expansion. +ifeq ($(PLATFORM),PLATFORM_DESKTOP) + ifeq ($(PLATFORM_OS),LINUX) + RAYLIB_PREFIX ?= .. + RAYLIB_PATH = $(realpath $(RAYLIB_PREFIX)) + endif +endif +# Default path for raylib on Raspberry Pi, if installed in different path, update it! +# This is not currently used by src/Makefile. Not sure of its origin or usage. Refer to wiki. +# TODO: update install: target in src/Makefile for RPI, consider relation to LINUX. +ifeq ($(PLATFORM),PLATFORM_RPI) + RAYLIB_PATH ?= /home/pi/raylib +endif + ifeq ($(PLATFORM),PLATFORM_WEB) # Emscripten required variables - EMSDK_PATH = C:/emsdk - EMSCRIPTEN_VERSION = 1.37.28 - CLANG_VERSION=e1.37.28_64bit - PYTHON_VERSION=2.7.5.3_64bit - NODE_VERSION=4.1.1_64bit - export PATH=$(EMSDK_PATH);$(EMSDK_PATH)\clang\$(CLANG_VERSION);$(EMSDK_PATH)\node\$(NODE_VERSION)\bin;$(EMSDK_PATH)\python\$(PYTHON_VERSION);$(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION);C:\raylib\MinGW\bin:$$(PATH) - EMSCRIPTEN=$(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION) + EMSDK_PATH ?= C:/emsdk + EMSCRIPTEN_VERSION ?= 1.38.31 + CLANG_VERSION = e$(EMSCRIPTEN_VERSION)_64bit + PYTHON_VERSION = 2.7.13.1_64bit\python-2.7.13.amd64 + NODE_VERSION = 8.9.1_64bit + export PATH = $(EMSDK_PATH);$(EMSDK_PATH)\clang\$(CLANG_VERSION);$(EMSDK_PATH)\node\$(NODE_VERSION)\bin;$(EMSDK_PATH)\python\$(PYTHON_VERSION);$(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION);C:\raylib\MinGW\bin:$$(PATH) + EMSCRIPTEN = $(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION) endif -RAYLIB_RELEASE_PATH ?= $(RAYLIB_PATH)/release/libs +# Define raylib release directory for compiled library. +# RAYLIB_RELEASE_PATH points to provided binaries or your freshly built version +RAYLIB_RELEASE_PATH ?= $(RAYLIB_PATH)/src -# Define raylib release directory for compiled library -ifeq ($(PLATFORM),PLATFORM_DESKTOP) - ifeq ($(PLATFORM_OS),WINDOWS) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/win32/mingw32 - endif - ifeq ($(PLATFORM_OS),LINUX) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/linux - endif - ifeq ($(PLATFORM_OS),OSX) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/osx - endif - ifeq ($(PLATFORM_OS),BSD) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/bsd - endif -endif -ifeq ($(PLATFORM),PLATFORM_RPI) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/rpi -endif -ifeq ($(PLATFORM),PLATFORM_WEB) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/html5 -endif +# EXAMPLE_RUNTIME_PATH embeds a custom runtime location of libraylib.so or other desired libraries +# into each example binary compiled with RAYLIB_LIBTYPE=SHARED. It defaults to RAYLIB_RELEASE_PATH +# so that these examples link at runtime with your version of libraylib.so in ../release/libs/linux +# without formal installation from ../src/Makefile. It aids portability and is useful if you have +# multiple versions of raylib, have raylib installed to a non-standard location, or want to +# bundle libraylib.so with your game. Change it to your liking. +# NOTE: If, at runtime, there is a libraylib.so at both EXAMPLE_RUNTIME_PATH and RAYLIB_INSTALL_PATH, +# The library at EXAMPLE_RUNTIME_PATH, if present, will take precedence over RAYLIB_INSTALL_PATH, +# Implemented for LINUX below with CFLAGS += -Wl,-rpath,$(EXAMPLE_RUNTIME_PATH) +# To see the result, run readelf -d core/core_basic_window; looking at the RPATH or RUNPATH attribute. +# To see which libraries a built example is linking to, ldd core/core_basic_window; +# Look for libraylib.so.1 => $(RAYLIB_INSTALL_PATH)/libraylib.so.1 or similar listing. +EXAMPLE_RUNTIME_PATH ?= $(RAYLIB_RELEASE_PATH) # Define default C compiler: gcc # NOTE: define g++ compiler if using C++ @@ -140,6 +165,8 @@ ifeq ($(PLATFORM),PLATFORM_RPI) endif ifeq ($(PLATFORM),PLATFORM_WEB) # HTML5 emscripten compiler + # WARNING: To compile to HTML5, code must be redesigned + # to use emscripten.h and emscripten_set_main_loop() CC = emcc endif @@ -154,7 +181,7 @@ endif # Define compiler flags: # -O1 defines optimization level -# -g enable debugging +# -g include debug information on compilation # -s strip unnecessary data from build # -Wall turns on most, but not all, compiler warnings # -std=c99 defines C language mode (standard C from 1999 revision) @@ -163,56 +190,92 @@ endif # -D_DEFAULT_SOURCE use with -std=c99 on Linux and PLATFORM_WEB, required for timespec CFLAGS += -O1 -s -Wall -std=c99 -D_DEFAULT_SOURCE -Wno-missing-braces +ifeq ($(BUILD_MODE),DEBUG) + CFLAGS += -g +endif + # Additional flags for compiler (if desired) #CFLAGS += -Wextra -Wmissing-prototypes -Wstrict-prototypes ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),WINDOWS) - # resources file contains windows exe icon + # resource file contains windows executable icon and properties # -Wl,--subsystem,windows hides the console window CFLAGS += $(RAYLIB_PATH)/raylib.rc.data -Wl,--subsystem,windows endif ifeq ($(PLATFORM_OS),LINUX) - CFLAGS += -D_DEFAULT_SOURCE + ifeq ($(RAYLIB_LIBTYPE),STATIC) + CFLAGS += -D_DEFAULT_SOURCE + endif + ifeq ($(RAYLIB_LIBTYPE),SHARED) + # Explicitly enable runtime link to libraylib.so + CFLAGS += -Wl,-rpath,$(EXAMPLE_RUNTIME_PATH) + endif endif endif ifeq ($(PLATFORM),PLATFORM_RPI) CFLAGS += -std=gnu99 endif ifeq ($(PLATFORM),PLATFORM_WEB) - # -O2 # if used, also set --memory-init-file 0 - # --memory-init-file 0 # to avoid an external memory initialization code file (.mem) - # -s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing + # -Os # size optimization + # -O2 # optimization level 2, if used, also set --memory-init-file 0 + # -s USE_GLFW=3 # Use glfw3 library (context/input management) + # -s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing -> WARNING: Audio buffers could FAIL! # -s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB) # -s USE_PTHREADS=1 # multithreading support - # -s WASM=1 # support Web Assembly (https://github.com/kripken/emscripten/wiki/WebAssembly) + # -s WASM=0 # disable Web Assembly, emitted by default + # -s EMTERPRETIFY=1 # enable emscripten code interpreter (very slow) + # -s EMTERPRETIFY_ASYNC=1 # support synchronous loops by emterpreter + # -s FORCE_FILESYSTEM=1 # force filesystem to load/save files data + # -s ASSERTIONS=1 # enable runtime checks for common memory allocation errors (-O1 and above turn it off) + # --profiling # include information for code profiling + # --memory-init-file 0 # to avoid an external memory initialization code file (.mem) # --preload-file resources # specify a resources folder for data compilation - CFLAGS += -s USE_GLFW=3 -s ASSERTIONS=1 -s WASM=1 --profiling --preload-file resources - + CFLAGS += -Os -s USE_GLFW=3 -s TOTAL_MEMORY=16777216 --preload-file resources + ifeq ($(BUILD_MODE), DEBUG) + CFLAGS += -s ASSERTIONS=1 --profiling + endif + # Define a custom shell .html and output extension - CFLAGS += --shell-file $(RAYLIB_PATH)\templates\web_shell\shell.html + CFLAGS += --shell-file $(RAYLIB_PATH)/src/shell.html EXT = .html endif # Define include paths for required headers # NOTE: Several external required libraries (stb and others) -INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/release/include -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external +INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external # Define additional directories containing required header files ifeq ($(PLATFORM),PLATFORM_RPI) - # RPI requried libraries + # RPI required libraries INCLUDE_PATHS += -I/opt/vc/include INCLUDE_PATHS += -I/opt/vc/include/interface/vmcs_host/linux INCLUDE_PATHS += -I/opt/vc/include/interface/vcos/pthreads endif +ifeq ($(PLATFORM),PLATFORM_DESKTOP) + ifeq ($(PLATFORM_OS),BSD) + # Consider -L$(RAYLIB_H_INSTALL_PATH) + INCLUDE_PATHS += -I/usr/local/include + endif + ifeq ($(PLATFORM_OS),LINUX) + # Reset everything. + # Precedence: immediately local, installed version, raysan5 provided libs -I$(RAYLIB_H_INSTALL_PATH) -I$(RAYLIB_PATH)/release/include + INCLUDE_PATHS = -I$(RAYLIB_H_INSTALL_PATH) -isystem. -isystem$(RAYLIB_PATH)/src -isystem$(RAYLIB_PATH)/release/include -isystem$(RAYLIB_PATH)/src/external + endif +endif -# Define library paths containing required libs -LDFLAGS = -L. -L$(RAYLIB_RELEASE_PATH) -L$(RAYLIB_PATH)/src +# Define library paths containing required libs. +LDFLAGS = -L. -L$(RAYLIB_RELEASE_PATH) -L$(RAYLIB_PATH)/src ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),BSD) - INCLUDE_PATHS += -I/usr/local/include + # Consider -L$(RAYLIB_INSTALL_PATH) LDFLAGS += -L. -Lsrc -L/usr/local/lib endif + ifeq ($(PLATFORM_OS),LINUX) + # Reset everything. + # Precedence: immediately local, installed version, raysan5 provided libs + LDFLAGS = -L. -L$(RAYLIB_INSTALL_PATH) -L$(RAYLIB_RELEASE_PATH) + endif endif ifeq ($(PLATFORM),PLATFORM_RPI) @@ -224,7 +287,10 @@ endif ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),WINDOWS) # Libraries for Windows desktop compilation - LDLIBS = -lraylib -lopengl32 -lgdi32 + # NOTE: WinMM library required to set high-res timer resolution + LDLIBS = -lraylib -lopengl32 -lgdi32 -lwinmm + # Required for physac examples + #LDLIBS += -static -lpthread endif ifeq ($(PLATFORM_OS),LINUX) # Libraries for Debian GNU/Linux desktop compiling @@ -240,6 +306,10 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(USE_WAYLAND_DISPLAY),TRUE) LDLIBS += -lwayland-client -lwayland-cursor -lwayland-egl -lxkbcommon endif + # Explicit link to libc + ifeq ($(RAYLIB_LIBTYPE),SHARED) + LDLIBS += -lc + endif endif ifeq ($(PLATFORM_OS),OSX) # Libraries for OSX 10.9 desktop compiling @@ -247,7 +317,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) LDLIBS = -lraylib -framework OpenGL -framework OpenAL -framework Cocoa endif ifeq ($(PLATFORM_OS),BSD) - # Libraries for FreeBSD desktop compiling + # Libraries for FreeBSD, OpenBSD, NetBSD, DragonFly desktop compiling # NOTE: Required packages: mesa-libs LDLIBS = -lraylib -lGL -lpthread -lm @@ -270,18 +340,19 @@ ifeq ($(PLATFORM),PLATFORM_WEB) endif # Define all source files required -PROJECT_SOURCE_FILES ?= just_do.c \ - screens/screen_logo.c \ - screens/screen_level00.c \ - screens/screen_level01.c \ - screens/screen_level02.c \ - screens/screen_level03.c \ - screens/screen_level04.c \ - screens/screen_level05.c \ - screens/screen_level06.c \ - screens/screen_level07.c \ - screens/screen_level08.c \ - screens/screen_level09.c +PROJECT_SOURCE_FILES ?= \ + just_do.c \ + screens/screen_logo.c \ + screens/screen_level00.c \ + screens/screen_level01.c \ + screens/screen_level02.c \ + screens/screen_level03.c \ + screens/screen_level04.c \ + screens/screen_level05.c \ + screens/screen_level06.c \ + screens/screen_level07.c \ + screens/screen_level08.c \ + screens/screen_level09.c # Define all object files from source files OBJS = $(patsubst %.c, %.o, $(PROJECT_SOURCE_FILES)) @@ -316,7 +387,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) del *.o *.exe /s endif ifeq ($(PLATFORM_OS),LINUX) - find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -f + find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -fv endif ifeq ($(PLATFORM_OS),OSX) find . -type f -perm +ugo+x -delete @@ -325,7 +396,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) endif ifeq ($(PLATFORM),PLATFORM_RPI) find . -type f -executable -delete - rm -f *.o + rm -fv *.o endif ifeq ($(PLATFORM),PLATFORM_WEB) del *.o *.html *.js diff --git a/games/just_do/Makefile.Android b/games/just_do/Makefile.Android index f082ab230..29d437b1b 100644 --- a/games/just_do/Makefile.Android +++ b/games/just_do/Makefile.Android @@ -22,24 +22,33 @@ #************************************************************************************************** # Define required raylib variables -PLATFORM ?= PLATFORM_ANDROID -RAYLIB_PATH ?= ..\.. +PLATFORM ?= PLATFORM_ANDROID +RAYLIB_PATH ?= ..\.. + +# Define Android architecture (armeabi-v7a, arm64-v8a, x86, x86-64) and API version +ANDROID_ARCH ?= ARM +ANDROID_API_VERSION = 21 +ifeq ($(ANDROID_ARCH),ARM) + ANDROID_ARCH_NAME = armeabi-v7a +endif +ifeq ($(ANDROID_ARCH),ARM64) + ANDROID_ARCH_NAME = arm64-v8a +endif # Required path variables # NOTE: JAVA_HOME must be set to JDK -ANDROID_HOME = C:/android-sdk -ANDROID_NDK = C:/android-ndk -ANDROID_TOOLCHAIN = C:/android_toolchain_arm_api16 -ANDROID_BUILD_TOOLS = $(ANDROID_HOME)/build-tools/26.0.2 -ANDROID_PLATFORM_TOOLS = $(ANDROID_HOME)/platform-tools -JAVA_HOME = C:/PROGRA~1/Java/jdk1.8.0_144 +JAVA_HOME ?= C:/JavaJDK +ANDROID_HOME = C:/android-sdk +ANDROID_TOOLCHAIN = C:/android_toolchain_$(ANDROID_ARCH)_API$(ANDROID_API_VERSION) +ANDROID_BUILD_TOOLS = $(ANDROID_HOME)/build-tools/28.0.1 +ANDROID_PLATFORM_TOOLS = $(ANDROID_HOME)/platform-tools # Android project configuration variables -PROJECT_NAME ?= raylib_game -PROJECT_LIBRARY_NAME ?= main -PROJECT_BUILD_PATH ?= android.$(PROJECT_NAME) +PROJECT_NAME ?= raylib_game +PROJECT_LIBRARY_NAME ?= main +PROJECT_BUILD_PATH ?= android.$(PROJECT_NAME) PROJECT_RESOURCES_PATH ?= resources -PROJECT_SOURCE_FILES ?= raylib_game.c +PROJECT_SOURCE_FILES ?= raylib_game.c # Some source files are placed in directories, when compiling to some # output directory other than source, that directory must pre-exist. @@ -61,30 +70,43 @@ APP_KEYSTORE_PASS ?= raylib # Library type used for raylib: STATIC (.a) or SHARED (.so/.dll) RAYLIB_LIBTYPE ?= STATIC -RAYLIB_LIB_PATH = $(RAYLIB_PATH)\release\libs\android\armeabi-v7a + +# Library path for libraylib.a/libraylib.so +RAYLIB_LIB_PATH = $(RAYLIB_PATH)\src # Shared libs must be added to APK if required # NOTE: Generated NativeLoader.java automatically load those libraries ifeq ($(RAYLIB_LIBTYPE),SHARED) - PROJECT_SHARED_LIBS = lib/armeabi-v7a/libraylib.so + PROJECT_SHARED_LIBS = lib/$(ANDROID_ARCH_NAME)/libraylib.so endif # Compiler and archiver -# NOTE: GCC is being deprectated in Android NDK r16 -CC = $(ANDROID_TOOLCHAIN)/bin/arm-linux-androideabi-gcc -AR = $(ANDROID_TOOLCHAIN)/bin/arm-linux-androideabi-ar +# NOTE: GCC is being deprecated in Android NDK r16 +ifeq ($(ANDROID_ARCH),ARM) + CC = $(ANDROID_TOOLCHAIN)/bin/arm-linux-androideabi-clang + AR = $(ANDROID_TOOLCHAIN)/bin/arm-linux-androideabi-ar +endif +ifeq ($(ANDROID_ARCH),ARM64) + CC = $(ANDROID_TOOLCHAIN)/bin/aarch64-linux-android-clang + AR = $(ANDROID_TOOLCHAIN)/bin/aarch64-linux-android-ar +endif # Compiler flags for arquitecture -CFLAGS = -std=c99 -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 +ifeq ($(ANDROID_ARCH),ARM) + CFLAGS = -std=c99 -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 +endif +ifeq ($(ANDROID_ARCH),ARM64) + CFLAGS = -std=c99 -target aarch64 -mfix-cortex-a53-835769 +endif # Compilation functions attributes options CFLAGS += -ffunction-sections -funwind-tables -fstack-protector-strong -fPIC # Compiler options for the linker CFLAGS += -Wall -Wa,--noexecstack -Wformat -Werror=format-security -no-canonical-prefixes # Preprocessor macro definitions -CFLAGS += -DANDROID -DPLATFORM_ANDROID -D__ANDROID_API__=16 +CFLAGS += -DANDROID -DPLATFORM_ANDROID -D__ANDROID_API__=$(ANDROID_API_VERSION) # Paths containing required header files -INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/release/include -I$(RAYLIB_PATH)/src/external/android/native_app_glue +INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external/android/native_app_glue # Linker options LDFLAGS = -Wl,-soname,lib$(PROJECT_LIBRARY_NAME).so -Wl,--exclude-libs,libatomic.a @@ -92,11 +114,11 @@ LDFLAGS += -Wl,--build-id -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,relro -Wl # Force linking of library module to define symbol LDFLAGS += -u ANativeActivity_onCreate # Library paths containing required libs -LDFLAGS += -L. -L$(PROJECT_BUILD_PATH)/obj -L$(PROJECT_BUILD_PATH)/lib/armeabi-v7a +LDFLAGS += -L. -L$(PROJECT_BUILD_PATH)/obj -L$(PROJECT_BUILD_PATH)/lib/$(ANDROID_ARCH_NAME) -L$(ANDROID_TOOLCHAIN)\sysroot\usr\lib # Define any libraries to link into executable # if you want to link libraries (libname.so or libname.a), use the -lname -LDLIBS = -lraylib -lnative_app_glue -llog -landroid -lEGL -lGLESv2 -lOpenSLES -latomic -lc -lm -ldl +LDLIBS = -lm -lc -lraylib -llog -landroid -lEGL -lGLESv2 -lOpenSLES -ldl # Generate target objects list from PROJECT_SOURCE_FILES OBJS = $(patsubst %.c, $(PROJECT_BUILD_PATH)/obj/%.o, $(PROJECT_SOURCE_FILES)) @@ -110,7 +132,6 @@ all: create_temp_project_dirs \ generate_android_manifest \ generate_apk_keystore \ config_project_package \ - compile_native_app_glue \ compile_project_code \ compile_project_class \ compile_project_class_dex \ @@ -127,7 +148,7 @@ create_temp_project_dirs: if not exist $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME) mkdir $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME) if not exist $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME)\$(APP_PRODUCT_NAME) mkdir $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME)\$(APP_PRODUCT_NAME) if not exist $(PROJECT_BUILD_PATH)\lib mkdir $(PROJECT_BUILD_PATH)\lib - if not exist $(PROJECT_BUILD_PATH)\lib\armeabi-v7a mkdir $(PROJECT_BUILD_PATH)\lib\armeabi-v7a + if not exist $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME) mkdir $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME) if not exist $(PROJECT_BUILD_PATH)\bin mkdir $(PROJECT_BUILD_PATH)\bin if not exist $(PROJECT_BUILD_PATH)\res mkdir $(PROJECT_BUILD_PATH)\res if not exist $(PROJECT_BUILD_PATH)\res\drawable-ldpi mkdir $(PROJECT_BUILD_PATH)\res\drawable-ldpi @@ -147,10 +168,10 @@ endef # NOTE: If using shared libs they are loaded by generated NativeLoader.java copy_project_required_libs: ifeq ($(RAYLIB_LIBTYPE),SHARED) - copy /Y $(RAYLIB_LIB_PATH)\libraylib.so $(PROJECT_BUILD_PATH)\lib\armeabi-v7a\libraylib.so + copy /Y $(RAYLIB_LIB_PATH)\libraylib.so $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME)\libraylib.so endif ifeq ($(RAYLIB_LIBTYPE),STATIC) - copy /Y $(RAYLIB_LIB_PATH)\libraylib.a $(PROJECT_BUILD_PATH)\lib\armeabi-v7a\libraylib.a + copy /Y $(RAYLIB_LIB_PATH)\libraylib.a $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME)\libraylib.a endif # Copy project required resources: strings.xml, icon.png, assets @@ -185,7 +206,7 @@ generate_android_manifest: @echo ^> $(PROJECT_BUILD_PATH)/AndroidManifest.xml @echo package="com.$(APP_COMPANY_NAME).$(APP_PRODUCT_NAME)" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml @echo android:versionCode="$(APP_VERSION_CODE)" android:versionName="$(APP_VERSION_NAME)" ^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml - @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml @echo ^> $(PROJECT_BUILD_PATH)/AndroidManifest.xml @@ -210,7 +231,7 @@ generate_apk_keystore: # Config project package and resource using AndroidManifest.xml and res/values/strings.xml # NOTE: Generates resources file: src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/R.java config_project_package: - $(ANDROID_BUILD_TOOLS)/aapt package -f -m -S $(PROJECT_BUILD_PATH)/res -J $(PROJECT_BUILD_PATH)/src -M $(PROJECT_BUILD_PATH)/AndroidManifest.xml -I $(ANDROID_HOME)/platforms/android-16/android.jar + $(ANDROID_BUILD_TOOLS)/aapt package -f -m -S $(PROJECT_BUILD_PATH)/res -J $(PROJECT_BUILD_PATH)/src -M $(PROJECT_BUILD_PATH)/AndroidManifest.xml -I $(ANDROID_HOME)/platforms/android-$(ANDROID_API_VERSION)/android.jar # Compile native_app_glue code as static library: obj/libnative_app_glue.a compile_native_app_glue: @@ -219,7 +240,7 @@ compile_native_app_glue: # Compile project code into a shared library: lib/lib$(PROJECT_LIBRARY_NAME).so compile_project_code: $(OBJS) - $(CC) -o $(PROJECT_BUILD_PATH)/lib/armeabi-v7a/lib$(PROJECT_LIBRARY_NAME).so $(OBJS) -shared $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) + $(CC) -o $(PROJECT_BUILD_PATH)/lib/$(ANDROID_ARCH_NAME)/lib$(PROJECT_LIBRARY_NAME).so $(OBJS) -shared $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) # Compile all .c files required into object (.o) files # NOTE: Those files will be linked into a shared library @@ -228,7 +249,7 @@ $(PROJECT_BUILD_PATH)/obj/%.o:%.c # Compile project .java code into .class (Java bytecode) compile_project_class: - $(JAVA_HOME)/bin/javac -verbose -source 1.7 -target 1.7 -d $(PROJECT_BUILD_PATH)/obj -bootclasspath $(JAVA_HOME)/jre/lib/rt.jar -classpath $(ANDROID_HOME)/platforms/android-16/android.jar;$(PROJECT_BUILD_PATH)/obj -sourcepath $(PROJECT_BUILD_PATH)/src $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/R.java $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java + $(JAVA_HOME)/bin/javac -verbose -source 1.7 -target 1.7 -d $(PROJECT_BUILD_PATH)/obj -bootclasspath $(JAVA_HOME)/jre/lib/rt.jar -classpath $(ANDROID_HOME)/platforms/android-$(ANDROID_API_VERSION)/android.jar;$(PROJECT_BUILD_PATH)/obj -sourcepath $(PROJECT_BUILD_PATH)/src $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/R.java $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java # Compile .class files into Dalvik executable bytecode (.dex) # NOTE: Since Android 5.0, Dalvik interpreter (JIT) has been replaced by ART (AOT) @@ -239,8 +260,8 @@ compile_project_class_dex: # NOTE: Requires compiled classes.dex and lib$(PROJECT_LIBRARY_NAME).so # NOTE: Use -A resources to define additional directory in which to find raw asset files create_project_apk_package: - $(ANDROID_BUILD_TOOLS)/aapt package -f -M $(PROJECT_BUILD_PATH)/AndroidManifest.xml -S $(PROJECT_BUILD_PATH)/res -A $(PROJECT_BUILD_PATH)/assets -I $(ANDROID_HOME)/platforms/android-16/android.jar -F $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).unsigned.apk $(PROJECT_BUILD_PATH)/bin - cd $(PROJECT_BUILD_PATH) && $(ANDROID_BUILD_TOOLS)/aapt add bin/$(PROJECT_NAME).unsigned.apk lib/armeabi-v7a/lib$(PROJECT_LIBRARY_NAME).so $(PROJECT_SHARED_LIBS) + $(ANDROID_BUILD_TOOLS)/aapt package -f -M $(PROJECT_BUILD_PATH)/AndroidManifest.xml -S $(PROJECT_BUILD_PATH)/res -A $(PROJECT_BUILD_PATH)/assets -I $(ANDROID_HOME)/platforms/android-$(ANDROID_API_VERSION)/android.jar -F $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).unsigned.apk $(PROJECT_BUILD_PATH)/bin + cd $(PROJECT_BUILD_PATH) && $(ANDROID_BUILD_TOOLS)/aapt add bin/$(PROJECT_NAME).unsigned.apk lib/$(ANDROID_ARCH_NAME)/lib$(PROJECT_LIBRARY_NAME).so $(PROJECT_SHARED_LIBS) # Create signed APK package using generated Key: bin/$(PROJECT_NAME).signed.apk sign_project_apk_package: @@ -253,7 +274,11 @@ zipalign_project_apk_package: # Install $(PROJECT_NAME).apk to default emulator/device # NOTE: Use -e (emulator) or -d (device) parameters if required install: - $(ANDROID_PLATFORM_TOOLS)/adb install -r $(PROJECT_NAME).apk + $(ANDROID_PLATFORM_TOOLS)/adb install --abi $(ANDROID_ARCH_NAME) -rds $(PROJECT_NAME).apk + +# Check supported ABI for the device (armeabi-v7a, arm64-v8a, x86, x86_64) +check_device_abi: + $(ANDROID_PLATFORM_TOOLS)/adb shell getprop ro.product.cpu.abi # Monitorize output log coming from device, only raylib tag logcat: diff --git a/games/just_do/just_do.c b/games/just_do/just_do.c index c7c76af96..6a73a2b38 100644 --- a/games/just_do/just_do.c +++ b/games/just_do/just_do.c @@ -1,20 +1,19 @@ /******************************************************************************************* * -* JUST DO - Global Game Jam 2015 Videogame -* Experimental puzzle game that lets the user try to find a logic solution to -* different shape-color-based situations. +* JUST DO [GLOBAL GAME JAM 2015] * -* Developed by: Ramon Santamaria (Ray San) +* Experimental puzzle game that lets the user try to find a logic +* solution to different shape-color-based situations. * * This game has been created using raylib 1.6 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * -* raylib - Copyright (c) 2015 Ramon Santamaria (@raysan5) +* Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ #include "raylib.h" -#include "screens/screens.h" // NOTE: Defines currentScreen +#include "screens/screens.h" // NOTE: Defines global variable: currentScreen #if defined(PLATFORM_WEB) #include @@ -51,9 +50,9 @@ void UpdateDrawFrame(void); // Update and Draw one frame //---------------------------------------------------------------------------------- int main(void) { - // Initialization (Note windowTitle is unused on Android) - //--------------------------------------------------------- - InitWindow(screenWidth, screenHeight, "GGJ15 - JUST DO"); + // Initialization (Note windowTitle is unused on Android) + //--------------------------------------------------------- + InitWindow(screenWidth, screenHeight, "JUST DO [GGJ15]"); // Load global data here (assets that must be available in all screens, i.e. fonts) InitAudioDevice(); @@ -74,9 +73,6 @@ int main(void) // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { - - if (IsKeyPressed(KEY_SPACE)) PlaySound(levelWin); - UpdateDrawFrame(); } #endif @@ -144,6 +140,8 @@ void UpdateDrawFrame(void) { // Update //---------------------------------------------------------------------------------- + if (currentScreen != LOGO) UpdateMusicStream(music); + if (!onTransition) { if (IsKeyPressed('0')) @@ -197,8 +195,6 @@ void UpdateDrawFrame(void) InitLevel08Screen(); } - UpdateMusicStream(music); - switch(currentScreen) { case LOGO: diff --git a/games/koala_seasons/Makefile b/games/koala_seasons/Makefile index 25dbe6964..fea4437d8 100644 --- a/games/koala_seasons/Makefile +++ b/games/koala_seasons/Makefile @@ -24,28 +24,43 @@ .PHONY: all clean # Define required raylib variables -# WARNING: To compile to HTML5, code must be redesigned to use emscripten.h and emscripten_set_main_loop() -PLATFORM ?= PLATFORM_DESKTOP -RAYLIB_PATH ?= ..\.. -PROJECT_NAME ?= koala_seasons +PROJECT_NAME ?= koala_seasons +RAYLIB_VERSION ?= 2.5.0 +RAYLIB_API_VERSION ?= 2 +RAYLIB_PATH ?= C:\GitHub\raylib -# Default path for raylib on Raspberry Pi, if installed in different path, update it! -ifeq ($(PLATFORM),PLATFORM_RPI) - RAYLIB_PATH ?= /home/pi/raylib -endif +# Define default options + +# One of PLATFORM_DESKTOP, PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB +PLATFORM ?= PLATFORM_DESKTOP + +# Locations of your newly installed library and associated headers. See ../src/Makefile +# On Linux, if you have installed raylib but cannot compile the examples, check that +# the *_INSTALL_PATH values here are the same as those in src/Makefile or point to known locations. +# To enable system-wide compile-time and runtime linking to libraylib.so, run ../src/$ sudo make install RAYLIB_LIBTYPE_SHARED. +# To enable compile-time linking to a special version of libraylib.so, change these variables here. +# To enable runtime linking to a special version of libraylib.so, see EXAMPLE_RUNTIME_PATH below. +# If there is a libraylib in both EXAMPLE_RUNTIME_PATH and RAYLIB_INSTALL_PATH, at runtime, +# the library at EXAMPLE_RUNTIME_PATH, if present, will take precedence over the one at RAYLIB_INSTALL_PATH. +# RAYLIB_INSTALL_PATH should be the desired full path to libraylib. No relative paths. +DESTDIR ?= /usr/local +RAYLIB_INSTALL_PATH ?= $(DESTDIR)/lib +# RAYLIB_H_INSTALL_PATH locates the installed raylib header and associated source files. +RAYLIB_H_INSTALL_PATH ?= $(DESTDIR)/include # Library type used for raylib: STATIC (.a) or SHARED (.so/.dll) -RAYLIB_LIBTYPE ?= STATIC +RAYLIB_LIBTYPE ?= STATIC + +# Build mode for project: DEBUG or RELEASE +BUILD_MODE ?= RELEASE # Use external GLFW library instead of rglfw module -USE_EXTERNAL_GLFW ?= FALSE +# TODO: Review usage on Linux. Target version of choice. Switch on -lglfw or -lglfw3 +USE_EXTERNAL_GLFW ?= FALSE # Use Wayland display server protocol on Linux desktop # by default it uses X11 windowing system -USE_WAYLAND_DISPLAY ?= FALSE - -# NOTE: On PLATFORM_WEB OpenAL Soft backend is used by default (check raylib/src/Makefile) - +USE_WAYLAND_DISPLAY ?= FALSE # Determine PLATFORM_OS in case PLATFORM_DESKTOP selected ifeq ($(PLATFORM),PLATFORM_DESKTOP) @@ -82,40 +97,50 @@ ifeq ($(PLATFORM),PLATFORM_RPI) endif endif +# RAYLIB_PATH adjustment for different platforms. +# If using GNU make, we can get the full path to the top of the tree. Windows? BSD? +# Required for ldconfig or other tools that do not perform path expansion. +ifeq ($(PLATFORM),PLATFORM_DESKTOP) + ifeq ($(PLATFORM_OS),LINUX) + RAYLIB_PREFIX ?= .. + RAYLIB_PATH = $(realpath $(RAYLIB_PREFIX)) + endif +endif +# Default path for raylib on Raspberry Pi, if installed in different path, update it! +# This is not currently used by src/Makefile. Not sure of its origin or usage. Refer to wiki. +# TODO: update install: target in src/Makefile for RPI, consider relation to LINUX. +ifeq ($(PLATFORM),PLATFORM_RPI) + RAYLIB_PATH ?= /home/pi/raylib +endif + ifeq ($(PLATFORM),PLATFORM_WEB) # Emscripten required variables - EMSDK_PATH = C:/emsdk - EMSCRIPTEN_VERSION = 1.37.28 - CLANG_VERSION=e1.37.28_64bit - PYTHON_VERSION=2.7.5.3_64bit - NODE_VERSION=4.1.1_64bit - export PATH=$(EMSDK_PATH);$(EMSDK_PATH)\clang\$(CLANG_VERSION);$(EMSDK_PATH)\node\$(NODE_VERSION)\bin;$(EMSDK_PATH)\python\$(PYTHON_VERSION);$(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION);C:\raylib\MinGW\bin:$$(PATH) - EMSCRIPTEN=$(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION) + EMSDK_PATH ?= C:/emsdk + EMSCRIPTEN_VERSION ?= 1.38.32 + CLANG_VERSION = e$(EMSCRIPTEN_VERSION)_64bit + PYTHON_VERSION = 2.7.13.1_64bit\python-2.7.13.amd64 + NODE_VERSION = 8.9.1_64bit + export PATH = $(EMSDK_PATH);$(EMSDK_PATH)\clang\$(CLANG_VERSION);$(EMSDK_PATH)\node\$(NODE_VERSION)\bin;$(EMSDK_PATH)\python\$(PYTHON_VERSION);$(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION);C:\raylib\MinGW\bin:$$(PATH) + EMSCRIPTEN = $(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION) endif -RAYLIB_RELEASE_PATH ?= $(RAYLIB_PATH)/release/libs +# Define raylib release directory for compiled library. +# RAYLIB_RELEASE_PATH points to provided binaries or your freshly built version +RAYLIB_RELEASE_PATH ?= $(RAYLIB_PATH)/src -# Define raylib release directory for compiled library -ifeq ($(PLATFORM),PLATFORM_DESKTOP) - ifeq ($(PLATFORM_OS),WINDOWS) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/win32/mingw32 - endif - ifeq ($(PLATFORM_OS),LINUX) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/linux - endif - ifeq ($(PLATFORM_OS),OSX) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/osx - endif - ifeq ($(PLATFORM_OS),BSD) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/bsd - endif -endif -ifeq ($(PLATFORM),PLATFORM_RPI) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/rpi -endif -ifeq ($(PLATFORM),PLATFORM_WEB) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/html5 -endif +# EXAMPLE_RUNTIME_PATH embeds a custom runtime location of libraylib.so or other desired libraries +# into each example binary compiled with RAYLIB_LIBTYPE=SHARED. It defaults to RAYLIB_RELEASE_PATH +# so that these examples link at runtime with your version of libraylib.so in ../release/libs/linux +# without formal installation from ../src/Makefile. It aids portability and is useful if you have +# multiple versions of raylib, have raylib installed to a non-standard location, or want to +# bundle libraylib.so with your game. Change it to your liking. +# NOTE: If, at runtime, there is a libraylib.so at both EXAMPLE_RUNTIME_PATH and RAYLIB_INSTALL_PATH, +# The library at EXAMPLE_RUNTIME_PATH, if present, will take precedence over RAYLIB_INSTALL_PATH, +# Implemented for LINUX below with CFLAGS += -Wl,-rpath,$(EXAMPLE_RUNTIME_PATH) +# To see the result, run readelf -d core/core_basic_window; looking at the RPATH or RUNPATH attribute. +# To see which libraries a built example is linking to, ldd core/core_basic_window; +# Look for libraylib.so.1 => $(RAYLIB_INSTALL_PATH)/libraylib.so.1 or similar listing. +EXAMPLE_RUNTIME_PATH ?= $(RAYLIB_RELEASE_PATH) # Define default C compiler: gcc # NOTE: define g++ compiler if using C++ @@ -140,6 +165,8 @@ ifeq ($(PLATFORM),PLATFORM_RPI) endif ifeq ($(PLATFORM),PLATFORM_WEB) # HTML5 emscripten compiler + # WARNING: To compile to HTML5, code must be redesigned + # to use emscripten.h and emscripten_set_main_loop() CC = emcc endif @@ -154,7 +181,7 @@ endif # Define compiler flags: # -O1 defines optimization level -# -g enable debugging +# -g include debug information on compilation # -s strip unnecessary data from build # -Wall turns on most, but not all, compiler warnings # -std=c99 defines C language mode (standard C from 1999 revision) @@ -163,56 +190,92 @@ endif # -D_DEFAULT_SOURCE use with -std=c99 on Linux and PLATFORM_WEB, required for timespec CFLAGS += -O1 -s -Wall -std=c99 -D_DEFAULT_SOURCE -Wno-missing-braces +ifeq ($(BUILD_MODE),DEBUG) + CFLAGS += -g +endif + # Additional flags for compiler (if desired) #CFLAGS += -Wextra -Wmissing-prototypes -Wstrict-prototypes ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),WINDOWS) - # resources file contains windows exe icon + # resource file contains windows executable icon and properties # -Wl,--subsystem,windows hides the console window - CFLAGS += $(RAYLIB_PATH)/raylib.rc.data -Wl,--subsystem,windows + CFLAGS += $(RAYLIB_PATH)/src/raylib.rc.data -Wl,--subsystem,windows endif ifeq ($(PLATFORM_OS),LINUX) - CFLAGS += -D_DEFAULT_SOURCE + ifeq ($(RAYLIB_LIBTYPE),STATIC) + CFLAGS += -D_DEFAULT_SOURCE + endif + ifeq ($(RAYLIB_LIBTYPE),SHARED) + # Explicitly enable runtime link to libraylib.so + CFLAGS += -Wl,-rpath,$(EXAMPLE_RUNTIME_PATH) + endif endif endif ifeq ($(PLATFORM),PLATFORM_RPI) CFLAGS += -std=gnu99 endif ifeq ($(PLATFORM),PLATFORM_WEB) - # -O2 # if used, also set --memory-init-file 0 - # --memory-init-file 0 # to avoid an external memory initialization code file (.mem) - # -s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing + # -Os # size optimization + # -O2 # optimization level 2, if used, also set --memory-init-file 0 + # -s USE_GLFW=3 # Use glfw3 library (context/input management) + # -s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing -> WARNING: Audio buffers could FAIL! # -s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB) # -s USE_PTHREADS=1 # multithreading support - # -s WASM=1 # support Web Assembly (https://github.com/kripken/emscripten/wiki/WebAssembly) + # -s WASM=0 # disable Web Assembly, emitted by default + # -s EMTERPRETIFY=1 # enable emscripten code interpreter (very slow) + # -s EMTERPRETIFY_ASYNC=1 # support synchronous loops by emterpreter + # -s FORCE_FILESYSTEM=1 # force filesystem to load/save files data + # -s ASSERTIONS=1 # enable runtime checks for common memory allocation errors (-O1 and above turn it off) + # --profiling # include information for code profiling + # --memory-init-file 0 # to avoid an external memory initialization code file (.mem) # --preload-file resources # specify a resources folder for data compilation - CFLAGS += -s USE_GLFW=3 -s ASSERTIONS=1 -s WASM=1 --profiling --preload-file resources - + CFLAGS += -Os -s USE_GLFW=3 -s TOTAL_MEMORY=67108864 --preload-file resources + ifeq ($(BUILD_MODE), DEBUG) + CFLAGS += -s ASSERTIONS=1 --profiling + endif + # Define a custom shell .html and output extension - CFLAGS += --shell-file $(RAYLIB_PATH)\templates\web_shell\shell.html + CFLAGS += --shell-file $(RAYLIB_PATH)/src/shell.html EXT = .html endif # Define include paths for required headers # NOTE: Several external required libraries (stb and others) -INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/release/include -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external +INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external # Define additional directories containing required header files ifeq ($(PLATFORM),PLATFORM_RPI) - # RPI requried libraries + # RPI required libraries INCLUDE_PATHS += -I/opt/vc/include INCLUDE_PATHS += -I/opt/vc/include/interface/vmcs_host/linux INCLUDE_PATHS += -I/opt/vc/include/interface/vcos/pthreads endif +ifeq ($(PLATFORM),PLATFORM_DESKTOP) + ifeq ($(PLATFORM_OS),BSD) + # Consider -L$(RAYLIB_H_INSTALL_PATH) + INCLUDE_PATHS += -I/usr/local/include + endif + ifeq ($(PLATFORM_OS),LINUX) + # Reset everything. + # Precedence: immediately local, installed version, raysan5 provided libs -I$(RAYLIB_H_INSTALL_PATH) -I$(RAYLIB_PATH)/release/include + INCLUDE_PATHS = -I$(RAYLIB_H_INSTALL_PATH) -isystem. -isystem$(RAYLIB_PATH)/src -isystem$(RAYLIB_PATH)/release/include -isystem$(RAYLIB_PATH)/src/external + endif +endif -# Define library paths containing required libs -LDFLAGS = -L. -L$(RAYLIB_RELEASE_PATH) -L$(RAYLIB_PATH)/src +# Define library paths containing required libs. +LDFLAGS = -L. -L$(RAYLIB_RELEASE_PATH) -L$(RAYLIB_PATH)/src ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),BSD) - INCLUDE_PATHS += -I/usr/local/include + # Consider -L$(RAYLIB_INSTALL_PATH) LDFLAGS += -L. -Lsrc -L/usr/local/lib endif + ifeq ($(PLATFORM_OS),LINUX) + # Reset everything. + # Precedence: immediately local, installed version, raysan5 provided libs + LDFLAGS = -L. -L$(RAYLIB_INSTALL_PATH) -L$(RAYLIB_RELEASE_PATH) + endif endif ifeq ($(PLATFORM),PLATFORM_RPI) @@ -224,7 +287,10 @@ endif ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),WINDOWS) # Libraries for Windows desktop compilation - LDLIBS = -lraylib -lopengl32 -lgdi32 + # NOTE: WinMM library required to set high-res timer resolution + LDLIBS = -lraylib -lopengl32 -lgdi32 -lwinmm + # Required for physac examples + #LDLIBS += -static -lpthread endif ifeq ($(PLATFORM_OS),LINUX) # Libraries for Debian GNU/Linux desktop compiling @@ -240,6 +306,10 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(USE_WAYLAND_DISPLAY),TRUE) LDLIBS += -lwayland-client -lwayland-cursor -lwayland-egl -lxkbcommon endif + # Explicit link to libc + ifeq ($(RAYLIB_LIBTYPE),SHARED) + LDLIBS += -lc + endif endif ifeq ($(PLATFORM_OS),OSX) # Libraries for OSX 10.9 desktop compiling @@ -270,11 +340,12 @@ ifeq ($(PLATFORM),PLATFORM_WEB) endif # Define all source files required -PROJECT_SOURCE_FILES ?= koala_seasons.c \ - screens/screen_logo.c \ - screens/screen_title.c \ - screens/screen_gameplay.c \ - screens/screen_ending.c +PROJECT_SOURCE_FILES ?= \ + koala_seasons.c \ + screens/screen_logo.c \ + screens/screen_title.c \ + screens/screen_gameplay.c \ + screens/screen_ending.c # Define all object files from source files OBJS = $(patsubst %.c, %.o, $(PROJECT_SOURCE_FILES)) @@ -309,7 +380,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) del *.o *.exe /s endif ifeq ($(PLATFORM_OS),LINUX) - find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -f + find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -fv endif ifeq ($(PLATFORM_OS),OSX) find . -type f -perm +ugo+x -delete @@ -318,7 +389,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) endif ifeq ($(PLATFORM),PLATFORM_RPI) find . -type f -executable -delete - rm -f *.o + rm -fv *.o endif ifeq ($(PLATFORM),PLATFORM_WEB) del *.o *.html *.js diff --git a/games/koala_seasons/Makefile.Android b/games/koala_seasons/Makefile.Android index f082ab230..29d437b1b 100644 --- a/games/koala_seasons/Makefile.Android +++ b/games/koala_seasons/Makefile.Android @@ -22,24 +22,33 @@ #************************************************************************************************** # Define required raylib variables -PLATFORM ?= PLATFORM_ANDROID -RAYLIB_PATH ?= ..\.. +PLATFORM ?= PLATFORM_ANDROID +RAYLIB_PATH ?= ..\.. + +# Define Android architecture (armeabi-v7a, arm64-v8a, x86, x86-64) and API version +ANDROID_ARCH ?= ARM +ANDROID_API_VERSION = 21 +ifeq ($(ANDROID_ARCH),ARM) + ANDROID_ARCH_NAME = armeabi-v7a +endif +ifeq ($(ANDROID_ARCH),ARM64) + ANDROID_ARCH_NAME = arm64-v8a +endif # Required path variables # NOTE: JAVA_HOME must be set to JDK -ANDROID_HOME = C:/android-sdk -ANDROID_NDK = C:/android-ndk -ANDROID_TOOLCHAIN = C:/android_toolchain_arm_api16 -ANDROID_BUILD_TOOLS = $(ANDROID_HOME)/build-tools/26.0.2 -ANDROID_PLATFORM_TOOLS = $(ANDROID_HOME)/platform-tools -JAVA_HOME = C:/PROGRA~1/Java/jdk1.8.0_144 +JAVA_HOME ?= C:/JavaJDK +ANDROID_HOME = C:/android-sdk +ANDROID_TOOLCHAIN = C:/android_toolchain_$(ANDROID_ARCH)_API$(ANDROID_API_VERSION) +ANDROID_BUILD_TOOLS = $(ANDROID_HOME)/build-tools/28.0.1 +ANDROID_PLATFORM_TOOLS = $(ANDROID_HOME)/platform-tools # Android project configuration variables -PROJECT_NAME ?= raylib_game -PROJECT_LIBRARY_NAME ?= main -PROJECT_BUILD_PATH ?= android.$(PROJECT_NAME) +PROJECT_NAME ?= raylib_game +PROJECT_LIBRARY_NAME ?= main +PROJECT_BUILD_PATH ?= android.$(PROJECT_NAME) PROJECT_RESOURCES_PATH ?= resources -PROJECT_SOURCE_FILES ?= raylib_game.c +PROJECT_SOURCE_FILES ?= raylib_game.c # Some source files are placed in directories, when compiling to some # output directory other than source, that directory must pre-exist. @@ -61,30 +70,43 @@ APP_KEYSTORE_PASS ?= raylib # Library type used for raylib: STATIC (.a) or SHARED (.so/.dll) RAYLIB_LIBTYPE ?= STATIC -RAYLIB_LIB_PATH = $(RAYLIB_PATH)\release\libs\android\armeabi-v7a + +# Library path for libraylib.a/libraylib.so +RAYLIB_LIB_PATH = $(RAYLIB_PATH)\src # Shared libs must be added to APK if required # NOTE: Generated NativeLoader.java automatically load those libraries ifeq ($(RAYLIB_LIBTYPE),SHARED) - PROJECT_SHARED_LIBS = lib/armeabi-v7a/libraylib.so + PROJECT_SHARED_LIBS = lib/$(ANDROID_ARCH_NAME)/libraylib.so endif # Compiler and archiver -# NOTE: GCC is being deprectated in Android NDK r16 -CC = $(ANDROID_TOOLCHAIN)/bin/arm-linux-androideabi-gcc -AR = $(ANDROID_TOOLCHAIN)/bin/arm-linux-androideabi-ar +# NOTE: GCC is being deprecated in Android NDK r16 +ifeq ($(ANDROID_ARCH),ARM) + CC = $(ANDROID_TOOLCHAIN)/bin/arm-linux-androideabi-clang + AR = $(ANDROID_TOOLCHAIN)/bin/arm-linux-androideabi-ar +endif +ifeq ($(ANDROID_ARCH),ARM64) + CC = $(ANDROID_TOOLCHAIN)/bin/aarch64-linux-android-clang + AR = $(ANDROID_TOOLCHAIN)/bin/aarch64-linux-android-ar +endif # Compiler flags for arquitecture -CFLAGS = -std=c99 -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 +ifeq ($(ANDROID_ARCH),ARM) + CFLAGS = -std=c99 -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 +endif +ifeq ($(ANDROID_ARCH),ARM64) + CFLAGS = -std=c99 -target aarch64 -mfix-cortex-a53-835769 +endif # Compilation functions attributes options CFLAGS += -ffunction-sections -funwind-tables -fstack-protector-strong -fPIC # Compiler options for the linker CFLAGS += -Wall -Wa,--noexecstack -Wformat -Werror=format-security -no-canonical-prefixes # Preprocessor macro definitions -CFLAGS += -DANDROID -DPLATFORM_ANDROID -D__ANDROID_API__=16 +CFLAGS += -DANDROID -DPLATFORM_ANDROID -D__ANDROID_API__=$(ANDROID_API_VERSION) # Paths containing required header files -INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/release/include -I$(RAYLIB_PATH)/src/external/android/native_app_glue +INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external/android/native_app_glue # Linker options LDFLAGS = -Wl,-soname,lib$(PROJECT_LIBRARY_NAME).so -Wl,--exclude-libs,libatomic.a @@ -92,11 +114,11 @@ LDFLAGS += -Wl,--build-id -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,relro -Wl # Force linking of library module to define symbol LDFLAGS += -u ANativeActivity_onCreate # Library paths containing required libs -LDFLAGS += -L. -L$(PROJECT_BUILD_PATH)/obj -L$(PROJECT_BUILD_PATH)/lib/armeabi-v7a +LDFLAGS += -L. -L$(PROJECT_BUILD_PATH)/obj -L$(PROJECT_BUILD_PATH)/lib/$(ANDROID_ARCH_NAME) -L$(ANDROID_TOOLCHAIN)\sysroot\usr\lib # Define any libraries to link into executable # if you want to link libraries (libname.so or libname.a), use the -lname -LDLIBS = -lraylib -lnative_app_glue -llog -landroid -lEGL -lGLESv2 -lOpenSLES -latomic -lc -lm -ldl +LDLIBS = -lm -lc -lraylib -llog -landroid -lEGL -lGLESv2 -lOpenSLES -ldl # Generate target objects list from PROJECT_SOURCE_FILES OBJS = $(patsubst %.c, $(PROJECT_BUILD_PATH)/obj/%.o, $(PROJECT_SOURCE_FILES)) @@ -110,7 +132,6 @@ all: create_temp_project_dirs \ generate_android_manifest \ generate_apk_keystore \ config_project_package \ - compile_native_app_glue \ compile_project_code \ compile_project_class \ compile_project_class_dex \ @@ -127,7 +148,7 @@ create_temp_project_dirs: if not exist $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME) mkdir $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME) if not exist $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME)\$(APP_PRODUCT_NAME) mkdir $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME)\$(APP_PRODUCT_NAME) if not exist $(PROJECT_BUILD_PATH)\lib mkdir $(PROJECT_BUILD_PATH)\lib - if not exist $(PROJECT_BUILD_PATH)\lib\armeabi-v7a mkdir $(PROJECT_BUILD_PATH)\lib\armeabi-v7a + if not exist $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME) mkdir $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME) if not exist $(PROJECT_BUILD_PATH)\bin mkdir $(PROJECT_BUILD_PATH)\bin if not exist $(PROJECT_BUILD_PATH)\res mkdir $(PROJECT_BUILD_PATH)\res if not exist $(PROJECT_BUILD_PATH)\res\drawable-ldpi mkdir $(PROJECT_BUILD_PATH)\res\drawable-ldpi @@ -147,10 +168,10 @@ endef # NOTE: If using shared libs they are loaded by generated NativeLoader.java copy_project_required_libs: ifeq ($(RAYLIB_LIBTYPE),SHARED) - copy /Y $(RAYLIB_LIB_PATH)\libraylib.so $(PROJECT_BUILD_PATH)\lib\armeabi-v7a\libraylib.so + copy /Y $(RAYLIB_LIB_PATH)\libraylib.so $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME)\libraylib.so endif ifeq ($(RAYLIB_LIBTYPE),STATIC) - copy /Y $(RAYLIB_LIB_PATH)\libraylib.a $(PROJECT_BUILD_PATH)\lib\armeabi-v7a\libraylib.a + copy /Y $(RAYLIB_LIB_PATH)\libraylib.a $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME)\libraylib.a endif # Copy project required resources: strings.xml, icon.png, assets @@ -185,7 +206,7 @@ generate_android_manifest: @echo ^> $(PROJECT_BUILD_PATH)/AndroidManifest.xml @echo package="com.$(APP_COMPANY_NAME).$(APP_PRODUCT_NAME)" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml @echo android:versionCode="$(APP_VERSION_CODE)" android:versionName="$(APP_VERSION_NAME)" ^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml - @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml @echo ^> $(PROJECT_BUILD_PATH)/AndroidManifest.xml @@ -210,7 +231,7 @@ generate_apk_keystore: # Config project package and resource using AndroidManifest.xml and res/values/strings.xml # NOTE: Generates resources file: src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/R.java config_project_package: - $(ANDROID_BUILD_TOOLS)/aapt package -f -m -S $(PROJECT_BUILD_PATH)/res -J $(PROJECT_BUILD_PATH)/src -M $(PROJECT_BUILD_PATH)/AndroidManifest.xml -I $(ANDROID_HOME)/platforms/android-16/android.jar + $(ANDROID_BUILD_TOOLS)/aapt package -f -m -S $(PROJECT_BUILD_PATH)/res -J $(PROJECT_BUILD_PATH)/src -M $(PROJECT_BUILD_PATH)/AndroidManifest.xml -I $(ANDROID_HOME)/platforms/android-$(ANDROID_API_VERSION)/android.jar # Compile native_app_glue code as static library: obj/libnative_app_glue.a compile_native_app_glue: @@ -219,7 +240,7 @@ compile_native_app_glue: # Compile project code into a shared library: lib/lib$(PROJECT_LIBRARY_NAME).so compile_project_code: $(OBJS) - $(CC) -o $(PROJECT_BUILD_PATH)/lib/armeabi-v7a/lib$(PROJECT_LIBRARY_NAME).so $(OBJS) -shared $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) + $(CC) -o $(PROJECT_BUILD_PATH)/lib/$(ANDROID_ARCH_NAME)/lib$(PROJECT_LIBRARY_NAME).so $(OBJS) -shared $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) # Compile all .c files required into object (.o) files # NOTE: Those files will be linked into a shared library @@ -228,7 +249,7 @@ $(PROJECT_BUILD_PATH)/obj/%.o:%.c # Compile project .java code into .class (Java bytecode) compile_project_class: - $(JAVA_HOME)/bin/javac -verbose -source 1.7 -target 1.7 -d $(PROJECT_BUILD_PATH)/obj -bootclasspath $(JAVA_HOME)/jre/lib/rt.jar -classpath $(ANDROID_HOME)/platforms/android-16/android.jar;$(PROJECT_BUILD_PATH)/obj -sourcepath $(PROJECT_BUILD_PATH)/src $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/R.java $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java + $(JAVA_HOME)/bin/javac -verbose -source 1.7 -target 1.7 -d $(PROJECT_BUILD_PATH)/obj -bootclasspath $(JAVA_HOME)/jre/lib/rt.jar -classpath $(ANDROID_HOME)/platforms/android-$(ANDROID_API_VERSION)/android.jar;$(PROJECT_BUILD_PATH)/obj -sourcepath $(PROJECT_BUILD_PATH)/src $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/R.java $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java # Compile .class files into Dalvik executable bytecode (.dex) # NOTE: Since Android 5.0, Dalvik interpreter (JIT) has been replaced by ART (AOT) @@ -239,8 +260,8 @@ compile_project_class_dex: # NOTE: Requires compiled classes.dex and lib$(PROJECT_LIBRARY_NAME).so # NOTE: Use -A resources to define additional directory in which to find raw asset files create_project_apk_package: - $(ANDROID_BUILD_TOOLS)/aapt package -f -M $(PROJECT_BUILD_PATH)/AndroidManifest.xml -S $(PROJECT_BUILD_PATH)/res -A $(PROJECT_BUILD_PATH)/assets -I $(ANDROID_HOME)/platforms/android-16/android.jar -F $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).unsigned.apk $(PROJECT_BUILD_PATH)/bin - cd $(PROJECT_BUILD_PATH) && $(ANDROID_BUILD_TOOLS)/aapt add bin/$(PROJECT_NAME).unsigned.apk lib/armeabi-v7a/lib$(PROJECT_LIBRARY_NAME).so $(PROJECT_SHARED_LIBS) + $(ANDROID_BUILD_TOOLS)/aapt package -f -M $(PROJECT_BUILD_PATH)/AndroidManifest.xml -S $(PROJECT_BUILD_PATH)/res -A $(PROJECT_BUILD_PATH)/assets -I $(ANDROID_HOME)/platforms/android-$(ANDROID_API_VERSION)/android.jar -F $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).unsigned.apk $(PROJECT_BUILD_PATH)/bin + cd $(PROJECT_BUILD_PATH) && $(ANDROID_BUILD_TOOLS)/aapt add bin/$(PROJECT_NAME).unsigned.apk lib/$(ANDROID_ARCH_NAME)/lib$(PROJECT_LIBRARY_NAME).so $(PROJECT_SHARED_LIBS) # Create signed APK package using generated Key: bin/$(PROJECT_NAME).signed.apk sign_project_apk_package: @@ -253,7 +274,11 @@ zipalign_project_apk_package: # Install $(PROJECT_NAME).apk to default emulator/device # NOTE: Use -e (emulator) or -d (device) parameters if required install: - $(ANDROID_PLATFORM_TOOLS)/adb install -r $(PROJECT_NAME).apk + $(ANDROID_PLATFORM_TOOLS)/adb install --abi $(ANDROID_ARCH_NAME) -rds $(PROJECT_NAME).apk + +# Check supported ABI for the device (armeabi-v7a, arm64-v8a, x86, x86_64) +check_device_abi: + $(ANDROID_PLATFORM_TOOLS)/adb shell getprop ro.product.cpu.abi # Monitorize output log coming from device, only raylib tag logcat: diff --git a/games/koala_seasons/koala_seasons.c b/games/koala_seasons/koala_seasons.c index 214fda4c1..aaad52769 100644 --- a/games/koala_seasons/koala_seasons.c +++ b/games/koala_seasons/koala_seasons.c @@ -1,6 +1,6 @@ /******************************************************************************************* * -* raylib - Koala Seasons game +* Koala Seasons [emegeme 2015] * * Koala Seasons is a runner, you must survive as long as possible jumping from tree to tree * Ready to start the adventure? How long can you survive? @@ -13,7 +13,7 @@ ********************************************************************************************/ #include "raylib.h" -#include "screens/screens.h" // NOTE: Defines currentScreen +#include "screens/screens.h" // NOTE: Defines global variable: currentScreen #if defined(PLATFORM_WEB) #include @@ -22,6 +22,9 @@ //---------------------------------------------------------------------------------- // Global Variables Definition (local to this module) //---------------------------------------------------------------------------------- +static const int screenWidth = 1280; +static const int screenHeight = 720; + static float transAlpha = 0; static bool onTransition = false; static bool transFadeOut = false; @@ -43,17 +46,11 @@ void UpdateDrawFrame(void); // Update and Draw one frame //---------------------------------------------------------------------------------- // Main entry point //---------------------------------------------------------------------------------- -int main(void) { - // Initialization - //--------------------------------------------------------- - const int screenWidth = 1280; - const int screenHeight = 720; - const char windowTitle[30] = "KOALA SEASONS"; - - //SetConfigFlags(FLAG_FULLSCREEN_MODE); - - // Note that windowTitle is ignored on Android - InitWindow(screenWidth, screenHeight, windowTitle); +int main(void) +{ + // Initialization (Note windowTitle is unused on Android) + //--------------------------------------------------------- + InitWindow(screenWidth, screenHeight, "KOALA SEASONS"); // Load global data here (assets that must be available in all screens, i.e. fonts) font = LoadFont("resources/graphics/mainfont.png"); @@ -62,9 +59,9 @@ int main(void) { atlas02 = LoadTexture("resources/graphics/atlas02.png"); #if defined(PLATFORM_WEB) || defined(PLATFORM_RPI) || defined(PLATFORM_ANDROID) - colorBlend = LoadShader("resources/shaders/glsl100/base.vs", "resources/shaders/glsl100/blend_color.fs"); + colorBlend = LoadShader(0, "resources/shaders/glsl100/blend_color.fs"); #else - colorBlend = LoadShader("resources/shaders/glsl330/base.vs", "resources/shaders/glsl330/blend_color.fs"); + colorBlend = LoadShader(0, "resources/shaders/glsl330/blend_color.fs"); #endif InitAudioDevice(); @@ -79,20 +76,14 @@ int main(void) { fxDieDingo = LoadSound("resources/audio/dingo_die.ogg"); fxDieOwl = LoadSound("resources/audio/owl_die.ogg"); - music = LoadMusicStream("resources/audio/jngl.xm"); PlayMusicStream(music); - SetMusicVolume(music, 1.0f); + SetMusicVolume(music, 2.0f); // Define and init first screen // NOTE: currentScreen is defined in screens.h as a global variable currentScreen = TITLE; - - InitLogoScreen(); - //InitOptionsScreen(); InitTitleScreen(); - InitGameplayScreen(); - InitEndingScreen(); #if defined(PLATFORM_WEB) emscripten_set_main_loop(UpdateDrawFrame, 0, 1); @@ -260,9 +251,7 @@ void UpdateDrawFrame(void) } if (onTransition) DrawTransition(); - - DrawFPS(20, GetScreenHeight() - 30); - + DrawRectangle(GetScreenWidth() - 200, GetScreenHeight() - 50, 200, 40, Fade(WHITE, 0.6f)); DrawText("ALPHA VERSION", GetScreenWidth() - 180, GetScreenHeight() - 40, 20, DARKGRAY); diff --git a/games/koala_seasons/screens/screen_gameplay.c b/games/koala_seasons/screens/screen_gameplay.c index 4d8ff04d6..0bbad362d 100644 --- a/games/koala_seasons/screens/screen_gameplay.c +++ b/games/koala_seasons/screens/screen_gameplay.c @@ -38,7 +38,6 @@ //#define DEBUG -// DONE: Review MAX_* limits, don't waste memory!!! #define MAX_ENEMIES 16 #define MAX_BAMBOO 16 #define MAX_LEAVES 14 @@ -96,7 +95,7 @@ //---------------------------------------------------------------------------------- // Types and Structures Definition //---------------------------------------------------------------------------------- -typedef enum { WINTER, SPRING, SUMMER, FALL, TRANSITION} SeasonState; +typedef enum { WINTER, SPRING, SUMMER, FALL, TRANSITION } SeasonState; typedef enum { JUMPING, KICK, FINALFORM, GRABED, ONWIND } KoalaState; typedef struct { @@ -343,7 +342,6 @@ static Rectangle leftButton = {0, 0, 0, 0}; static Rectangle rightButton = {0, 0, 0, 0}; static Rectangle powerButton = {0, 0, 0, 0}; static Rectangle fire[MAX_FIRE]; -//static Rectangle flames[MAX_FLAMES]; static Rectangle ice[MAX_ICE]; static Rectangle resin[MAX_RESIN]; static Rectangle wind[MAX_WIND]; @@ -351,7 +349,7 @@ static Rectangle bamboo[MAX_BAMBOO]; static Rectangle snake[MAX_ENEMIES]; static Rectangle dingo[MAX_ENEMIES]; static Rectangle owl[MAX_ENEMIES]; -static Rectangle leaf[MAX_LEAVES]; // DONE: Review name! +static Rectangle leaf[MAX_LEAVES]; static Rectangle powerBar; static Rectangle backBar; static Rectangle fireAnimation; @@ -387,7 +385,7 @@ static Vector2 textSize; static Vector2 clockPosition; static Particle enemyHit[MAX_ENEMIES]; -static ParticleSystem leafParticles[MAX_LEAVES]; // DONE: Review!!! Creating 40 ParticleSystem!!! -> 40*128 = 5120 Particles! Maybe better create a struct Leaf? +static ParticleSystem leafParticles[MAX_LEAVES]; static ParticleSystem snowParticle; static ParticleSystem backSnowParticle; static ParticleSystem dandelionParticle; @@ -670,7 +668,7 @@ void UpdateGameplayScreen(void) transitionFramesCounter += speedMod*TIME_FACTOR; - if(transitionFramesCounter <= SEASONTRANSITION) + if (transitionFramesCounter <= SEASONTRANSITION) { color00 = ColorTransition(initcolor00, finalcolor00, transitionFramesCounter); color01 = ColorTransition(initcolor01, finalcolor01, transitionFramesCounter); @@ -1043,12 +1041,8 @@ void UpdateGameplayScreen(void) #endif } #if defined(DEBUG) - if (currentLeaves < LEAVESTOTRANSFORM && (IsKeyPressed(KEY_ENTER))) - { - currentLeaves += LEAVESTOTRANSFORM; - } + if ((currentLeaves < LEAVESTOTRANSFORM) && (IsKeyPressed(KEY_ENTER))) currentLeaves += LEAVESTOTRANSFORM; #endif - if (coolDown) { power += 20; @@ -1427,10 +1421,6 @@ void UpdateGameplayScreen(void) if (CheckCollisionRecs(player, leaf[j]) && leafActive[j]) { - //power += 20; - //printf("coin %c", coinType[j]); - - // DONE: Review popupLeaves[j].position = (Vector2){ leaf[j].x, leaf[j].y }; popupLeaves[j].scale = 1.0f; popupLeaves[j].alpha = 1.0f; @@ -1438,25 +1428,25 @@ void UpdateGameplayScreen(void) PlaySound(fxEatLeaves); - if(leafType[j] == 0) + if (leafType[j] == 0) { currentLeaves++; popupLeaves[j].score = 1; } - else if(leafType[j] == 1) + else if (leafType[j] == 1) { currentLeaves += 2; popupLeaves[j].score = 2; } - else if(leafType[j] == 2) + else if (leafType[j] == 2) { currentLeaves += 3; popupLeaves[j].score = 3; } - else if(leafType[j] == 3) + else if (leafType[j] == 3) { currentLeaves += 4; popupLeaves[j].score = 4; @@ -2232,7 +2222,6 @@ void UpdateGameplayScreen(void) player.x -= speed; grabCounter += 1*TIME_FACTOR; - // DONE: Review, before checking collision with ALL enemies, check if they are active! for (int i = 0; i < MAX_ENEMIES; i++) { if (CheckCollisionRecs(player, snake[i]) && !isHitSnake[i] && snakeActive[i]) @@ -2286,7 +2275,6 @@ void UpdateGameplayScreen(void) enemyHit[i].speed = (Vector2){ dingo[i].x, dingo[i].y }; enemyHit[i].size = (float)GetRandomValue(5, 10)/30; enemyHit[i].rotation = 0.0f; - //enemyHit[i].color = (Color){ GetRandomValue(0, 255), GetRandomValue(0, 255), GetRandomValue(0, 255), 255 }; enemyHit[i].alpha = 1.0f; enemyHit[i].active = true; @@ -2317,7 +2305,6 @@ void UpdateGameplayScreen(void) enemyHit[i].speed = (Vector2){ owl[i].x, owl[i].y }; enemyHit[i].size = (float)GetRandomValue(5, 10)/30; enemyHit[i].rotation = 0.0f; - //enemyHit[i].color = (Color){ GetRandomValue(0, 255), GetRandomValue(0, 255), GetRandomValue(0, 255), 255 }; enemyHit[i].alpha = 1.0f; enemyHit[i].active = true; @@ -2392,9 +2379,7 @@ void UpdateGameplayScreen(void) thisFrameKoala = 0; } - //if (curFrameKoala > 1) curFrameKoala = ; - - if(curFrameKoala <= 1 )koalaAnimationTransform.x = gameplay_koala_transform.x + koalaAnimationTransform.width*curFrameKoala; + if (curFrameKoala <= 1) koalaAnimationTransform.x = gameplay_koala_transform.x + koalaAnimationTransform.width*curFrameKoala; if (transAniCounter >= 5) { @@ -2407,8 +2392,7 @@ void UpdateGameplayScreen(void) finalColor = RED; finalColor2 = WHITE; } - - if (!transBackAnim) + else { finalColor = WHITE; finalColor2 = RED; @@ -2420,9 +2404,7 @@ void UpdateGameplayScreen(void) thisFrameKoala = 0; curFrameKoala = 0; speedFX.active = true; - //speedMod = 2; transCount = 0; - //printf ("THIS ISN'T EVEN MY FINAL FORM"); bambooTimer += 15*TIME_FACTOR; } } @@ -2558,7 +2540,7 @@ void UpdateGameplayScreen(void) velocity -= 1*TIME_FACTOR; player.y -= velocity; - if(player.y >= GetScreenHeight()) + if (player.y >= GetScreenHeight()) { deathsCounter++; finishScreen = 1; @@ -2781,7 +2763,7 @@ void DrawGameplayScreen(void) case KICK:DrawTexturePro(atlas01, gameplay_koala_dash, (Rectangle){player.x - player.width, player.y - gameplay_koala_jump.height/4, gameplay_koala_dash.width, gameplay_koala_dash.height}, (Vector2){0, 0}, 0, WHITE); break; case FINALFORM: { - if(transforming)DrawTexturePro(atlas01, koalaAnimationTransform, (Rectangle){player.x - player.width, player.y - gameplay_koala_transform.height/4, gameplay_koala_transform.width/2, gameplay_koala_transform.height}, (Vector2){0, 0}, 0, finalColor); + if (transforming)DrawTexturePro(atlas01, koalaAnimationTransform, (Rectangle){player.x - player.width, player.y - gameplay_koala_transform.height/4, gameplay_koala_transform.width/2, gameplay_koala_transform.height}, (Vector2){0, 0}, 0, finalColor); else DrawTexturePro(atlas01, koalaAnimationFly, (Rectangle){player.x - gameplay_koala_fly.width/3, player.y - gameplay_koala_fly.height/4, gameplay_koala_fly.width/2, gameplay_koala_fly.height}, (Vector2){0, 0}, 0, finalColor);//DrawTextureRec((koalaFly), (Rectangle){0, 0, 128, 128}, (Vector2){player.x - 50, player.y - 40}, WHITE); } break; @@ -3781,7 +3763,7 @@ static void Reset(void) bamboo[i].y = 0; bamboo[i].width = 50; bamboo[i].height = GetScreenHeight(); - if(i > 5) bambooActive[i] = false; + if (i > 5) bambooActive[i] = false; else bambooActive[i] = true; } diff --git a/games/light_my_ritual/Makefile b/games/light_my_ritual/Makefile index 3291bb3e7..7c6a14387 100644 --- a/games/light_my_ritual/Makefile +++ b/games/light_my_ritual/Makefile @@ -24,28 +24,43 @@ .PHONY: all clean # Define required raylib variables -# WARNING: To compile to HTML5, code must be redesigned to use emscripten.h and emscripten_set_main_loop() -PLATFORM ?= PLATFORM_DESKTOP -RAYLIB_PATH ?= ..\.. -PROJECT_NAME ?= light_my_ritual +PROJECT_NAME ?= light_my_ritual +RAYLIB_VERSION ?= 2.5.0 +RAYLIB_API_VERSION ?= 2 +RAYLIB_PATH ?= C:\GitHub\raylib -# Default path for raylib on Raspberry Pi, if installed in different path, update it! -ifeq ($(PLATFORM),PLATFORM_RPI) - RAYLIB_PATH ?= /home/pi/raylib -endif +# Define default options + +# One of PLATFORM_DESKTOP, PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB +PLATFORM ?= PLATFORM_DESKTOP + +# Locations of your newly installed library and associated headers. See ../src/Makefile +# On Linux, if you have installed raylib but cannot compile the examples, check that +# the *_INSTALL_PATH values here are the same as those in src/Makefile or point to known locations. +# To enable system-wide compile-time and runtime linking to libraylib.so, run ../src/$ sudo make install RAYLIB_LIBTYPE_SHARED. +# To enable compile-time linking to a special version of libraylib.so, change these variables here. +# To enable runtime linking to a special version of libraylib.so, see EXAMPLE_RUNTIME_PATH below. +# If there is a libraylib in both EXAMPLE_RUNTIME_PATH and RAYLIB_INSTALL_PATH, at runtime, +# the library at EXAMPLE_RUNTIME_PATH, if present, will take precedence over the one at RAYLIB_INSTALL_PATH. +# RAYLIB_INSTALL_PATH should be the desired full path to libraylib. No relative paths. +DESTDIR ?= /usr/local +RAYLIB_INSTALL_PATH ?= $(DESTDIR)/lib +# RAYLIB_H_INSTALL_PATH locates the installed raylib header and associated source files. +RAYLIB_H_INSTALL_PATH ?= $(DESTDIR)/include # Library type used for raylib: STATIC (.a) or SHARED (.so/.dll) -RAYLIB_LIBTYPE ?= STATIC +RAYLIB_LIBTYPE ?= STATIC + +# Build mode for project: DEBUG or RELEASE +BUILD_MODE ?= RELEASE # Use external GLFW library instead of rglfw module -USE_EXTERNAL_GLFW ?= FALSE +# TODO: Review usage on Linux. Target version of choice. Switch on -lglfw or -lglfw3 +USE_EXTERNAL_GLFW ?= FALSE # Use Wayland display server protocol on Linux desktop # by default it uses X11 windowing system -USE_WAYLAND_DISPLAY ?= FALSE - -# NOTE: On PLATFORM_WEB OpenAL Soft backend is used by default (check raylib/src/Makefile) - +USE_WAYLAND_DISPLAY ?= FALSE # Determine PLATFORM_OS in case PLATFORM_DESKTOP selected ifeq ($(PLATFORM),PLATFORM_DESKTOP) @@ -82,40 +97,50 @@ ifeq ($(PLATFORM),PLATFORM_RPI) endif endif +# RAYLIB_PATH adjustment for different platforms. +# If using GNU make, we can get the full path to the top of the tree. Windows? BSD? +# Required for ldconfig or other tools that do not perform path expansion. +ifeq ($(PLATFORM),PLATFORM_DESKTOP) + ifeq ($(PLATFORM_OS),LINUX) + RAYLIB_PREFIX ?= .. + RAYLIB_PATH = $(realpath $(RAYLIB_PREFIX)) + endif +endif +# Default path for raylib on Raspberry Pi, if installed in different path, update it! +# This is not currently used by src/Makefile. Not sure of its origin or usage. Refer to wiki. +# TODO: update install: target in src/Makefile for RPI, consider relation to LINUX. +ifeq ($(PLATFORM),PLATFORM_RPI) + RAYLIB_PATH ?= /home/pi/raylib +endif + ifeq ($(PLATFORM),PLATFORM_WEB) # Emscripten required variables - EMSDK_PATH = C:/emsdk - EMSCRIPTEN_VERSION = 1.37.28 - CLANG_VERSION=e1.37.28_64bit - PYTHON_VERSION=2.7.5.3_64bit - NODE_VERSION=4.1.1_64bit - export PATH=$(EMSDK_PATH);$(EMSDK_PATH)\clang\$(CLANG_VERSION);$(EMSDK_PATH)\node\$(NODE_VERSION)\bin;$(EMSDK_PATH)\python\$(PYTHON_VERSION);$(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION);C:\raylib\MinGW\bin:$$(PATH) - EMSCRIPTEN=$(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION) + EMSDK_PATH ?= C:/emsdk + EMSCRIPTEN_VERSION ?= 1.38.32 + CLANG_VERSION = e$(EMSCRIPTEN_VERSION)_64bit + PYTHON_VERSION = 2.7.13.1_64bit\python-2.7.13.amd64 + NODE_VERSION = 8.9.1_64bit + export PATH = $(EMSDK_PATH);$(EMSDK_PATH)\clang\$(CLANG_VERSION);$(EMSDK_PATH)\node\$(NODE_VERSION)\bin;$(EMSDK_PATH)\python\$(PYTHON_VERSION);$(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION);C:\raylib\MinGW\bin:$$(PATH) + EMSCRIPTEN = $(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION) endif -RAYLIB_RELEASE_PATH ?= $(RAYLIB_PATH)/release/libs +# Define raylib release directory for compiled library. +# RAYLIB_RELEASE_PATH points to provided binaries or your freshly built version +RAYLIB_RELEASE_PATH ?= $(RAYLIB_PATH)/src -# Define raylib release directory for compiled library -ifeq ($(PLATFORM),PLATFORM_DESKTOP) - ifeq ($(PLATFORM_OS),WINDOWS) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/win32/mingw32 - endif - ifeq ($(PLATFORM_OS),LINUX) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/linux - endif - ifeq ($(PLATFORM_OS),OSX) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/osx - endif - ifeq ($(PLATFORM_OS),BSD) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/bsd - endif -endif -ifeq ($(PLATFORM),PLATFORM_RPI) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/rpi -endif -ifeq ($(PLATFORM),PLATFORM_WEB) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/html5 -endif +# EXAMPLE_RUNTIME_PATH embeds a custom runtime location of libraylib.so or other desired libraries +# into each example binary compiled with RAYLIB_LIBTYPE=SHARED. It defaults to RAYLIB_RELEASE_PATH +# so that these examples link at runtime with your version of libraylib.so in ../release/libs/linux +# without formal installation from ../src/Makefile. It aids portability and is useful if you have +# multiple versions of raylib, have raylib installed to a non-standard location, or want to +# bundle libraylib.so with your game. Change it to your liking. +# NOTE: If, at runtime, there is a libraylib.so at both EXAMPLE_RUNTIME_PATH and RAYLIB_INSTALL_PATH, +# The library at EXAMPLE_RUNTIME_PATH, if present, will take precedence over RAYLIB_INSTALL_PATH, +# Implemented for LINUX below with CFLAGS += -Wl,-rpath,$(EXAMPLE_RUNTIME_PATH) +# To see the result, run readelf -d core/core_basic_window; looking at the RPATH or RUNPATH attribute. +# To see which libraries a built example is linking to, ldd core/core_basic_window; +# Look for libraylib.so.1 => $(RAYLIB_INSTALL_PATH)/libraylib.so.1 or similar listing. +EXAMPLE_RUNTIME_PATH ?= $(RAYLIB_RELEASE_PATH) # Define default C compiler: gcc # NOTE: define g++ compiler if using C++ @@ -140,6 +165,8 @@ ifeq ($(PLATFORM),PLATFORM_RPI) endif ifeq ($(PLATFORM),PLATFORM_WEB) # HTML5 emscripten compiler + # WARNING: To compile to HTML5, code must be redesigned + # to use emscripten.h and emscripten_set_main_loop() CC = emcc endif @@ -154,7 +181,7 @@ endif # Define compiler flags: # -O1 defines optimization level -# -g enable debugging +# -g include debug information on compilation # -s strip unnecessary data from build # -Wall turns on most, but not all, compiler warnings # -std=c99 defines C language mode (standard C from 1999 revision) @@ -163,56 +190,92 @@ endif # -D_DEFAULT_SOURCE use with -std=c99 on Linux and PLATFORM_WEB, required for timespec CFLAGS += -O1 -s -Wall -std=c99 -D_DEFAULT_SOURCE -Wno-missing-braces +ifeq ($(BUILD_MODE),DEBUG) + CFLAGS += -g +endif + # Additional flags for compiler (if desired) #CFLAGS += -Wextra -Wmissing-prototypes -Wstrict-prototypes ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),WINDOWS) - # resources file contains windows exe icon + # resource file contains windows executable icon and properties # -Wl,--subsystem,windows hides the console window CFLAGS += $(RAYLIB_PATH)/raylib.rc.data -Wl,--subsystem,windows endif ifeq ($(PLATFORM_OS),LINUX) - CFLAGS += -D_DEFAULT_SOURCE + ifeq ($(RAYLIB_LIBTYPE),STATIC) + CFLAGS += -D_DEFAULT_SOURCE + endif + ifeq ($(RAYLIB_LIBTYPE),SHARED) + # Explicitly enable runtime link to libraylib.so + CFLAGS += -Wl,-rpath,$(EXAMPLE_RUNTIME_PATH) + endif endif endif ifeq ($(PLATFORM),PLATFORM_RPI) CFLAGS += -std=gnu99 endif ifeq ($(PLATFORM),PLATFORM_WEB) - # -O2 # if used, also set --memory-init-file 0 - # --memory-init-file 0 # to avoid an external memory initialization code file (.mem) - # -s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing + # -Os # size optimization + # -O2 # optimization level 2, if used, also set --memory-init-file 0 + # -s USE_GLFW=3 # Use glfw3 library (context/input management) + # -s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing -> WARNING: Audio buffers could FAIL! # -s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB) # -s USE_PTHREADS=1 # multithreading support - # -s WASM=1 # support Web Assembly (https://github.com/kripken/emscripten/wiki/WebAssembly) + # -s WASM=0 # disable Web Assembly, emitted by default + # -s EMTERPRETIFY=1 # enable emscripten code interpreter (very slow) + # -s EMTERPRETIFY_ASYNC=1 # support synchronous loops by emterpreter + # -s FORCE_FILESYSTEM=1 # force filesystem to load/save files data + # -s ASSERTIONS=1 # enable runtime checks for common memory allocation errors (-O1 and above turn it off) + # --profiling # include information for code profiling + # --memory-init-file 0 # to avoid an external memory initialization code file (.mem) # --preload-file resources # specify a resources folder for data compilation - CFLAGS += -s USE_GLFW=3 -s ASSERTIONS=1 -s WASM=1 --profiling --preload-file resources - + CFLAGS += -Os -s USE_GLFW=3 -s TOTAL_MEMORY=67108864 --preload-file resources + ifeq ($(BUILD_MODE), DEBUG) + CFLAGS += -s ASSERTIONS=1 --profiling + endif + # Define a custom shell .html and output extension - CFLAGS += --shell-file $(RAYLIB_PATH)\templates\web_shell\shell.html + CFLAGS += --shell-file $(RAYLIB_PATH)/src/shell.html EXT = .html endif # Define include paths for required headers # NOTE: Several external required libraries (stb and others) -INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/release/include -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external +INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external # Define additional directories containing required header files ifeq ($(PLATFORM),PLATFORM_RPI) - # RPI requried libraries + # RPI required libraries INCLUDE_PATHS += -I/opt/vc/include INCLUDE_PATHS += -I/opt/vc/include/interface/vmcs_host/linux INCLUDE_PATHS += -I/opt/vc/include/interface/vcos/pthreads endif +ifeq ($(PLATFORM),PLATFORM_DESKTOP) + ifeq ($(PLATFORM_OS),BSD) + # Consider -L$(RAYLIB_H_INSTALL_PATH) + INCLUDE_PATHS += -I/usr/local/include + endif + ifeq ($(PLATFORM_OS),LINUX) + # Reset everything. + # Precedence: immediately local, installed version, raysan5 provided libs -I$(RAYLIB_H_INSTALL_PATH) -I$(RAYLIB_PATH)/release/include + INCLUDE_PATHS = -I$(RAYLIB_H_INSTALL_PATH) -isystem. -isystem$(RAYLIB_PATH)/src -isystem$(RAYLIB_PATH)/release/include -isystem$(RAYLIB_PATH)/src/external + endif +endif -# Define library paths containing required libs -LDFLAGS = -L. -L$(RAYLIB_RELEASE_PATH) -L$(RAYLIB_PATH)/src +# Define library paths containing required libs. +LDFLAGS = -L. -L$(RAYLIB_RELEASE_PATH) -L$(RAYLIB_PATH)/src ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),BSD) - INCLUDE_PATHS += -I/usr/local/include + # Consider -L$(RAYLIB_INSTALL_PATH) LDFLAGS += -L. -Lsrc -L/usr/local/lib endif + ifeq ($(PLATFORM_OS),LINUX) + # Reset everything. + # Precedence: immediately local, installed version, raysan5 provided libs + LDFLAGS = -L. -L$(RAYLIB_INSTALL_PATH) -L$(RAYLIB_RELEASE_PATH) + endif endif ifeq ($(PLATFORM),PLATFORM_RPI) @@ -224,7 +287,10 @@ endif ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),WINDOWS) # Libraries for Windows desktop compilation - LDLIBS = -lraylib -lopengl32 -lgdi32 + # NOTE: WinMM library required to set high-res timer resolution + LDLIBS = -lraylib -lopengl32 -lgdi32 -lwinmm + # Required for physac examples + #LDLIBS += -static -lpthread endif ifeq ($(PLATFORM_OS),LINUX) # Libraries for Debian GNU/Linux desktop compiling @@ -240,6 +306,10 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(USE_WAYLAND_DISPLAY),TRUE) LDLIBS += -lwayland-client -lwayland-cursor -lwayland-egl -lxkbcommon endif + # Explicit link to libc + ifeq ($(RAYLIB_LIBTYPE),SHARED) + LDLIBS += -lc + endif endif ifeq ($(PLATFORM_OS),OSX) # Libraries for OSX 10.9 desktop compiling @@ -270,10 +340,11 @@ ifeq ($(PLATFORM),PLATFORM_WEB) endif # Define all source files required -PROJECT_SOURCE_FILES ?= light_my_ritual.c \ - screens/screen_logo_raylib.c \ - screens/screen_title.c \ - screens/screen_gameplay.c +PROJECT_SOURCE_FILES ?= \ + light_my_ritual.c \ + screens/screen_logo_raylib.c \ + screens/screen_title.c \ + screens/screen_gameplay.c # Define all object files from source files OBJS = $(patsubst %.c, %.o, $(PROJECT_SOURCE_FILES)) @@ -308,7 +379,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) del *.o *.exe /s endif ifeq ($(PLATFORM_OS),LINUX) - find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -f + find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -fv endif ifeq ($(PLATFORM_OS),OSX) find . -type f -perm +ugo+x -delete @@ -317,7 +388,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) endif ifeq ($(PLATFORM),PLATFORM_RPI) find . -type f -executable -delete - rm -f *.o + rm -fv *.o endif ifeq ($(PLATFORM),PLATFORM_WEB) del *.o *.html *.js diff --git a/games/light_my_ritual/Makefile.Android b/games/light_my_ritual/Makefile.Android index f082ab230..29d437b1b 100644 --- a/games/light_my_ritual/Makefile.Android +++ b/games/light_my_ritual/Makefile.Android @@ -22,24 +22,33 @@ #************************************************************************************************** # Define required raylib variables -PLATFORM ?= PLATFORM_ANDROID -RAYLIB_PATH ?= ..\.. +PLATFORM ?= PLATFORM_ANDROID +RAYLIB_PATH ?= ..\.. + +# Define Android architecture (armeabi-v7a, arm64-v8a, x86, x86-64) and API version +ANDROID_ARCH ?= ARM +ANDROID_API_VERSION = 21 +ifeq ($(ANDROID_ARCH),ARM) + ANDROID_ARCH_NAME = armeabi-v7a +endif +ifeq ($(ANDROID_ARCH),ARM64) + ANDROID_ARCH_NAME = arm64-v8a +endif # Required path variables # NOTE: JAVA_HOME must be set to JDK -ANDROID_HOME = C:/android-sdk -ANDROID_NDK = C:/android-ndk -ANDROID_TOOLCHAIN = C:/android_toolchain_arm_api16 -ANDROID_BUILD_TOOLS = $(ANDROID_HOME)/build-tools/26.0.2 -ANDROID_PLATFORM_TOOLS = $(ANDROID_HOME)/platform-tools -JAVA_HOME = C:/PROGRA~1/Java/jdk1.8.0_144 +JAVA_HOME ?= C:/JavaJDK +ANDROID_HOME = C:/android-sdk +ANDROID_TOOLCHAIN = C:/android_toolchain_$(ANDROID_ARCH)_API$(ANDROID_API_VERSION) +ANDROID_BUILD_TOOLS = $(ANDROID_HOME)/build-tools/28.0.1 +ANDROID_PLATFORM_TOOLS = $(ANDROID_HOME)/platform-tools # Android project configuration variables -PROJECT_NAME ?= raylib_game -PROJECT_LIBRARY_NAME ?= main -PROJECT_BUILD_PATH ?= android.$(PROJECT_NAME) +PROJECT_NAME ?= raylib_game +PROJECT_LIBRARY_NAME ?= main +PROJECT_BUILD_PATH ?= android.$(PROJECT_NAME) PROJECT_RESOURCES_PATH ?= resources -PROJECT_SOURCE_FILES ?= raylib_game.c +PROJECT_SOURCE_FILES ?= raylib_game.c # Some source files are placed in directories, when compiling to some # output directory other than source, that directory must pre-exist. @@ -61,30 +70,43 @@ APP_KEYSTORE_PASS ?= raylib # Library type used for raylib: STATIC (.a) or SHARED (.so/.dll) RAYLIB_LIBTYPE ?= STATIC -RAYLIB_LIB_PATH = $(RAYLIB_PATH)\release\libs\android\armeabi-v7a + +# Library path for libraylib.a/libraylib.so +RAYLIB_LIB_PATH = $(RAYLIB_PATH)\src # Shared libs must be added to APK if required # NOTE: Generated NativeLoader.java automatically load those libraries ifeq ($(RAYLIB_LIBTYPE),SHARED) - PROJECT_SHARED_LIBS = lib/armeabi-v7a/libraylib.so + PROJECT_SHARED_LIBS = lib/$(ANDROID_ARCH_NAME)/libraylib.so endif # Compiler and archiver -# NOTE: GCC is being deprectated in Android NDK r16 -CC = $(ANDROID_TOOLCHAIN)/bin/arm-linux-androideabi-gcc -AR = $(ANDROID_TOOLCHAIN)/bin/arm-linux-androideabi-ar +# NOTE: GCC is being deprecated in Android NDK r16 +ifeq ($(ANDROID_ARCH),ARM) + CC = $(ANDROID_TOOLCHAIN)/bin/arm-linux-androideabi-clang + AR = $(ANDROID_TOOLCHAIN)/bin/arm-linux-androideabi-ar +endif +ifeq ($(ANDROID_ARCH),ARM64) + CC = $(ANDROID_TOOLCHAIN)/bin/aarch64-linux-android-clang + AR = $(ANDROID_TOOLCHAIN)/bin/aarch64-linux-android-ar +endif # Compiler flags for arquitecture -CFLAGS = -std=c99 -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 +ifeq ($(ANDROID_ARCH),ARM) + CFLAGS = -std=c99 -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 +endif +ifeq ($(ANDROID_ARCH),ARM64) + CFLAGS = -std=c99 -target aarch64 -mfix-cortex-a53-835769 +endif # Compilation functions attributes options CFLAGS += -ffunction-sections -funwind-tables -fstack-protector-strong -fPIC # Compiler options for the linker CFLAGS += -Wall -Wa,--noexecstack -Wformat -Werror=format-security -no-canonical-prefixes # Preprocessor macro definitions -CFLAGS += -DANDROID -DPLATFORM_ANDROID -D__ANDROID_API__=16 +CFLAGS += -DANDROID -DPLATFORM_ANDROID -D__ANDROID_API__=$(ANDROID_API_VERSION) # Paths containing required header files -INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/release/include -I$(RAYLIB_PATH)/src/external/android/native_app_glue +INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external/android/native_app_glue # Linker options LDFLAGS = -Wl,-soname,lib$(PROJECT_LIBRARY_NAME).so -Wl,--exclude-libs,libatomic.a @@ -92,11 +114,11 @@ LDFLAGS += -Wl,--build-id -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,relro -Wl # Force linking of library module to define symbol LDFLAGS += -u ANativeActivity_onCreate # Library paths containing required libs -LDFLAGS += -L. -L$(PROJECT_BUILD_PATH)/obj -L$(PROJECT_BUILD_PATH)/lib/armeabi-v7a +LDFLAGS += -L. -L$(PROJECT_BUILD_PATH)/obj -L$(PROJECT_BUILD_PATH)/lib/$(ANDROID_ARCH_NAME) -L$(ANDROID_TOOLCHAIN)\sysroot\usr\lib # Define any libraries to link into executable # if you want to link libraries (libname.so or libname.a), use the -lname -LDLIBS = -lraylib -lnative_app_glue -llog -landroid -lEGL -lGLESv2 -lOpenSLES -latomic -lc -lm -ldl +LDLIBS = -lm -lc -lraylib -llog -landroid -lEGL -lGLESv2 -lOpenSLES -ldl # Generate target objects list from PROJECT_SOURCE_FILES OBJS = $(patsubst %.c, $(PROJECT_BUILD_PATH)/obj/%.o, $(PROJECT_SOURCE_FILES)) @@ -110,7 +132,6 @@ all: create_temp_project_dirs \ generate_android_manifest \ generate_apk_keystore \ config_project_package \ - compile_native_app_glue \ compile_project_code \ compile_project_class \ compile_project_class_dex \ @@ -127,7 +148,7 @@ create_temp_project_dirs: if not exist $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME) mkdir $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME) if not exist $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME)\$(APP_PRODUCT_NAME) mkdir $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME)\$(APP_PRODUCT_NAME) if not exist $(PROJECT_BUILD_PATH)\lib mkdir $(PROJECT_BUILD_PATH)\lib - if not exist $(PROJECT_BUILD_PATH)\lib\armeabi-v7a mkdir $(PROJECT_BUILD_PATH)\lib\armeabi-v7a + if not exist $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME) mkdir $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME) if not exist $(PROJECT_BUILD_PATH)\bin mkdir $(PROJECT_BUILD_PATH)\bin if not exist $(PROJECT_BUILD_PATH)\res mkdir $(PROJECT_BUILD_PATH)\res if not exist $(PROJECT_BUILD_PATH)\res\drawable-ldpi mkdir $(PROJECT_BUILD_PATH)\res\drawable-ldpi @@ -147,10 +168,10 @@ endef # NOTE: If using shared libs they are loaded by generated NativeLoader.java copy_project_required_libs: ifeq ($(RAYLIB_LIBTYPE),SHARED) - copy /Y $(RAYLIB_LIB_PATH)\libraylib.so $(PROJECT_BUILD_PATH)\lib\armeabi-v7a\libraylib.so + copy /Y $(RAYLIB_LIB_PATH)\libraylib.so $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME)\libraylib.so endif ifeq ($(RAYLIB_LIBTYPE),STATIC) - copy /Y $(RAYLIB_LIB_PATH)\libraylib.a $(PROJECT_BUILD_PATH)\lib\armeabi-v7a\libraylib.a + copy /Y $(RAYLIB_LIB_PATH)\libraylib.a $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME)\libraylib.a endif # Copy project required resources: strings.xml, icon.png, assets @@ -185,7 +206,7 @@ generate_android_manifest: @echo ^> $(PROJECT_BUILD_PATH)/AndroidManifest.xml @echo package="com.$(APP_COMPANY_NAME).$(APP_PRODUCT_NAME)" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml @echo android:versionCode="$(APP_VERSION_CODE)" android:versionName="$(APP_VERSION_NAME)" ^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml - @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml @echo ^> $(PROJECT_BUILD_PATH)/AndroidManifest.xml @@ -210,7 +231,7 @@ generate_apk_keystore: # Config project package and resource using AndroidManifest.xml and res/values/strings.xml # NOTE: Generates resources file: src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/R.java config_project_package: - $(ANDROID_BUILD_TOOLS)/aapt package -f -m -S $(PROJECT_BUILD_PATH)/res -J $(PROJECT_BUILD_PATH)/src -M $(PROJECT_BUILD_PATH)/AndroidManifest.xml -I $(ANDROID_HOME)/platforms/android-16/android.jar + $(ANDROID_BUILD_TOOLS)/aapt package -f -m -S $(PROJECT_BUILD_PATH)/res -J $(PROJECT_BUILD_PATH)/src -M $(PROJECT_BUILD_PATH)/AndroidManifest.xml -I $(ANDROID_HOME)/platforms/android-$(ANDROID_API_VERSION)/android.jar # Compile native_app_glue code as static library: obj/libnative_app_glue.a compile_native_app_glue: @@ -219,7 +240,7 @@ compile_native_app_glue: # Compile project code into a shared library: lib/lib$(PROJECT_LIBRARY_NAME).so compile_project_code: $(OBJS) - $(CC) -o $(PROJECT_BUILD_PATH)/lib/armeabi-v7a/lib$(PROJECT_LIBRARY_NAME).so $(OBJS) -shared $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) + $(CC) -o $(PROJECT_BUILD_PATH)/lib/$(ANDROID_ARCH_NAME)/lib$(PROJECT_LIBRARY_NAME).so $(OBJS) -shared $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) # Compile all .c files required into object (.o) files # NOTE: Those files will be linked into a shared library @@ -228,7 +249,7 @@ $(PROJECT_BUILD_PATH)/obj/%.o:%.c # Compile project .java code into .class (Java bytecode) compile_project_class: - $(JAVA_HOME)/bin/javac -verbose -source 1.7 -target 1.7 -d $(PROJECT_BUILD_PATH)/obj -bootclasspath $(JAVA_HOME)/jre/lib/rt.jar -classpath $(ANDROID_HOME)/platforms/android-16/android.jar;$(PROJECT_BUILD_PATH)/obj -sourcepath $(PROJECT_BUILD_PATH)/src $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/R.java $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java + $(JAVA_HOME)/bin/javac -verbose -source 1.7 -target 1.7 -d $(PROJECT_BUILD_PATH)/obj -bootclasspath $(JAVA_HOME)/jre/lib/rt.jar -classpath $(ANDROID_HOME)/platforms/android-$(ANDROID_API_VERSION)/android.jar;$(PROJECT_BUILD_PATH)/obj -sourcepath $(PROJECT_BUILD_PATH)/src $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/R.java $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java # Compile .class files into Dalvik executable bytecode (.dex) # NOTE: Since Android 5.0, Dalvik interpreter (JIT) has been replaced by ART (AOT) @@ -239,8 +260,8 @@ compile_project_class_dex: # NOTE: Requires compiled classes.dex and lib$(PROJECT_LIBRARY_NAME).so # NOTE: Use -A resources to define additional directory in which to find raw asset files create_project_apk_package: - $(ANDROID_BUILD_TOOLS)/aapt package -f -M $(PROJECT_BUILD_PATH)/AndroidManifest.xml -S $(PROJECT_BUILD_PATH)/res -A $(PROJECT_BUILD_PATH)/assets -I $(ANDROID_HOME)/platforms/android-16/android.jar -F $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).unsigned.apk $(PROJECT_BUILD_PATH)/bin - cd $(PROJECT_BUILD_PATH) && $(ANDROID_BUILD_TOOLS)/aapt add bin/$(PROJECT_NAME).unsigned.apk lib/armeabi-v7a/lib$(PROJECT_LIBRARY_NAME).so $(PROJECT_SHARED_LIBS) + $(ANDROID_BUILD_TOOLS)/aapt package -f -M $(PROJECT_BUILD_PATH)/AndroidManifest.xml -S $(PROJECT_BUILD_PATH)/res -A $(PROJECT_BUILD_PATH)/assets -I $(ANDROID_HOME)/platforms/android-$(ANDROID_API_VERSION)/android.jar -F $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).unsigned.apk $(PROJECT_BUILD_PATH)/bin + cd $(PROJECT_BUILD_PATH) && $(ANDROID_BUILD_TOOLS)/aapt add bin/$(PROJECT_NAME).unsigned.apk lib/$(ANDROID_ARCH_NAME)/lib$(PROJECT_LIBRARY_NAME).so $(PROJECT_SHARED_LIBS) # Create signed APK package using generated Key: bin/$(PROJECT_NAME).signed.apk sign_project_apk_package: @@ -253,7 +274,11 @@ zipalign_project_apk_package: # Install $(PROJECT_NAME).apk to default emulator/device # NOTE: Use -e (emulator) or -d (device) parameters if required install: - $(ANDROID_PLATFORM_TOOLS)/adb install -r $(PROJECT_NAME).apk + $(ANDROID_PLATFORM_TOOLS)/adb install --abi $(ANDROID_ARCH_NAME) -rds $(PROJECT_NAME).apk + +# Check supported ABI for the device (armeabi-v7a, arm64-v8a, x86, x86_64) +check_device_abi: + $(ANDROID_PLATFORM_TOOLS)/adb shell getprop ro.product.cpu.abi # Monitorize output log coming from device, only raylib tag logcat: diff --git a/games/light_my_ritual/light_my_ritual.c b/games/light_my_ritual/light_my_ritual.c index ece51997b..73e40485e 100644 --- a/games/light_my_ritual/light_my_ritual.c +++ b/games/light_my_ritual/light_my_ritual.c @@ -1,16 +1,16 @@ /******************************************************************************************* * -* GLOBAL GAME JAM 2016 - LIGHT MY RITUAL! +* LIGHT MY RITUAL [GLOBAL GAME JAM 2016] * * Preparing a ritual session is not that easy. * You must light all the candles before the astral alignment finishes... * but dark creatures move in the shadows to put out all your lights! * Be fast! Be smart! Light my ritual! * -* This game has been created using raylib (www.raylib.com) +* This game has been created using raylib 1.6 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * -* Copyright (c) 2015 Ramon Santamaria (@raysan5) +* Copyright (c) 2016 Ramon Santamaria (@raysan5) * ********************************************************************************************/ @@ -53,9 +53,9 @@ void UpdateDrawFrame(void); // Update and Draw one frame //---------------------------------------------------------------------------------- int main(void) { - // Initialization (Note windowTitle is unused on Android) - //--------------------------------------------------------- - InitWindow(screenWidth, screenHeight, "GGJ16 - LIGHT MY RITUAL!"); + // Initialization (Note windowTitle is unused on Android) + //--------------------------------------------------------- + InitWindow(screenWidth, screenHeight, "LIGHT MY RITUAL! [GGJ16]"); // Global data loading (assets that must be available in all screens, i.e. fonts) InitAudioDevice(); @@ -69,7 +69,7 @@ int main(void) UnloadImage(image); // Unload image from CPU memory (RAM) font = LoadFont("resources/font_arcadian.png"); - //doors = LoadTexture("resources/textures/doors.png"); + //doors = LoadTexture("resources/textures/doors.png"); //sndDoor = LoadSound("resources/audio/door.ogg"); music = LoadMusicStream("resources/audio/ambient.ogg"); @@ -270,7 +270,7 @@ void UpdateDrawFrame(void) case GAMEPLAY: DrawGameplayScreen(); break; default: break; } - + if (onTransition) DrawTransition(); //DrawFPS(10, 10); diff --git a/games/missile_commander.c b/games/missile_commander.c index 15e06f6d5..0d7886c70 100644 --- a/games/missile_commander.c +++ b/games/missile_commander.c @@ -92,11 +92,11 @@ static bool gameOver = false; static bool pause = false; static int score = 0; -static Missile missile[MAX_MISSILES]; -static Interceptor interceptor[MAX_INTERCEPTORS]; -static Explosion explosion[MAX_EXPLOSIONS]; -static Launcher launcher[LAUNCHERS_AMOUNT]; -static Building building[BUILDINGS_AMOUNT]; +static Missile missile[MAX_MISSILES] = { 0 }; +static Interceptor interceptor[MAX_INTERCEPTORS] = { 0 }; +static Explosion explosion[MAX_EXPLOSIONS] = { 0 }; +static Launcher launcher[LAUNCHERS_AMOUNT] = { 0 }; +static Building building[BUILDINGS_AMOUNT] = { 0 }; static int explosionIndex = 0; //------------------------------------------------------------------------------------ @@ -126,7 +126,6 @@ int main(void) #if defined(PLATFORM_WEB) emscripten_set_main_loop(UpdateDrawFrame, 0, 1); #else - SetTargetFPS(60); //-------------------------------------------------------------------------------------- @@ -139,7 +138,6 @@ int main(void) //---------------------------------------------------------------------------------- } #endif - // De-Initialization //-------------------------------------------------------------------------------------- UnloadGame(); // Unload loaded data (textures, sounds, models...) @@ -436,7 +434,7 @@ void DrawGame(void) } // Draw score - DrawText(FormatText("SCORE %4i", score), 20, 20, 40, LIGHTGRAY); + DrawText(TextFormat("SCORE %4i", score), 20, 20, 40, LIGHTGRAY); if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); } @@ -504,7 +502,7 @@ static void UpdateIncomingFire() static int missileIndex = 0; // Launch missile - if (framesCounter % MISSILE_LAUNCH_FRAMES == 0) + if (framesCounter%MISSILE_LAUNCH_FRAMES == 0) { float module; float sideX; diff --git a/games/pang.c b/games/pang.c index a81f32f01..20c4093e9 100644 --- a/games/pang.c +++ b/games/pang.c @@ -32,7 +32,6 @@ //---------------------------------------------------------------------------------- // Types and Structures Definition //---------------------------------------------------------------------------------- - typedef struct Player { Vector2 position; Vector2 speed; @@ -66,33 +65,33 @@ typedef struct Points { //------------------------------------------------------------------------------------ // Global Variables Declaration //------------------------------------------------------------------------------------ -static int screenWidth = 800; -static int screenHeight = 450; +static const int screenWidth = 800; +static const int screenHeight = 450; -static int framesCounter; -static bool gameOver; -static bool pause; -static int score; +static int framesCounter = 0; +static bool gameOver = false; +static bool pause = false; +static int score = 0; -static Player player; -static Shoot shoot[PLAYER_MAX_SHOOTS]; -static Ball bigBalls[MAX_BIG_BALLS]; -static Ball mediumBalls[MAX_BIG_BALLS*2]; -static Ball smallBalls[MAX_BIG_BALLS*4]; -static Points points[5]; +static Player player = { 0 }; +static Shoot shoot[PLAYER_MAX_SHOOTS] = { 0 }; +static Ball bigBalls[MAX_BIG_BALLS] = { 0 }; +static Ball mediumBalls[MAX_BIG_BALLS*2] = { 0 }; +static Ball smallBalls[MAX_BIG_BALLS*4] = { 0 }; +static Points points[5] = { 0 }; // NOTE: Defined triangle is isosceles with common angles of 70 degrees. -static float shipHeight; -static float gravity; +static float shipHeight = 0.0f; +static float gravity = 0.0f; -static int countmediumBallss; -static int countsmallBallss; -static int meteorsDestroyed; -static Vector2 linePosition; +static int countmediumBallss = 0; +static int countsmallBallss = 0; +static int meteorsDestroyed = 0; +static Vector2 linePosition = { 0 }; -static bool victory; -static bool lose; -static bool awake; +static bool victory = false; +static bool lose = false; +static bool awake = false; //------------------------------------------------------------------------------------ // Module Functions Declaration (local) @@ -117,7 +116,6 @@ int main(void) #if defined(PLATFORM_WEB) emscripten_set_main_loop(UpdateDrawFrame, 0, 1); #else - SetTargetFPS(60); //-------------------------------------------------------------------------------------- @@ -130,7 +128,6 @@ int main(void) //---------------------------------------------------------------------------------- } #endif - // De-Initialization //-------------------------------------------------------------------------------------- UnloadGame(); // Unload loaded data (textures, sounds, models...) @@ -593,12 +590,12 @@ void DrawGame(void) { if (points[z].alpha > 0.0f) { - DrawText(FormatText("+%02i", points[z].value), points[z].position.x, points[z].position.y, 20, Fade(BLUE, points[z].alpha)); + DrawText(TextFormat("+%02i", points[z].value), points[z].position.x, points[z].position.y, 20, Fade(BLUE, points[z].alpha)); } } // Draw score (UI) - DrawText(FormatText("SCORE: %i", score), 10, 10, 20, LIGHTGRAY); + DrawText(TextFormat("SCORE: %i", score), 10, 10, 20, LIGHTGRAY); if (victory) { diff --git a/games/skully_escape/Makefile b/games/skully_escape/Makefile index 4673a549e..c785eb280 100644 --- a/games/skully_escape/Makefile +++ b/games/skully_escape/Makefile @@ -24,28 +24,43 @@ .PHONY: all clean # Define required raylib variables -# WARNING: To compile to HTML5, code must be redesigned to use emscripten.h and emscripten_set_main_loop() -PLATFORM ?= PLATFORM_DESKTOP -RAYLIB_PATH ?= ..\.. -PROJECT_NAME ?= skully_escape +PROJECT_NAME ?= skully_escape +RAYLIB_VERSION ?= 2.5.0 +RAYLIB_API_VERSION ?= 2 +RAYLIB_PATH ?= C:\GitHub\raylib -# Default path for raylib on Raspberry Pi, if installed in different path, update it! -ifeq ($(PLATFORM),PLATFORM_RPI) - RAYLIB_PATH ?= /home/pi/raylib -endif +# Define default options + +# One of PLATFORM_DESKTOP, PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB +PLATFORM ?= PLATFORM_DESKTOP + +# Locations of your newly installed library and associated headers. See ../src/Makefile +# On Linux, if you have installed raylib but cannot compile the examples, check that +# the *_INSTALL_PATH values here are the same as those in src/Makefile or point to known locations. +# To enable system-wide compile-time and runtime linking to libraylib.so, run ../src/$ sudo make install RAYLIB_LIBTYPE_SHARED. +# To enable compile-time linking to a special version of libraylib.so, change these variables here. +# To enable runtime linking to a special version of libraylib.so, see EXAMPLE_RUNTIME_PATH below. +# If there is a libraylib in both EXAMPLE_RUNTIME_PATH and RAYLIB_INSTALL_PATH, at runtime, +# the library at EXAMPLE_RUNTIME_PATH, if present, will take precedence over the one at RAYLIB_INSTALL_PATH. +# RAYLIB_INSTALL_PATH should be the desired full path to libraylib. No relative paths. +DESTDIR ?= /usr/local +RAYLIB_INSTALL_PATH ?= $(DESTDIR)/lib +# RAYLIB_H_INSTALL_PATH locates the installed raylib header and associated source files. +RAYLIB_H_INSTALL_PATH ?= $(DESTDIR)/include # Library type used for raylib: STATIC (.a) or SHARED (.so/.dll) -RAYLIB_LIBTYPE ?= STATIC +RAYLIB_LIBTYPE ?= STATIC + +# Build mode for project: DEBUG or RELEASE +BUILD_MODE ?= RELEASE # Use external GLFW library instead of rglfw module -USE_EXTERNAL_GLFW ?= FALSE +# TODO: Review usage on Linux. Target version of choice. Switch on -lglfw or -lglfw3 +USE_EXTERNAL_GLFW ?= FALSE # Use Wayland display server protocol on Linux desktop # by default it uses X11 windowing system -USE_WAYLAND_DISPLAY ?= FALSE - -# NOTE: On PLATFORM_WEB OpenAL Soft backend is used by default (check raylib/src/Makefile) - +USE_WAYLAND_DISPLAY ?= FALSE # Determine PLATFORM_OS in case PLATFORM_DESKTOP selected ifeq ($(PLATFORM),PLATFORM_DESKTOP) @@ -82,40 +97,50 @@ ifeq ($(PLATFORM),PLATFORM_RPI) endif endif +# RAYLIB_PATH adjustment for different platforms. +# If using GNU make, we can get the full path to the top of the tree. Windows? BSD? +# Required for ldconfig or other tools that do not perform path expansion. +ifeq ($(PLATFORM),PLATFORM_DESKTOP) + ifeq ($(PLATFORM_OS),LINUX) + RAYLIB_PREFIX ?= .. + RAYLIB_PATH = $(realpath $(RAYLIB_PREFIX)) + endif +endif +# Default path for raylib on Raspberry Pi, if installed in different path, update it! +# This is not currently used by src/Makefile. Not sure of its origin or usage. Refer to wiki. +# TODO: update install: target in src/Makefile for RPI, consider relation to LINUX. +ifeq ($(PLATFORM),PLATFORM_RPI) + RAYLIB_PATH ?= /home/pi/raylib +endif + ifeq ($(PLATFORM),PLATFORM_WEB) # Emscripten required variables - EMSDK_PATH = C:/emsdk - EMSCRIPTEN_VERSION = 1.37.28 - CLANG_VERSION=e1.37.28_64bit - PYTHON_VERSION=2.7.5.3_64bit - NODE_VERSION=4.1.1_64bit - export PATH=$(EMSDK_PATH);$(EMSDK_PATH)\clang\$(CLANG_VERSION);$(EMSDK_PATH)\node\$(NODE_VERSION)\bin;$(EMSDK_PATH)\python\$(PYTHON_VERSION);$(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION);C:\raylib\MinGW\bin:$$(PATH) - EMSCRIPTEN=$(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION) + EMSDK_PATH ?= C:/emsdk + EMSCRIPTEN_VERSION ?= 1.38.32 + CLANG_VERSION = e$(EMSCRIPTEN_VERSION)_64bit + PYTHON_VERSION = 2.7.13.1_64bit\python-2.7.13.amd64 + NODE_VERSION = 8.9.1_64bit + export PATH = $(EMSDK_PATH);$(EMSDK_PATH)\clang\$(CLANG_VERSION);$(EMSDK_PATH)\node\$(NODE_VERSION)\bin;$(EMSDK_PATH)\python\$(PYTHON_VERSION);$(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION);C:\raylib\MinGW\bin:$$(PATH) + EMSCRIPTEN = $(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION) endif -RAYLIB_RELEASE_PATH ?= $(RAYLIB_PATH)/release/libs +# Define raylib release directory for compiled library. +# RAYLIB_RELEASE_PATH points to provided binaries or your freshly built version +RAYLIB_RELEASE_PATH ?= $(RAYLIB_PATH)/src -# Define raylib release directory for compiled library -ifeq ($(PLATFORM),PLATFORM_DESKTOP) - ifeq ($(PLATFORM_OS),WINDOWS) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/win32/mingw32 - endif - ifeq ($(PLATFORM_OS),LINUX) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/linux - endif - ifeq ($(PLATFORM_OS),OSX) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/osx - endif - ifeq ($(PLATFORM_OS),BSD) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/bsd - endif -endif -ifeq ($(PLATFORM),PLATFORM_RPI) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/rpi -endif -ifeq ($(PLATFORM),PLATFORM_WEB) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/html5 -endif +# EXAMPLE_RUNTIME_PATH embeds a custom runtime location of libraylib.so or other desired libraries +# into each example binary compiled with RAYLIB_LIBTYPE=SHARED. It defaults to RAYLIB_RELEASE_PATH +# so that these examples link at runtime with your version of libraylib.so in ../release/libs/linux +# without formal installation from ../src/Makefile. It aids portability and is useful if you have +# multiple versions of raylib, have raylib installed to a non-standard location, or want to +# bundle libraylib.so with your game. Change it to your liking. +# NOTE: If, at runtime, there is a libraylib.so at both EXAMPLE_RUNTIME_PATH and RAYLIB_INSTALL_PATH, +# The library at EXAMPLE_RUNTIME_PATH, if present, will take precedence over RAYLIB_INSTALL_PATH, +# Implemented for LINUX below with CFLAGS += -Wl,-rpath,$(EXAMPLE_RUNTIME_PATH) +# To see the result, run readelf -d core/core_basic_window; looking at the RPATH or RUNPATH attribute. +# To see which libraries a built example is linking to, ldd core/core_basic_window; +# Look for libraylib.so.1 => $(RAYLIB_INSTALL_PATH)/libraylib.so.1 or similar listing. +EXAMPLE_RUNTIME_PATH ?= $(RAYLIB_RELEASE_PATH) # Define default C compiler: gcc # NOTE: define g++ compiler if using C++ @@ -140,6 +165,8 @@ ifeq ($(PLATFORM),PLATFORM_RPI) endif ifeq ($(PLATFORM),PLATFORM_WEB) # HTML5 emscripten compiler + # WARNING: To compile to HTML5, code must be redesigned + # to use emscripten.h and emscripten_set_main_loop() CC = emcc endif @@ -154,7 +181,7 @@ endif # Define compiler flags: # -O1 defines optimization level -# -g enable debugging +# -g include debug information on compilation # -s strip unnecessary data from build # -Wall turns on most, but not all, compiler warnings # -std=c99 defines C language mode (standard C from 1999 revision) @@ -163,56 +190,92 @@ endif # -D_DEFAULT_SOURCE use with -std=c99 on Linux and PLATFORM_WEB, required for timespec CFLAGS += -O1 -s -Wall -std=c99 -D_DEFAULT_SOURCE -Wno-missing-braces +ifeq ($(BUILD_MODE),DEBUG) + CFLAGS += -g +endif + # Additional flags for compiler (if desired) #CFLAGS += -Wextra -Wmissing-prototypes -Wstrict-prototypes ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),WINDOWS) - # resources file contains windows exe icon + # resource file contains windows executable icon and properties # -Wl,--subsystem,windows hides the console window CFLAGS += $(RAYLIB_PATH)/raylib.rc.data -Wl,--subsystem,windows endif ifeq ($(PLATFORM_OS),LINUX) - CFLAGS += -D_DEFAULT_SOURCE + ifeq ($(RAYLIB_LIBTYPE),STATIC) + CFLAGS += -D_DEFAULT_SOURCE + endif + ifeq ($(RAYLIB_LIBTYPE),SHARED) + # Explicitly enable runtime link to libraylib.so + CFLAGS += -Wl,-rpath,$(EXAMPLE_RUNTIME_PATH) + endif endif endif ifeq ($(PLATFORM),PLATFORM_RPI) CFLAGS += -std=gnu99 endif ifeq ($(PLATFORM),PLATFORM_WEB) - # -O2 # if used, also set --memory-init-file 0 - # --memory-init-file 0 # to avoid an external memory initialization code file (.mem) - # -s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing + # -Os # size optimization + # -O2 # optimization level 2, if used, also set --memory-init-file 0 + # -s USE_GLFW=3 # Use glfw3 library (context/input management) + # -s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing -> WARNING: Audio buffers could FAIL! # -s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB) # -s USE_PTHREADS=1 # multithreading support - # -s WASM=1 # support Web Assembly (https://github.com/kripken/emscripten/wiki/WebAssembly) + # -s WASM=0 # disable Web Assembly, emitted by default + # -s EMTERPRETIFY=1 # enable emscripten code interpreter (very slow) + # -s EMTERPRETIFY_ASYNC=1 # support synchronous loops by emterpreter + # -s FORCE_FILESYSTEM=1 # force filesystem to load/save files data + # -s ASSERTIONS=1 # enable runtime checks for common memory allocation errors (-O1 and above turn it off) + # --profiling # include information for code profiling + # --memory-init-file 0 # to avoid an external memory initialization code file (.mem) # --preload-file resources # specify a resources folder for data compilation - CFLAGS += -s USE_GLFW=3 -s ASSERTIONS=1 -s WASM=1 --profiling --preload-file resources - + CFLAGS += -Os -s USE_GLFW=3 -s TOTAL_MEMORY=67108864 --preload-file resources + ifeq ($(BUILD_MODE), DEBUG) + CFLAGS += -s ASSERTIONS=1 --profiling + endif + # Define a custom shell .html and output extension - CFLAGS += --shell-file $(RAYLIB_PATH)\templates\web_shell\shell.html + CFLAGS += --shell-file $(RAYLIB_PATH)/src/shell.html EXT = .html endif # Define include paths for required headers # NOTE: Several external required libraries (stb and others) -INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/release/include -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external +INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external # Define additional directories containing required header files ifeq ($(PLATFORM),PLATFORM_RPI) - # RPI requried libraries + # RPI required libraries INCLUDE_PATHS += -I/opt/vc/include INCLUDE_PATHS += -I/opt/vc/include/interface/vmcs_host/linux INCLUDE_PATHS += -I/opt/vc/include/interface/vcos/pthreads endif +ifeq ($(PLATFORM),PLATFORM_DESKTOP) + ifeq ($(PLATFORM_OS),BSD) + # Consider -L$(RAYLIB_H_INSTALL_PATH) + INCLUDE_PATHS += -I/usr/local/include + endif + ifeq ($(PLATFORM_OS),LINUX) + # Reset everything. + # Precedence: immediately local, installed version, raysan5 provided libs -I$(RAYLIB_H_INSTALL_PATH) -I$(RAYLIB_PATH)/release/include + INCLUDE_PATHS = -I$(RAYLIB_H_INSTALL_PATH) -isystem. -isystem$(RAYLIB_PATH)/src -isystem$(RAYLIB_PATH)/release/include -isystem$(RAYLIB_PATH)/src/external + endif +endif -# Define library paths containing required libs -LDFLAGS = -L. -L$(RAYLIB_RELEASE_PATH) -L$(RAYLIB_PATH)/src +# Define library paths containing required libs. +LDFLAGS = -L. -L$(RAYLIB_RELEASE_PATH) -L$(RAYLIB_PATH)/src ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),BSD) - INCLUDE_PATHS += -I/usr/local/include + # Consider -L$(RAYLIB_INSTALL_PATH) LDFLAGS += -L. -Lsrc -L/usr/local/lib endif + ifeq ($(PLATFORM_OS),LINUX) + # Reset everything. + # Precedence: immediately local, installed version, raysan5 provided libs + LDFLAGS = -L. -L$(RAYLIB_INSTALL_PATH) -L$(RAYLIB_RELEASE_PATH) + endif endif ifeq ($(PLATFORM),PLATFORM_RPI) @@ -224,7 +287,10 @@ endif ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),WINDOWS) # Libraries for Windows desktop compilation - LDLIBS = -lraylib -lopengl32 -lgdi32 + # NOTE: WinMM library required to set high-res timer resolution + LDLIBS = -lraylib -lopengl32 -lgdi32 -lwinmm + # Required for physac examples + #LDLIBS += -static -lpthread endif ifeq ($(PLATFORM_OS),LINUX) # Libraries for Debian GNU/Linux desktop compiling @@ -240,6 +306,10 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(USE_WAYLAND_DISPLAY),TRUE) LDLIBS += -lwayland-client -lwayland-cursor -lwayland-egl -lxkbcommon endif + # Explicit link to libc + ifeq ($(RAYLIB_LIBTYPE),SHARED) + LDLIBS += -lc + endif endif ifeq ($(PLATFORM_OS),OSX) # Libraries for OSX 10.9 desktop compiling @@ -270,20 +340,21 @@ ifeq ($(PLATFORM),PLATFORM_WEB) endif # Define all source files required -PROJECT_SOURCE_FILES ?= skully_escape.c \ - player.c \ - monster.c \ - screens/screen_logo.c \ - screens/screen_logo_raylib.c \ - screens/screen_title.c \ - screens/screen_attic.c \ - screens/screen_aisle01.c \ - screens/screen_aisle02.c \ - screens/screen_armory.c \ - screens/screen_livingroom.c \ - screens/screen_kitchen.c \ - screens/screen_bathroom.c \ - screens/screen_ending.c +PROJECT_SOURCE_FILES ?= \ + skully_escape.c \ + player.c \ + monster.c \ + screens/screen_logo.c \ + screens/screen_logo_raylib.c \ + screens/screen_title.c \ + screens/screen_attic.c \ + screens/screen_aisle01.c \ + screens/screen_aisle02.c \ + screens/screen_armory.c \ + screens/screen_livingroom.c \ + screens/screen_kitchen.c \ + screens/screen_bathroom.c \ + screens/screen_ending.c # Define all object files from source files OBJS = $(patsubst %.c, %.o, $(PROJECT_SOURCE_FILES)) @@ -318,7 +389,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) del *.o *.exe /s endif ifeq ($(PLATFORM_OS),LINUX) - find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -f + find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -fv endif ifeq ($(PLATFORM_OS),OSX) find . -type f -perm +ugo+x -delete @@ -327,7 +398,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) endif ifeq ($(PLATFORM),PLATFORM_RPI) find . -type f -executable -delete - rm -f *.o + rm -fv *.o endif ifeq ($(PLATFORM),PLATFORM_WEB) del *.o *.html *.js diff --git a/games/skully_escape/Makefile.Android b/games/skully_escape/Makefile.Android index f082ab230..29d437b1b 100644 --- a/games/skully_escape/Makefile.Android +++ b/games/skully_escape/Makefile.Android @@ -22,24 +22,33 @@ #************************************************************************************************** # Define required raylib variables -PLATFORM ?= PLATFORM_ANDROID -RAYLIB_PATH ?= ..\.. +PLATFORM ?= PLATFORM_ANDROID +RAYLIB_PATH ?= ..\.. + +# Define Android architecture (armeabi-v7a, arm64-v8a, x86, x86-64) and API version +ANDROID_ARCH ?= ARM +ANDROID_API_VERSION = 21 +ifeq ($(ANDROID_ARCH),ARM) + ANDROID_ARCH_NAME = armeabi-v7a +endif +ifeq ($(ANDROID_ARCH),ARM64) + ANDROID_ARCH_NAME = arm64-v8a +endif # Required path variables # NOTE: JAVA_HOME must be set to JDK -ANDROID_HOME = C:/android-sdk -ANDROID_NDK = C:/android-ndk -ANDROID_TOOLCHAIN = C:/android_toolchain_arm_api16 -ANDROID_BUILD_TOOLS = $(ANDROID_HOME)/build-tools/26.0.2 -ANDROID_PLATFORM_TOOLS = $(ANDROID_HOME)/platform-tools -JAVA_HOME = C:/PROGRA~1/Java/jdk1.8.0_144 +JAVA_HOME ?= C:/JavaJDK +ANDROID_HOME = C:/android-sdk +ANDROID_TOOLCHAIN = C:/android_toolchain_$(ANDROID_ARCH)_API$(ANDROID_API_VERSION) +ANDROID_BUILD_TOOLS = $(ANDROID_HOME)/build-tools/28.0.1 +ANDROID_PLATFORM_TOOLS = $(ANDROID_HOME)/platform-tools # Android project configuration variables -PROJECT_NAME ?= raylib_game -PROJECT_LIBRARY_NAME ?= main -PROJECT_BUILD_PATH ?= android.$(PROJECT_NAME) +PROJECT_NAME ?= raylib_game +PROJECT_LIBRARY_NAME ?= main +PROJECT_BUILD_PATH ?= android.$(PROJECT_NAME) PROJECT_RESOURCES_PATH ?= resources -PROJECT_SOURCE_FILES ?= raylib_game.c +PROJECT_SOURCE_FILES ?= raylib_game.c # Some source files are placed in directories, when compiling to some # output directory other than source, that directory must pre-exist. @@ -61,30 +70,43 @@ APP_KEYSTORE_PASS ?= raylib # Library type used for raylib: STATIC (.a) or SHARED (.so/.dll) RAYLIB_LIBTYPE ?= STATIC -RAYLIB_LIB_PATH = $(RAYLIB_PATH)\release\libs\android\armeabi-v7a + +# Library path for libraylib.a/libraylib.so +RAYLIB_LIB_PATH = $(RAYLIB_PATH)\src # Shared libs must be added to APK if required # NOTE: Generated NativeLoader.java automatically load those libraries ifeq ($(RAYLIB_LIBTYPE),SHARED) - PROJECT_SHARED_LIBS = lib/armeabi-v7a/libraylib.so + PROJECT_SHARED_LIBS = lib/$(ANDROID_ARCH_NAME)/libraylib.so endif # Compiler and archiver -# NOTE: GCC is being deprectated in Android NDK r16 -CC = $(ANDROID_TOOLCHAIN)/bin/arm-linux-androideabi-gcc -AR = $(ANDROID_TOOLCHAIN)/bin/arm-linux-androideabi-ar +# NOTE: GCC is being deprecated in Android NDK r16 +ifeq ($(ANDROID_ARCH),ARM) + CC = $(ANDROID_TOOLCHAIN)/bin/arm-linux-androideabi-clang + AR = $(ANDROID_TOOLCHAIN)/bin/arm-linux-androideabi-ar +endif +ifeq ($(ANDROID_ARCH),ARM64) + CC = $(ANDROID_TOOLCHAIN)/bin/aarch64-linux-android-clang + AR = $(ANDROID_TOOLCHAIN)/bin/aarch64-linux-android-ar +endif # Compiler flags for arquitecture -CFLAGS = -std=c99 -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 +ifeq ($(ANDROID_ARCH),ARM) + CFLAGS = -std=c99 -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 +endif +ifeq ($(ANDROID_ARCH),ARM64) + CFLAGS = -std=c99 -target aarch64 -mfix-cortex-a53-835769 +endif # Compilation functions attributes options CFLAGS += -ffunction-sections -funwind-tables -fstack-protector-strong -fPIC # Compiler options for the linker CFLAGS += -Wall -Wa,--noexecstack -Wformat -Werror=format-security -no-canonical-prefixes # Preprocessor macro definitions -CFLAGS += -DANDROID -DPLATFORM_ANDROID -D__ANDROID_API__=16 +CFLAGS += -DANDROID -DPLATFORM_ANDROID -D__ANDROID_API__=$(ANDROID_API_VERSION) # Paths containing required header files -INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/release/include -I$(RAYLIB_PATH)/src/external/android/native_app_glue +INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external/android/native_app_glue # Linker options LDFLAGS = -Wl,-soname,lib$(PROJECT_LIBRARY_NAME).so -Wl,--exclude-libs,libatomic.a @@ -92,11 +114,11 @@ LDFLAGS += -Wl,--build-id -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,relro -Wl # Force linking of library module to define symbol LDFLAGS += -u ANativeActivity_onCreate # Library paths containing required libs -LDFLAGS += -L. -L$(PROJECT_BUILD_PATH)/obj -L$(PROJECT_BUILD_PATH)/lib/armeabi-v7a +LDFLAGS += -L. -L$(PROJECT_BUILD_PATH)/obj -L$(PROJECT_BUILD_PATH)/lib/$(ANDROID_ARCH_NAME) -L$(ANDROID_TOOLCHAIN)\sysroot\usr\lib # Define any libraries to link into executable # if you want to link libraries (libname.so or libname.a), use the -lname -LDLIBS = -lraylib -lnative_app_glue -llog -landroid -lEGL -lGLESv2 -lOpenSLES -latomic -lc -lm -ldl +LDLIBS = -lm -lc -lraylib -llog -landroid -lEGL -lGLESv2 -lOpenSLES -ldl # Generate target objects list from PROJECT_SOURCE_FILES OBJS = $(patsubst %.c, $(PROJECT_BUILD_PATH)/obj/%.o, $(PROJECT_SOURCE_FILES)) @@ -110,7 +132,6 @@ all: create_temp_project_dirs \ generate_android_manifest \ generate_apk_keystore \ config_project_package \ - compile_native_app_glue \ compile_project_code \ compile_project_class \ compile_project_class_dex \ @@ -127,7 +148,7 @@ create_temp_project_dirs: if not exist $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME) mkdir $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME) if not exist $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME)\$(APP_PRODUCT_NAME) mkdir $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME)\$(APP_PRODUCT_NAME) if not exist $(PROJECT_BUILD_PATH)\lib mkdir $(PROJECT_BUILD_PATH)\lib - if not exist $(PROJECT_BUILD_PATH)\lib\armeabi-v7a mkdir $(PROJECT_BUILD_PATH)\lib\armeabi-v7a + if not exist $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME) mkdir $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME) if not exist $(PROJECT_BUILD_PATH)\bin mkdir $(PROJECT_BUILD_PATH)\bin if not exist $(PROJECT_BUILD_PATH)\res mkdir $(PROJECT_BUILD_PATH)\res if not exist $(PROJECT_BUILD_PATH)\res\drawable-ldpi mkdir $(PROJECT_BUILD_PATH)\res\drawable-ldpi @@ -147,10 +168,10 @@ endef # NOTE: If using shared libs they are loaded by generated NativeLoader.java copy_project_required_libs: ifeq ($(RAYLIB_LIBTYPE),SHARED) - copy /Y $(RAYLIB_LIB_PATH)\libraylib.so $(PROJECT_BUILD_PATH)\lib\armeabi-v7a\libraylib.so + copy /Y $(RAYLIB_LIB_PATH)\libraylib.so $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME)\libraylib.so endif ifeq ($(RAYLIB_LIBTYPE),STATIC) - copy /Y $(RAYLIB_LIB_PATH)\libraylib.a $(PROJECT_BUILD_PATH)\lib\armeabi-v7a\libraylib.a + copy /Y $(RAYLIB_LIB_PATH)\libraylib.a $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME)\libraylib.a endif # Copy project required resources: strings.xml, icon.png, assets @@ -185,7 +206,7 @@ generate_android_manifest: @echo ^> $(PROJECT_BUILD_PATH)/AndroidManifest.xml @echo package="com.$(APP_COMPANY_NAME).$(APP_PRODUCT_NAME)" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml @echo android:versionCode="$(APP_VERSION_CODE)" android:versionName="$(APP_VERSION_NAME)" ^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml - @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml @echo ^> $(PROJECT_BUILD_PATH)/AndroidManifest.xml @@ -210,7 +231,7 @@ generate_apk_keystore: # Config project package and resource using AndroidManifest.xml and res/values/strings.xml # NOTE: Generates resources file: src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/R.java config_project_package: - $(ANDROID_BUILD_TOOLS)/aapt package -f -m -S $(PROJECT_BUILD_PATH)/res -J $(PROJECT_BUILD_PATH)/src -M $(PROJECT_BUILD_PATH)/AndroidManifest.xml -I $(ANDROID_HOME)/platforms/android-16/android.jar + $(ANDROID_BUILD_TOOLS)/aapt package -f -m -S $(PROJECT_BUILD_PATH)/res -J $(PROJECT_BUILD_PATH)/src -M $(PROJECT_BUILD_PATH)/AndroidManifest.xml -I $(ANDROID_HOME)/platforms/android-$(ANDROID_API_VERSION)/android.jar # Compile native_app_glue code as static library: obj/libnative_app_glue.a compile_native_app_glue: @@ -219,7 +240,7 @@ compile_native_app_glue: # Compile project code into a shared library: lib/lib$(PROJECT_LIBRARY_NAME).so compile_project_code: $(OBJS) - $(CC) -o $(PROJECT_BUILD_PATH)/lib/armeabi-v7a/lib$(PROJECT_LIBRARY_NAME).so $(OBJS) -shared $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) + $(CC) -o $(PROJECT_BUILD_PATH)/lib/$(ANDROID_ARCH_NAME)/lib$(PROJECT_LIBRARY_NAME).so $(OBJS) -shared $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) # Compile all .c files required into object (.o) files # NOTE: Those files will be linked into a shared library @@ -228,7 +249,7 @@ $(PROJECT_BUILD_PATH)/obj/%.o:%.c # Compile project .java code into .class (Java bytecode) compile_project_class: - $(JAVA_HOME)/bin/javac -verbose -source 1.7 -target 1.7 -d $(PROJECT_BUILD_PATH)/obj -bootclasspath $(JAVA_HOME)/jre/lib/rt.jar -classpath $(ANDROID_HOME)/platforms/android-16/android.jar;$(PROJECT_BUILD_PATH)/obj -sourcepath $(PROJECT_BUILD_PATH)/src $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/R.java $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java + $(JAVA_HOME)/bin/javac -verbose -source 1.7 -target 1.7 -d $(PROJECT_BUILD_PATH)/obj -bootclasspath $(JAVA_HOME)/jre/lib/rt.jar -classpath $(ANDROID_HOME)/platforms/android-$(ANDROID_API_VERSION)/android.jar;$(PROJECT_BUILD_PATH)/obj -sourcepath $(PROJECT_BUILD_PATH)/src $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/R.java $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java # Compile .class files into Dalvik executable bytecode (.dex) # NOTE: Since Android 5.0, Dalvik interpreter (JIT) has been replaced by ART (AOT) @@ -239,8 +260,8 @@ compile_project_class_dex: # NOTE: Requires compiled classes.dex and lib$(PROJECT_LIBRARY_NAME).so # NOTE: Use -A resources to define additional directory in which to find raw asset files create_project_apk_package: - $(ANDROID_BUILD_TOOLS)/aapt package -f -M $(PROJECT_BUILD_PATH)/AndroidManifest.xml -S $(PROJECT_BUILD_PATH)/res -A $(PROJECT_BUILD_PATH)/assets -I $(ANDROID_HOME)/platforms/android-16/android.jar -F $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).unsigned.apk $(PROJECT_BUILD_PATH)/bin - cd $(PROJECT_BUILD_PATH) && $(ANDROID_BUILD_TOOLS)/aapt add bin/$(PROJECT_NAME).unsigned.apk lib/armeabi-v7a/lib$(PROJECT_LIBRARY_NAME).so $(PROJECT_SHARED_LIBS) + $(ANDROID_BUILD_TOOLS)/aapt package -f -M $(PROJECT_BUILD_PATH)/AndroidManifest.xml -S $(PROJECT_BUILD_PATH)/res -A $(PROJECT_BUILD_PATH)/assets -I $(ANDROID_HOME)/platforms/android-$(ANDROID_API_VERSION)/android.jar -F $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).unsigned.apk $(PROJECT_BUILD_PATH)/bin + cd $(PROJECT_BUILD_PATH) && $(ANDROID_BUILD_TOOLS)/aapt add bin/$(PROJECT_NAME).unsigned.apk lib/$(ANDROID_ARCH_NAME)/lib$(PROJECT_LIBRARY_NAME).so $(PROJECT_SHARED_LIBS) # Create signed APK package using generated Key: bin/$(PROJECT_NAME).signed.apk sign_project_apk_package: @@ -253,7 +274,11 @@ zipalign_project_apk_package: # Install $(PROJECT_NAME).apk to default emulator/device # NOTE: Use -e (emulator) or -d (device) parameters if required install: - $(ANDROID_PLATFORM_TOOLS)/adb install -r $(PROJECT_NAME).apk + $(ANDROID_PLATFORM_TOOLS)/adb install --abi $(ANDROID_ARCH_NAME) -rds $(PROJECT_NAME).apk + +# Check supported ABI for the device (armeabi-v7a, arm64-v8a, x86, x86_64) +check_device_abi: + $(ANDROID_PLATFORM_TOOLS)/adb shell getprop ro.product.cpu.abi # Monitorize output log coming from device, only raylib tag logcat: diff --git a/games/skully_escape/player.c b/games/skully_escape/player.c index 857ff5388..552326e18 100644 --- a/games/skully_escape/player.c +++ b/games/skully_escape/player.c @@ -271,11 +271,11 @@ static void DrawLifes(void) { if (player.numLifes != 0) { - Vector2 position = { 20, GetScreenHeight() - texLife.height - 20 }; - + Vector2 position = { 20, GetScreenHeight() - texLife.height - 20 }; + for(int i = 0; i < player.numLifes; i++) { - DrawTexture(texLife, position.x + i*texLife.width, position.y, Fade(RAYWHITE, 0.7f)); + DrawTexture(texLife, position.x + i*texLife.width, position.y, Fade(RAYWHITE, 0.7f)); } } } \ No newline at end of file diff --git a/games/skully_escape/skully_escape.c b/games/skully_escape/skully_escape.c index e2e7007bb..1bb598ea3 100644 --- a/games/skully_escape/skully_escape.c +++ b/games/skully_escape/skully_escape.c @@ -2,10 +2,12 @@ * * SKULLY ESCAPE [KING GAME JAM 2015] * +* A scary graphic adventure in an old mansion +* * This game has been created using raylib 1.6 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * -* Copyright (c) 2014 Ramon Santamaria (@raysan5) +* Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ @@ -50,9 +52,9 @@ void UpdateDrawFrame(void); // Update and Draw one frame //---------------------------------------------------------------------------------- int main(void) { - // Initialization (Note windowTitle is unused on Android) - //--------------------------------------------------------- - InitWindow(screenWidth, screenHeight, "SKULLY ESCAPE [KING GAMEJAM]"); + // Initialization (Note windowTitle is unused on Android) + //--------------------------------------------------------- + InitWindow(screenWidth, screenHeight, "SKULLY ESCAPE [KING GAMEJAM 2015]"); // Global data loading (assets that must be available in all screens, i.e. fonts) InitAudioDevice(); @@ -61,10 +63,10 @@ int main(void) PlayMusicStream(music); font = LoadFont("resources/textures/alagard.png"); - doors = LoadTexture("resources/textures/doors.png"); + doors = LoadTexture("resources/textures/doors.png"); sndDoor = LoadSound("resources/audio/door.ogg"); sndScream = LoadSound("resources/audio/scream.ogg"); - + InitPlayer(); // Setup and Init first screen @@ -88,7 +90,7 @@ int main(void) //-------------------------------------------------------------------------------------- // Unload all global loaded data (i.e. fonts) here! - UnloadPlayer(); + UnloadPlayer(); UnloadFont(font); UnloadTexture(doors); UnloadSound(sndDoor); @@ -395,7 +397,7 @@ void UpdateDrawFrame(void) case ENDING: DrawEndingScreen(); break; default: break; } - + if (onTransition) DrawTransition(); //DrawFPS(10, 10); diff --git a/games/snake.c b/games/snake.c index 23d1bd1d0..475227543 100644 --- a/games/snake.c +++ b/games/snake.c @@ -43,19 +43,19 @@ typedef struct Food { //------------------------------------------------------------------------------------ // Global Variables Declaration //------------------------------------------------------------------------------------ -static int screenWidth = 800; -static int screenHeight = 450; +static const int screenWidth = 800; +static const int screenHeight = 450; -static int framesCounter; -static bool gameOver; -static bool pause; +static int framesCounter = 0; +static bool gameOver = false; +static bool pause = false; -static Food fruit; -static Snake snake[SNAKE_LENGTH]; -static Vector2 snakePosition[SNAKE_LENGTH]; -static bool allowMove; -static Vector2 offset; -static int counterTail; +static Food fruit = { 0 }; +static Snake snake[SNAKE_LENGTH] = { 0 }; +static Vector2 snakePosition[SNAKE_LENGTH] = { 0 }; +static bool allowMove = false; +static Vector2 offset = { 0 }; +static int counterTail = 0; //------------------------------------------------------------------------------------ // Module Functions Declaration (local) @@ -80,7 +80,6 @@ int main(void) #if defined(PLATFORM_WEB) emscripten_set_main_loop(UpdateDrawFrame, 0, 1); #else - SetTargetFPS(60); //-------------------------------------------------------------------------------------- @@ -93,7 +92,6 @@ int main(void) //---------------------------------------------------------------------------------- } #endif - // De-Initialization //-------------------------------------------------------------------------------------- UnloadGame(); // Unload loaded data (textures, sounds, models...) @@ -150,7 +148,7 @@ void UpdateGame(void) if (!pause) { - // control + // Player control if (IsKeyPressed(KEY_RIGHT) && (snake[0].speed.x == 0) && allowMove) { snake[0].speed = (Vector2){ SQUARE_SIZE, 0 }; @@ -172,7 +170,7 @@ void UpdateGame(void) allowMove = false; } - // movement + // Snake movement for (int i = 0; i < counterTail; i++) snakePosition[i] = snake[i].position; if ((framesCounter%5) == 0) @@ -189,7 +187,7 @@ void UpdateGame(void) } } - // wall behaviour + // Wall behaviour if (((snake[0].position.x) > (screenWidth - offset.x)) || ((snake[0].position.y) > (screenHeight - offset.y)) || (snake[0].position.x < 0) || (snake[0].position.y < 0)) @@ -197,13 +195,13 @@ void UpdateGame(void) gameOver = true; } - // collision with yourself + // Collision with yourself for (int i = 1; i < counterTail; i++) { if ((snake[0].position.x == snake[i].position.x) && (snake[0].position.y == snake[i].position.y)) gameOver = true; } - // fruit.position calculation + // Fruit position calculation if (!fruit.active) { fruit.active = true; @@ -219,7 +217,7 @@ void UpdateGame(void) } } - // collision + // Collision if ((snake[0].position.x < (fruit.position.x + fruit.size.x) && (snake[0].position.x + snake[0].size.x) > fruit.position.x) && (snake[0].position.y < (fruit.position.y + fruit.size.y) && (snake[0].position.y + snake[0].size.y) > fruit.position.y)) { diff --git a/games/space_invaders.c b/games/space_invaders.c index 97f145473..7d5007782 100644 --- a/games/space_invaders.c +++ b/games/space_invaders.c @@ -54,25 +54,25 @@ typedef struct Shoot{ //------------------------------------------------------------------------------------ // Global Variables Declaration //------------------------------------------------------------------------------------ -static int screenWidth = 800; -static int screenHeight = 450; +static const int screenWidth = 800; +static const int screenHeight = 450; -static bool gameOver; -static bool pause; -static int score; -static bool victory; +static bool gameOver = false; +static bool pause = false; +static int score = 0; +static bool victory = false; -static Player player; -static Enemy enemy[NUM_MAX_ENEMIES]; -static Shoot shoot[NUM_SHOOTS]; -static EnemyWave wave; +static Player player = { 0 }; +static Enemy enemy[NUM_MAX_ENEMIES] = { 0 }; +static Shoot shoot[NUM_SHOOTS] = { 0 }; +static EnemyWave wave = { 0 }; -static int shootRate; -static float alpha; +static int shootRate = 0; +static float alpha = 0.0f; -static int activeEnemies; -static int enemiesKill; -static bool smooth; +static int activeEnemies = 0; +static int enemiesKill = 0; +static bool smooth = false; //------------------------------------------------------------------------------------ // Module Functions Declaration (local) @@ -97,7 +97,6 @@ int main(void) #if defined(PLATFORM_WEB) emscripten_set_main_loop(UpdateDrawFrame, 0, 1); #else - SetTargetFPS(60); //-------------------------------------------------------------------------------------- @@ -110,7 +109,6 @@ int main(void) //---------------------------------------------------------------------------------- } #endif - // De-Initialization //-------------------------------------------------------------------------------------- UnloadGame(); // Unload loaded data (textures, sounds, models...) @@ -289,7 +287,7 @@ void UpdateGame(void) if (player.rec.y <= 0) player.rec.y = 0; if (player.rec.y + player.rec.height >= screenHeight) player.rec.y = screenHeight - player.rec.height; - //Shoot initialization + // Shoot initialization if (IsKeyDown(KEY_SPACE)) { shootRate += 5; @@ -375,7 +373,7 @@ void DrawGame(void) if (shoot[i].active) DrawRectangleRec(shoot[i].rec, shoot[i].color); } - DrawText(FormatText("%04i", score), 20, 20, 40, GRAY); + DrawText(TextFormat("%04i", score), 20, 20, 40, GRAY); if (victory) DrawText("YOU WIN", screenWidth/2 - MeasureText("YOU WIN", 40)/2, screenHeight/2 - 40, 40, BLACK); diff --git a/games/tetris.c b/games/tetris.c index 3c9d5c5c6..2b309184b 100644 --- a/games/tetris.c +++ b/games/tetris.c @@ -44,8 +44,8 @@ typedef enum GridSquare { EMPTY, MOVING, FULL, BLOCK, FADING } GridSquare; //------------------------------------------------------------------------------------ // Global Variables Declaration //------------------------------------------------------------------------------------ -static int screenWidth = 800; -static int screenHeight = 450; +static const int screenWidth = 800; +static const int screenHeight = 450; static bool gameOver = false; static bool pause = false; @@ -99,7 +99,7 @@ static void ResolveFallingMovement(); static bool ResolveLateralMovement(); static bool ResolveTurnMovement(); static void CheckDetection(); -static void CheckCompletition(); +static void CheckCompletion(); static void DeleteCompleteLines(); //------------------------------------------------------------------------------------ @@ -116,7 +116,6 @@ int main(void) #if defined(PLATFORM_WEB) emscripten_set_main_loop(UpdateDrawFrame, 0, 1); #else - SetTargetFPS(60); //-------------------------------------------------------------------------------------- @@ -129,7 +128,6 @@ int main(void) //---------------------------------------------------------------------------------- } #endif - // De-Initialization //-------------------------------------------------------------------------------------- UnloadGame(); // Unload loaded data (textures, sounds, models...) @@ -239,7 +237,7 @@ void UpdateGame(void) ResolveFallingMovement(&detection, &pieceActive); // Check if we fullfilled a line and if so, erase the line and pull down the the lines above - CheckCompletition(&lineToDelete); + CheckCompletion(&lineToDelete); gravityMovementCounter = 0; } @@ -387,7 +385,7 @@ void DrawGame(void) } DrawText("INCOMING:", offset.x, offset.y - 100, 10, GRAY); - DrawText(FormatText("LINES: %04i", lines), offset.x, offset.y + 20, 10, GRAY); + DrawText(TextFormat("LINES: %04i", lines), offset.x, offset.y + 20, 10, GRAY); if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); } @@ -450,8 +448,7 @@ static bool Createpiece() static void GetRandompiece() { - srand(time(NULL)); - int random = rand() % 7; + int random = GetRandomValue(0, 6); for (int i = 0; i < 4; i++) { @@ -461,15 +458,15 @@ static void GetRandompiece() } } - switch(random) + switch (random) { - case 0: { incomingPiece[1][1] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[1][2] = MOVING; incomingPiece[2][2] = MOVING; } break; //Cube - case 1: { incomingPiece[1][0] = MOVING; incomingPiece[1][1] = MOVING; incomingPiece[1][2] = MOVING; incomingPiece[2][2] = MOVING; } break; //L - case 2: { incomingPiece[1][2] = MOVING; incomingPiece[2][0] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[2][2] = MOVING; } break; //L inversa - case 3: { incomingPiece[0][1] = MOVING; incomingPiece[1][1] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[3][1] = MOVING; } break; //Recta - case 4: { incomingPiece[1][0] = MOVING; incomingPiece[1][1] = MOVING; incomingPiece[1][2] = MOVING; incomingPiece[2][1] = MOVING; } break; //Creu tallada - case 5: { incomingPiece[1][1] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[2][2] = MOVING; incomingPiece[3][2] = MOVING; } break; //S - case 6: { incomingPiece[1][2] = MOVING; incomingPiece[2][2] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[3][1] = MOVING; } break; //S inversa + case 0: { incomingPiece[1][1] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[1][2] = MOVING; incomingPiece[2][2] = MOVING; } break; //Cube + case 1: { incomingPiece[1][0] = MOVING; incomingPiece[1][1] = MOVING; incomingPiece[1][2] = MOVING; incomingPiece[2][2] = MOVING; } break; //L + case 2: { incomingPiece[1][2] = MOVING; incomingPiece[2][0] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[2][2] = MOVING; } break; //L inversa + case 3: { incomingPiece[0][1] = MOVING; incomingPiece[1][1] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[3][1] = MOVING; } break; //Recta + case 4: { incomingPiece[1][0] = MOVING; incomingPiece[1][1] = MOVING; incomingPiece[1][2] = MOVING; incomingPiece[2][1] = MOVING; } break; //Creu tallada + case 5: { incomingPiece[1][1] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[2][2] = MOVING; incomingPiece[3][2] = MOVING; } break; //S + case 6: { incomingPiece[1][2] = MOVING; incomingPiece[2][2] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[3][1] = MOVING; } break; //S inversa } } @@ -491,8 +488,7 @@ static void ResolveFallingMovement(bool *detection, bool *pieceActive) } } } - // We move down the piece - else + else // We move down the piece { for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) { @@ -505,6 +501,7 @@ static void ResolveFallingMovement(bool *detection, bool *pieceActive) } } } + piecePositionY++; } } @@ -513,8 +510,8 @@ static bool ResolveLateralMovement() { bool collision = false; - // Move left - if (IsKeyDown(KEY_LEFT)) + // Piece movement + if (IsKeyDown(KEY_LEFT)) // Move left { // Check if is possible to move to left for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) @@ -528,6 +525,7 @@ static bool ResolveLateralMovement() } } } + // If able, move left if (!collision) { @@ -547,9 +545,7 @@ static bool ResolveLateralMovement() piecePositionX--; } } - - // Move right - else if (IsKeyDown(KEY_RIGHT)) + else if (IsKeyDown(KEY_RIGHT)) // Move right { // Check if is possible to move to right for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) @@ -567,6 +563,7 @@ static bool ResolveLateralMovement() } } } + // If able move right if (!collision) { @@ -595,112 +592,73 @@ static bool ResolveTurnMovement() // Input for turning the piece if (IsKeyDown(KEY_UP)) { - int aux; + int aux = 0; bool checker = false; // Check all turning possibilities if ((grid[piecePositionX + 3][piecePositionY] == MOVING) && (grid[piecePositionX][piecePositionY] != EMPTY) && - (grid[piecePositionX][piecePositionY] != MOVING)) - { - checker = true; - } + (grid[piecePositionX][piecePositionY] != MOVING)) checker = true; + if ((grid[piecePositionX + 3][piecePositionY + 3] == MOVING) && (grid[piecePositionX + 3][piecePositionY] != EMPTY) && - (grid[piecePositionX + 3][piecePositionY] != MOVING)) - { - checker = true; - } + (grid[piecePositionX + 3][piecePositionY] != MOVING)) checker = true; + if ((grid[piecePositionX][piecePositionY + 3] == MOVING) && (grid[piecePositionX + 3][piecePositionY + 3] != EMPTY) && - (grid[piecePositionX + 3][piecePositionY + 3] != MOVING)) - { - checker = true; - } + (grid[piecePositionX + 3][piecePositionY + 3] != MOVING)) checker = true; + if ((grid[piecePositionX][piecePositionY] == MOVING) && (grid[piecePositionX][piecePositionY + 3] != EMPTY) && - (grid[piecePositionX][piecePositionY + 3] != MOVING)) - { - checker = true; - } - + (grid[piecePositionX][piecePositionY + 3] != MOVING)) checker = true; if ((grid[piecePositionX + 1][piecePositionY] == MOVING) && (grid[piecePositionX][piecePositionY + 2] != EMPTY) && - (grid[piecePositionX][piecePositionY + 2] != MOVING)) - { - checker = true; - } + (grid[piecePositionX][piecePositionY + 2] != MOVING)) checker = true; + if ((grid[piecePositionX + 3][piecePositionY + 1] == MOVING) && (grid[piecePositionX + 1][piecePositionY] != EMPTY) && - (grid[piecePositionX + 1][piecePositionY] != MOVING)) - { - checker = true; - } + (grid[piecePositionX + 1][piecePositionY] != MOVING)) checker = true; + if ((grid[piecePositionX + 2][piecePositionY + 3] == MOVING) && (grid[piecePositionX + 3][piecePositionY + 1] != EMPTY) && - (grid[piecePositionX + 3][piecePositionY + 1] != MOVING)) - { - checker = true; - } + (grid[piecePositionX + 3][piecePositionY + 1] != MOVING)) checker = true; + if ((grid[piecePositionX][piecePositionY + 2] == MOVING) && (grid[piecePositionX + 2][piecePositionY + 3] != EMPTY) && - (grid[piecePositionX + 2][piecePositionY + 3] != MOVING)) - { - checker = true; - } - + (grid[piecePositionX + 2][piecePositionY + 3] != MOVING)) checker = true; if ((grid[piecePositionX + 2][piecePositionY] == MOVING) && (grid[piecePositionX][piecePositionY + 1] != EMPTY) && - (grid[piecePositionX][piecePositionY + 1] != MOVING)) - { - checker = true; - } + (grid[piecePositionX][piecePositionY + 1] != MOVING)) checker = true; + if ((grid[piecePositionX + 3][piecePositionY + 2] == MOVING) && (grid[piecePositionX + 2][piecePositionY] != EMPTY) && - (grid[piecePositionX + 2][piecePositionY] != MOVING)) - { - checker = true; - } + (grid[piecePositionX + 2][piecePositionY] != MOVING)) checker = true; + if ((grid[piecePositionX + 1][piecePositionY + 3] == MOVING) && (grid[piecePositionX + 3][piecePositionY + 2] != EMPTY) && - (grid[piecePositionX + 3][piecePositionY + 2] != MOVING)) - { - checker = true; - } + (grid[piecePositionX + 3][piecePositionY + 2] != MOVING)) checker = true; + if ((grid[piecePositionX][piecePositionY + 1] == MOVING) && (grid[piecePositionX + 1][piecePositionY + 3] != EMPTY) && - (grid[piecePositionX + 1][piecePositionY + 3] != MOVING)) - { - checker = true; - } + (grid[piecePositionX + 1][piecePositionY + 3] != MOVING)) checker = true; if ((grid[piecePositionX + 1][piecePositionY + 1] == MOVING) && (grid[piecePositionX + 1][piecePositionY + 2] != EMPTY) && - (grid[piecePositionX + 1][piecePositionY + 2] != MOVING)) - { - checker = true; - } - + (grid[piecePositionX + 1][piecePositionY + 2] != MOVING)) checker = true; + if ((grid[piecePositionX + 2][piecePositionY + 1] == MOVING) && (grid[piecePositionX + 1][piecePositionY + 1] != EMPTY) && - (grid[piecePositionX + 1][piecePositionY + 1] != MOVING)) - { - checker = true; - } + (grid[piecePositionX + 1][piecePositionY + 1] != MOVING)) checker = true; + if ((grid[piecePositionX + 2][piecePositionY + 2] == MOVING) && (grid[piecePositionX + 2][piecePositionY + 1] != EMPTY) && - (grid[piecePositionX + 2][piecePositionY + 1] != MOVING)) - { - checker = true; - } + (grid[piecePositionX + 2][piecePositionY + 1] != MOVING)) checker = true; + if ((grid[piecePositionX + 1][piecePositionY + 2] == MOVING) && (grid[piecePositionX + 2][piecePositionY + 2] != EMPTY) && - (grid[piecePositionX + 2][piecePositionY + 2] != MOVING)) - { - checker = true; - } + (grid[piecePositionX + 2][piecePositionY + 2] != MOVING)) checker = true; if (!checker) { @@ -750,6 +708,7 @@ static bool ResolveTurnMovement() } } } + return true; } @@ -767,9 +726,9 @@ static void CheckDetection(bool *detection) } } -static void CheckCompletition(bool *lineToDelete) +static void CheckCompletion(bool *lineToDelete) { - int calculator; + int calculator = 0; for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) { @@ -801,7 +760,7 @@ static void CheckCompletition(bool *lineToDelete) static void DeleteCompleteLines() { - // erase the completed line + // Erase the completed line for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) { while (grid[1][j] == FADING) @@ -810,6 +769,7 @@ static void DeleteCompleteLines() { grid[i][j] = EMPTY; } + for (int j2 = j-1; j2 >= 0; j2--) { for (int i2 = 1; i2 < GRID_HORIZONTAL_SIZE - 1; i2++) diff --git a/games/transmission/Makefile b/games/transmission/Makefile index f62fe0804..6df64277b 100644 --- a/games/transmission/Makefile +++ b/games/transmission/Makefile @@ -24,28 +24,43 @@ .PHONY: all clean # Define required raylib variables -# WARNING: To compile to HTML5, code must be redesigned to use emscripten.h and emscripten_set_main_loop() -PLATFORM ?= PLATFORM_DESKTOP -RAYLIB_PATH ?= ..\.. -PROJECT_NAME ?= transmission +PROJECT_NAME ?= transmission +RAYLIB_VERSION ?= 2.5.0 +RAYLIB_API_VERSION ?= 2 +RAYLIB_PATH ?= C:\GitHub\raylib -# Default path for raylib on Raspberry Pi, if installed in different path, update it! -ifeq ($(PLATFORM),PLATFORM_RPI) - RAYLIB_PATH ?= /home/pi/raylib -endif +# Define default options + +# One of PLATFORM_DESKTOP, PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB +PLATFORM ?= PLATFORM_DESKTOP + +# Locations of your newly installed library and associated headers. See ../src/Makefile +# On Linux, if you have installed raylib but cannot compile the examples, check that +# the *_INSTALL_PATH values here are the same as those in src/Makefile or point to known locations. +# To enable system-wide compile-time and runtime linking to libraylib.so, run ../src/$ sudo make install RAYLIB_LIBTYPE_SHARED. +# To enable compile-time linking to a special version of libraylib.so, change these variables here. +# To enable runtime linking to a special version of libraylib.so, see EXAMPLE_RUNTIME_PATH below. +# If there is a libraylib in both EXAMPLE_RUNTIME_PATH and RAYLIB_INSTALL_PATH, at runtime, +# the library at EXAMPLE_RUNTIME_PATH, if present, will take precedence over the one at RAYLIB_INSTALL_PATH. +# RAYLIB_INSTALL_PATH should be the desired full path to libraylib. No relative paths. +DESTDIR ?= /usr/local +RAYLIB_INSTALL_PATH ?= $(DESTDIR)/lib +# RAYLIB_H_INSTALL_PATH locates the installed raylib header and associated source files. +RAYLIB_H_INSTALL_PATH ?= $(DESTDIR)/include # Library type used for raylib: STATIC (.a) or SHARED (.so/.dll) -RAYLIB_LIBTYPE ?= STATIC +RAYLIB_LIBTYPE ?= STATIC + +# Build mode for project: DEBUG or RELEASE +BUILD_MODE ?= RELEASE # Use external GLFW library instead of rglfw module -USE_EXTERNAL_GLFW ?= FALSE +# TODO: Review usage on Linux. Target version of choice. Switch on -lglfw or -lglfw3 +USE_EXTERNAL_GLFW ?= FALSE # Use Wayland display server protocol on Linux desktop # by default it uses X11 windowing system -USE_WAYLAND_DISPLAY ?= FALSE - -# NOTE: On PLATFORM_WEB OpenAL Soft backend is used by default (check raylib/src/Makefile) - +USE_WAYLAND_DISPLAY ?= FALSE # Determine PLATFORM_OS in case PLATFORM_DESKTOP selected ifeq ($(PLATFORM),PLATFORM_DESKTOP) @@ -82,40 +97,50 @@ ifeq ($(PLATFORM),PLATFORM_RPI) endif endif +# RAYLIB_PATH adjustment for different platforms. +# If using GNU make, we can get the full path to the top of the tree. Windows? BSD? +# Required for ldconfig or other tools that do not perform path expansion. +ifeq ($(PLATFORM),PLATFORM_DESKTOP) + ifeq ($(PLATFORM_OS),LINUX) + RAYLIB_PREFIX ?= .. + RAYLIB_PATH = $(realpath $(RAYLIB_PREFIX)) + endif +endif +# Default path for raylib on Raspberry Pi, if installed in different path, update it! +# This is not currently used by src/Makefile. Not sure of its origin or usage. Refer to wiki. +# TODO: update install: target in src/Makefile for RPI, consider relation to LINUX. +ifeq ($(PLATFORM),PLATFORM_RPI) + RAYLIB_PATH ?= /home/pi/raylib +endif + ifeq ($(PLATFORM),PLATFORM_WEB) # Emscripten required variables - EMSDK_PATH = C:/emsdk - EMSCRIPTEN_VERSION = 1.37.28 - CLANG_VERSION=e1.37.28_64bit - PYTHON_VERSION=2.7.5.3_64bit - NODE_VERSION=4.1.1_64bit - export PATH=$(EMSDK_PATH);$(EMSDK_PATH)\clang\$(CLANG_VERSION);$(EMSDK_PATH)\node\$(NODE_VERSION)\bin;$(EMSDK_PATH)\python\$(PYTHON_VERSION);$(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION);C:\raylib\MinGW\bin:$$(PATH) - EMSCRIPTEN=$(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION) + EMSDK_PATH ?= C:/emsdk + EMSCRIPTEN_VERSION ?= 1.38.32 + CLANG_VERSION = e$(EMSCRIPTEN_VERSION)_64bit + PYTHON_VERSION = 2.7.13.1_64bit\python-2.7.13.amd64 + NODE_VERSION = 8.9.1_64bit + export PATH = $(EMSDK_PATH);$(EMSDK_PATH)\clang\$(CLANG_VERSION);$(EMSDK_PATH)\node\$(NODE_VERSION)\bin;$(EMSDK_PATH)\python\$(PYTHON_VERSION);$(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION);C:\raylib\MinGW\bin:$$(PATH) + EMSCRIPTEN = $(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION) endif -RAYLIB_RELEASE_PATH ?= $(RAYLIB_PATH)/release/libs +# Define raylib release directory for compiled library. +# RAYLIB_RELEASE_PATH points to provided binaries or your freshly built version +RAYLIB_RELEASE_PATH ?= $(RAYLIB_PATH)/src -# Define raylib release directory for compiled library -ifeq ($(PLATFORM),PLATFORM_DESKTOP) - ifeq ($(PLATFORM_OS),WINDOWS) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/win32/mingw32 - endif - ifeq ($(PLATFORM_OS),LINUX) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/linux - endif - ifeq ($(PLATFORM_OS),OSX) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/osx - endif - ifeq ($(PLATFORM_OS),BSD) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/bsd - endif -endif -ifeq ($(PLATFORM),PLATFORM_RPI) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/rpi -endif -ifeq ($(PLATFORM),PLATFORM_WEB) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/html5 -endif +# EXAMPLE_RUNTIME_PATH embeds a custom runtime location of libraylib.so or other desired libraries +# into each example binary compiled with RAYLIB_LIBTYPE=SHARED. It defaults to RAYLIB_RELEASE_PATH +# so that these examples link at runtime with your version of libraylib.so in ../release/libs/linux +# without formal installation from ../src/Makefile. It aids portability and is useful if you have +# multiple versions of raylib, have raylib installed to a non-standard location, or want to +# bundle libraylib.so with your game. Change it to your liking. +# NOTE: If, at runtime, there is a libraylib.so at both EXAMPLE_RUNTIME_PATH and RAYLIB_INSTALL_PATH, +# The library at EXAMPLE_RUNTIME_PATH, if present, will take precedence over RAYLIB_INSTALL_PATH, +# Implemented for LINUX below with CFLAGS += -Wl,-rpath,$(EXAMPLE_RUNTIME_PATH) +# To see the result, run readelf -d core/core_basic_window; looking at the RPATH or RUNPATH attribute. +# To see which libraries a built example is linking to, ldd core/core_basic_window; +# Look for libraylib.so.1 => $(RAYLIB_INSTALL_PATH)/libraylib.so.1 or similar listing. +EXAMPLE_RUNTIME_PATH ?= $(RAYLIB_RELEASE_PATH) # Define default C compiler: gcc # NOTE: define g++ compiler if using C++ @@ -140,6 +165,8 @@ ifeq ($(PLATFORM),PLATFORM_RPI) endif ifeq ($(PLATFORM),PLATFORM_WEB) # HTML5 emscripten compiler + # WARNING: To compile to HTML5, code must be redesigned + # to use emscripten.h and emscripten_set_main_loop() CC = emcc endif @@ -154,7 +181,7 @@ endif # Define compiler flags: # -O1 defines optimization level -# -g enable debugging +# -g include debug information on compilation # -s strip unnecessary data from build # -Wall turns on most, but not all, compiler warnings # -std=c99 defines C language mode (standard C from 1999 revision) @@ -163,56 +190,92 @@ endif # -D_DEFAULT_SOURCE use with -std=c99 on Linux and PLATFORM_WEB, required for timespec CFLAGS += -O1 -s -Wall -std=c99 -D_DEFAULT_SOURCE -Wno-missing-braces +ifeq ($(BUILD_MODE),DEBUG) + CFLAGS += -g +endif + # Additional flags for compiler (if desired) #CFLAGS += -Wextra -Wmissing-prototypes -Wstrict-prototypes ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),WINDOWS) - # resources file contains windows exe icon + # resource file contains windows executable icon and properties # -Wl,--subsystem,windows hides the console window CFLAGS += $(RAYLIB_PATH)/raylib.rc.data -Wl,--subsystem,windows endif ifeq ($(PLATFORM_OS),LINUX) - CFLAGS += -D_DEFAULT_SOURCE + ifeq ($(RAYLIB_LIBTYPE),STATIC) + CFLAGS += -D_DEFAULT_SOURCE + endif + ifeq ($(RAYLIB_LIBTYPE),SHARED) + # Explicitly enable runtime link to libraylib.so + CFLAGS += -Wl,-rpath,$(EXAMPLE_RUNTIME_PATH) + endif endif endif ifeq ($(PLATFORM),PLATFORM_RPI) CFLAGS += -std=gnu99 endif ifeq ($(PLATFORM),PLATFORM_WEB) - # -O2 # if used, also set --memory-init-file 0 - # --memory-init-file 0 # to avoid an external memory initialization code file (.mem) - # -s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing + # -Os # size optimization + # -O2 # optimization level 2, if used, also set --memory-init-file 0 + # -s USE_GLFW=3 # Use glfw3 library (context/input management) + # -s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing -> WARNING: Audio buffers could FAIL! # -s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB) # -s USE_PTHREADS=1 # multithreading support - # -s WASM=1 # support Web Assembly (https://github.com/kripken/emscripten/wiki/WebAssembly) + # -s WASM=0 # disable Web Assembly, emitted by default + # -s EMTERPRETIFY=1 # enable emscripten code interpreter (very slow) + # -s EMTERPRETIFY_ASYNC=1 # support synchronous loops by emterpreter + # -s FORCE_FILESYSTEM=1 # force filesystem to load/save files data + # -s ASSERTIONS=1 # enable runtime checks for common memory allocation errors (-O1 and above turn it off) + # --profiling # include information for code profiling + # --memory-init-file 0 # to avoid an external memory initialization code file (.mem) # --preload-file resources # specify a resources folder for data compilation - CFLAGS += -s USE_GLFW=3 -s ASSERTIONS=1 -s WASM=1 --profiling --preload-file resources -s TOTAL_MEMORY=67108864 - + CFLAGS += -Os -s USE_GLFW=3 -s TOTAL_MEMORY=67108864 --preload-file resources + ifeq ($(BUILD_MODE), DEBUG) + CFLAGS += -s ASSERTIONS=1 --profiling + endif + # Define a custom shell .html and output extension - CFLAGS += --shell-file $(RAYLIB_PATH)\templates\web_shell\shell.html + CFLAGS += --shell-file $(RAYLIB_PATH)/src/shell.html EXT = .html endif # Define include paths for required headers # NOTE: Several external required libraries (stb and others) -INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/release/include -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external +INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external # Define additional directories containing required header files ifeq ($(PLATFORM),PLATFORM_RPI) - # RPI requried libraries + # RPI required libraries INCLUDE_PATHS += -I/opt/vc/include INCLUDE_PATHS += -I/opt/vc/include/interface/vmcs_host/linux INCLUDE_PATHS += -I/opt/vc/include/interface/vcos/pthreads endif +ifeq ($(PLATFORM),PLATFORM_DESKTOP) + ifeq ($(PLATFORM_OS),BSD) + # Consider -L$(RAYLIB_H_INSTALL_PATH) + INCLUDE_PATHS += -I/usr/local/include + endif + ifeq ($(PLATFORM_OS),LINUX) + # Reset everything. + # Precedence: immediately local, installed version, raysan5 provided libs -I$(RAYLIB_H_INSTALL_PATH) -I$(RAYLIB_PATH)/release/include + INCLUDE_PATHS = -I$(RAYLIB_H_INSTALL_PATH) -isystem. -isystem$(RAYLIB_PATH)/src -isystem$(RAYLIB_PATH)/release/include -isystem$(RAYLIB_PATH)/src/external + endif +endif -# Define library paths containing required libs -LDFLAGS = -L. -L$(RAYLIB_RELEASE_PATH) -L$(RAYLIB_PATH)/src +# Define library paths containing required libs. +LDFLAGS = -L. -L$(RAYLIB_RELEASE_PATH) -L$(RAYLIB_PATH)/src ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),BSD) - INCLUDE_PATHS += -I/usr/local/include + # Consider -L$(RAYLIB_INSTALL_PATH) LDFLAGS += -L. -Lsrc -L/usr/local/lib endif + ifeq ($(PLATFORM_OS),LINUX) + # Reset everything. + # Precedence: immediately local, installed version, raysan5 provided libs + LDFLAGS = -L. -L$(RAYLIB_INSTALL_PATH) -L$(RAYLIB_RELEASE_PATH) + endif endif ifeq ($(PLATFORM),PLATFORM_RPI) @@ -224,7 +287,10 @@ endif ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),WINDOWS) # Libraries for Windows desktop compilation - LDLIBS = -lraylib -lopengl32 -lgdi32 + # NOTE: WinMM library required to set high-res timer resolution + LDLIBS = -lraylib -lopengl32 -lgdi32 -lwinmm + # Required for physac examples + #LDLIBS += -static -lpthread endif ifeq ($(PLATFORM_OS),LINUX) # Libraries for Debian GNU/Linux desktop compiling @@ -240,6 +306,10 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(USE_WAYLAND_DISPLAY),TRUE) LDLIBS += -lwayland-client -lwayland-cursor -lwayland-egl -lxkbcommon endif + # Explicit link to libc + ifeq ($(RAYLIB_LIBTYPE),SHARED) + LDLIBS += -lc + endif endif ifeq ($(PLATFORM_OS),OSX) # Libraries for OSX 10.9 desktop compiling @@ -270,12 +340,13 @@ ifeq ($(PLATFORM),PLATFORM_WEB) endif # Define all source files required -PROJECT_SOURCE_FILES ?= transmission.c \ - screens/screen_logo.c \ - screens/screen_title.c \ - screens/screen_mission.c \ - screens/screen_gameplay.c \ - screens/screen_ending.c +PROJECT_SOURCE_FILES ?= \ + transmission.c \ + screens/screen_logo.c \ + screens/screen_title.c \ + screens/screen_mission.c \ + screens/screen_gameplay.c \ + screens/screen_ending.c # Define all object files from source files OBJS = $(patsubst %.c, %.o, $(PROJECT_SOURCE_FILES)) @@ -310,7 +381,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) del *.o *.exe /s endif ifeq ($(PLATFORM_OS),LINUX) - find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -f + find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -fv endif ifeq ($(PLATFORM_OS),OSX) find . -type f -perm +ugo+x -delete @@ -319,7 +390,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) endif ifeq ($(PLATFORM),PLATFORM_RPI) find . -type f -executable -delete - rm -f *.o + rm -fv *.o endif ifeq ($(PLATFORM),PLATFORM_WEB) del *.o *.html *.js diff --git a/games/transmission/Makefile.Android b/games/transmission/Makefile.Android index f082ab230..29d437b1b 100644 --- a/games/transmission/Makefile.Android +++ b/games/transmission/Makefile.Android @@ -22,24 +22,33 @@ #************************************************************************************************** # Define required raylib variables -PLATFORM ?= PLATFORM_ANDROID -RAYLIB_PATH ?= ..\.. +PLATFORM ?= PLATFORM_ANDROID +RAYLIB_PATH ?= ..\.. + +# Define Android architecture (armeabi-v7a, arm64-v8a, x86, x86-64) and API version +ANDROID_ARCH ?= ARM +ANDROID_API_VERSION = 21 +ifeq ($(ANDROID_ARCH),ARM) + ANDROID_ARCH_NAME = armeabi-v7a +endif +ifeq ($(ANDROID_ARCH),ARM64) + ANDROID_ARCH_NAME = arm64-v8a +endif # Required path variables # NOTE: JAVA_HOME must be set to JDK -ANDROID_HOME = C:/android-sdk -ANDROID_NDK = C:/android-ndk -ANDROID_TOOLCHAIN = C:/android_toolchain_arm_api16 -ANDROID_BUILD_TOOLS = $(ANDROID_HOME)/build-tools/26.0.2 -ANDROID_PLATFORM_TOOLS = $(ANDROID_HOME)/platform-tools -JAVA_HOME = C:/PROGRA~1/Java/jdk1.8.0_144 +JAVA_HOME ?= C:/JavaJDK +ANDROID_HOME = C:/android-sdk +ANDROID_TOOLCHAIN = C:/android_toolchain_$(ANDROID_ARCH)_API$(ANDROID_API_VERSION) +ANDROID_BUILD_TOOLS = $(ANDROID_HOME)/build-tools/28.0.1 +ANDROID_PLATFORM_TOOLS = $(ANDROID_HOME)/platform-tools # Android project configuration variables -PROJECT_NAME ?= raylib_game -PROJECT_LIBRARY_NAME ?= main -PROJECT_BUILD_PATH ?= android.$(PROJECT_NAME) +PROJECT_NAME ?= raylib_game +PROJECT_LIBRARY_NAME ?= main +PROJECT_BUILD_PATH ?= android.$(PROJECT_NAME) PROJECT_RESOURCES_PATH ?= resources -PROJECT_SOURCE_FILES ?= raylib_game.c +PROJECT_SOURCE_FILES ?= raylib_game.c # Some source files are placed in directories, when compiling to some # output directory other than source, that directory must pre-exist. @@ -61,30 +70,43 @@ APP_KEYSTORE_PASS ?= raylib # Library type used for raylib: STATIC (.a) or SHARED (.so/.dll) RAYLIB_LIBTYPE ?= STATIC -RAYLIB_LIB_PATH = $(RAYLIB_PATH)\release\libs\android\armeabi-v7a + +# Library path for libraylib.a/libraylib.so +RAYLIB_LIB_PATH = $(RAYLIB_PATH)\src # Shared libs must be added to APK if required # NOTE: Generated NativeLoader.java automatically load those libraries ifeq ($(RAYLIB_LIBTYPE),SHARED) - PROJECT_SHARED_LIBS = lib/armeabi-v7a/libraylib.so + PROJECT_SHARED_LIBS = lib/$(ANDROID_ARCH_NAME)/libraylib.so endif # Compiler and archiver -# NOTE: GCC is being deprectated in Android NDK r16 -CC = $(ANDROID_TOOLCHAIN)/bin/arm-linux-androideabi-gcc -AR = $(ANDROID_TOOLCHAIN)/bin/arm-linux-androideabi-ar +# NOTE: GCC is being deprecated in Android NDK r16 +ifeq ($(ANDROID_ARCH),ARM) + CC = $(ANDROID_TOOLCHAIN)/bin/arm-linux-androideabi-clang + AR = $(ANDROID_TOOLCHAIN)/bin/arm-linux-androideabi-ar +endif +ifeq ($(ANDROID_ARCH),ARM64) + CC = $(ANDROID_TOOLCHAIN)/bin/aarch64-linux-android-clang + AR = $(ANDROID_TOOLCHAIN)/bin/aarch64-linux-android-ar +endif # Compiler flags for arquitecture -CFLAGS = -std=c99 -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 +ifeq ($(ANDROID_ARCH),ARM) + CFLAGS = -std=c99 -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 +endif +ifeq ($(ANDROID_ARCH),ARM64) + CFLAGS = -std=c99 -target aarch64 -mfix-cortex-a53-835769 +endif # Compilation functions attributes options CFLAGS += -ffunction-sections -funwind-tables -fstack-protector-strong -fPIC # Compiler options for the linker CFLAGS += -Wall -Wa,--noexecstack -Wformat -Werror=format-security -no-canonical-prefixes # Preprocessor macro definitions -CFLAGS += -DANDROID -DPLATFORM_ANDROID -D__ANDROID_API__=16 +CFLAGS += -DANDROID -DPLATFORM_ANDROID -D__ANDROID_API__=$(ANDROID_API_VERSION) # Paths containing required header files -INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/release/include -I$(RAYLIB_PATH)/src/external/android/native_app_glue +INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external/android/native_app_glue # Linker options LDFLAGS = -Wl,-soname,lib$(PROJECT_LIBRARY_NAME).so -Wl,--exclude-libs,libatomic.a @@ -92,11 +114,11 @@ LDFLAGS += -Wl,--build-id -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,relro -Wl # Force linking of library module to define symbol LDFLAGS += -u ANativeActivity_onCreate # Library paths containing required libs -LDFLAGS += -L. -L$(PROJECT_BUILD_PATH)/obj -L$(PROJECT_BUILD_PATH)/lib/armeabi-v7a +LDFLAGS += -L. -L$(PROJECT_BUILD_PATH)/obj -L$(PROJECT_BUILD_PATH)/lib/$(ANDROID_ARCH_NAME) -L$(ANDROID_TOOLCHAIN)\sysroot\usr\lib # Define any libraries to link into executable # if you want to link libraries (libname.so or libname.a), use the -lname -LDLIBS = -lraylib -lnative_app_glue -llog -landroid -lEGL -lGLESv2 -lOpenSLES -latomic -lc -lm -ldl +LDLIBS = -lm -lc -lraylib -llog -landroid -lEGL -lGLESv2 -lOpenSLES -ldl # Generate target objects list from PROJECT_SOURCE_FILES OBJS = $(patsubst %.c, $(PROJECT_BUILD_PATH)/obj/%.o, $(PROJECT_SOURCE_FILES)) @@ -110,7 +132,6 @@ all: create_temp_project_dirs \ generate_android_manifest \ generate_apk_keystore \ config_project_package \ - compile_native_app_glue \ compile_project_code \ compile_project_class \ compile_project_class_dex \ @@ -127,7 +148,7 @@ create_temp_project_dirs: if not exist $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME) mkdir $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME) if not exist $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME)\$(APP_PRODUCT_NAME) mkdir $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME)\$(APP_PRODUCT_NAME) if not exist $(PROJECT_BUILD_PATH)\lib mkdir $(PROJECT_BUILD_PATH)\lib - if not exist $(PROJECT_BUILD_PATH)\lib\armeabi-v7a mkdir $(PROJECT_BUILD_PATH)\lib\armeabi-v7a + if not exist $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME) mkdir $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME) if not exist $(PROJECT_BUILD_PATH)\bin mkdir $(PROJECT_BUILD_PATH)\bin if not exist $(PROJECT_BUILD_PATH)\res mkdir $(PROJECT_BUILD_PATH)\res if not exist $(PROJECT_BUILD_PATH)\res\drawable-ldpi mkdir $(PROJECT_BUILD_PATH)\res\drawable-ldpi @@ -147,10 +168,10 @@ endef # NOTE: If using shared libs they are loaded by generated NativeLoader.java copy_project_required_libs: ifeq ($(RAYLIB_LIBTYPE),SHARED) - copy /Y $(RAYLIB_LIB_PATH)\libraylib.so $(PROJECT_BUILD_PATH)\lib\armeabi-v7a\libraylib.so + copy /Y $(RAYLIB_LIB_PATH)\libraylib.so $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME)\libraylib.so endif ifeq ($(RAYLIB_LIBTYPE),STATIC) - copy /Y $(RAYLIB_LIB_PATH)\libraylib.a $(PROJECT_BUILD_PATH)\lib\armeabi-v7a\libraylib.a + copy /Y $(RAYLIB_LIB_PATH)\libraylib.a $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME)\libraylib.a endif # Copy project required resources: strings.xml, icon.png, assets @@ -185,7 +206,7 @@ generate_android_manifest: @echo ^> $(PROJECT_BUILD_PATH)/AndroidManifest.xml @echo package="com.$(APP_COMPANY_NAME).$(APP_PRODUCT_NAME)" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml @echo android:versionCode="$(APP_VERSION_CODE)" android:versionName="$(APP_VERSION_NAME)" ^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml - @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml @echo ^> $(PROJECT_BUILD_PATH)/AndroidManifest.xml @@ -210,7 +231,7 @@ generate_apk_keystore: # Config project package and resource using AndroidManifest.xml and res/values/strings.xml # NOTE: Generates resources file: src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/R.java config_project_package: - $(ANDROID_BUILD_TOOLS)/aapt package -f -m -S $(PROJECT_BUILD_PATH)/res -J $(PROJECT_BUILD_PATH)/src -M $(PROJECT_BUILD_PATH)/AndroidManifest.xml -I $(ANDROID_HOME)/platforms/android-16/android.jar + $(ANDROID_BUILD_TOOLS)/aapt package -f -m -S $(PROJECT_BUILD_PATH)/res -J $(PROJECT_BUILD_PATH)/src -M $(PROJECT_BUILD_PATH)/AndroidManifest.xml -I $(ANDROID_HOME)/platforms/android-$(ANDROID_API_VERSION)/android.jar # Compile native_app_glue code as static library: obj/libnative_app_glue.a compile_native_app_glue: @@ -219,7 +240,7 @@ compile_native_app_glue: # Compile project code into a shared library: lib/lib$(PROJECT_LIBRARY_NAME).so compile_project_code: $(OBJS) - $(CC) -o $(PROJECT_BUILD_PATH)/lib/armeabi-v7a/lib$(PROJECT_LIBRARY_NAME).so $(OBJS) -shared $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) + $(CC) -o $(PROJECT_BUILD_PATH)/lib/$(ANDROID_ARCH_NAME)/lib$(PROJECT_LIBRARY_NAME).so $(OBJS) -shared $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) # Compile all .c files required into object (.o) files # NOTE: Those files will be linked into a shared library @@ -228,7 +249,7 @@ $(PROJECT_BUILD_PATH)/obj/%.o:%.c # Compile project .java code into .class (Java bytecode) compile_project_class: - $(JAVA_HOME)/bin/javac -verbose -source 1.7 -target 1.7 -d $(PROJECT_BUILD_PATH)/obj -bootclasspath $(JAVA_HOME)/jre/lib/rt.jar -classpath $(ANDROID_HOME)/platforms/android-16/android.jar;$(PROJECT_BUILD_PATH)/obj -sourcepath $(PROJECT_BUILD_PATH)/src $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/R.java $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java + $(JAVA_HOME)/bin/javac -verbose -source 1.7 -target 1.7 -d $(PROJECT_BUILD_PATH)/obj -bootclasspath $(JAVA_HOME)/jre/lib/rt.jar -classpath $(ANDROID_HOME)/platforms/android-$(ANDROID_API_VERSION)/android.jar;$(PROJECT_BUILD_PATH)/obj -sourcepath $(PROJECT_BUILD_PATH)/src $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/R.java $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java # Compile .class files into Dalvik executable bytecode (.dex) # NOTE: Since Android 5.0, Dalvik interpreter (JIT) has been replaced by ART (AOT) @@ -239,8 +260,8 @@ compile_project_class_dex: # NOTE: Requires compiled classes.dex and lib$(PROJECT_LIBRARY_NAME).so # NOTE: Use -A resources to define additional directory in which to find raw asset files create_project_apk_package: - $(ANDROID_BUILD_TOOLS)/aapt package -f -M $(PROJECT_BUILD_PATH)/AndroidManifest.xml -S $(PROJECT_BUILD_PATH)/res -A $(PROJECT_BUILD_PATH)/assets -I $(ANDROID_HOME)/platforms/android-16/android.jar -F $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).unsigned.apk $(PROJECT_BUILD_PATH)/bin - cd $(PROJECT_BUILD_PATH) && $(ANDROID_BUILD_TOOLS)/aapt add bin/$(PROJECT_NAME).unsigned.apk lib/armeabi-v7a/lib$(PROJECT_LIBRARY_NAME).so $(PROJECT_SHARED_LIBS) + $(ANDROID_BUILD_TOOLS)/aapt package -f -M $(PROJECT_BUILD_PATH)/AndroidManifest.xml -S $(PROJECT_BUILD_PATH)/res -A $(PROJECT_BUILD_PATH)/assets -I $(ANDROID_HOME)/platforms/android-$(ANDROID_API_VERSION)/android.jar -F $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).unsigned.apk $(PROJECT_BUILD_PATH)/bin + cd $(PROJECT_BUILD_PATH) && $(ANDROID_BUILD_TOOLS)/aapt add bin/$(PROJECT_NAME).unsigned.apk lib/$(ANDROID_ARCH_NAME)/lib$(PROJECT_LIBRARY_NAME).so $(PROJECT_SHARED_LIBS) # Create signed APK package using generated Key: bin/$(PROJECT_NAME).signed.apk sign_project_apk_package: @@ -253,7 +274,11 @@ zipalign_project_apk_package: # Install $(PROJECT_NAME).apk to default emulator/device # NOTE: Use -e (emulator) or -d (device) parameters if required install: - $(ANDROID_PLATFORM_TOOLS)/adb install -r $(PROJECT_NAME).apk + $(ANDROID_PLATFORM_TOOLS)/adb install --abi $(ANDROID_ARCH_NAME) -rds $(PROJECT_NAME).apk + +# Check supported ABI for the device (armeabi-v7a, arm64-v8a, x86, x86_64) +check_device_abi: + $(ANDROID_PLATFORM_TOOLS)/adb shell getprop ro.product.cpu.abi # Monitorize output log coming from device, only raylib tag logcat: diff --git a/games/transmission/screens/screen_ending.c b/games/transmission/screens/screen_ending.c index 0492a0ccc..22c2298be 100644 --- a/games/transmission/screens/screen_ending.c +++ b/games/transmission/screens/screen_ending.c @@ -222,7 +222,7 @@ static char *StringReplace(char *orig, char *rep, char *with) // Count the number of replacements needed ins = orig; - for (count = 0; tmp = strstr(ins, rep); ++count) + for (count = 0; (tmp = strstr(ins, rep)); ++count) { ins = tmp + len_rep; } diff --git a/games/transmission/screens/screen_gameplay.c b/games/transmission/screens/screen_gameplay.c index 3dfce7145..0541c863e 100644 --- a/games/transmission/screens/screen_gameplay.c +++ b/games/transmission/screens/screen_gameplay.c @@ -152,7 +152,7 @@ void InitGameplayScreen(void) { ImageDraw(&imWords, imWordsBase, (Rectangle){ 0, 0, imWordsBase.width, imWordsBase.height }, - (Rectangle){ 0, imWordsBase.height*i, imWordsBase.width, imWordsBase.height }); + (Rectangle){ 0, imWordsBase.height*i, imWordsBase.width, imWordsBase.height }, WHITE); ImageDrawTextEx(&imWords,(Vector2){ imWordsBase.width/2 - MeasureTextEx(fontMessage, codingWords[i], fontMessage.baseSize, 0).x/2, imWordsBase.height*i }, fontMessage, codingWords[i], diff --git a/games/transmission/screens/screen_logo.c b/games/transmission/screens/screen_logo.c index dc016423e..80c998097 100644 --- a/games/transmission/screens/screen_logo.c +++ b/games/transmission/screens/screen_logo.c @@ -26,19 +26,32 @@ #include "raylib.h" #include "screens.h" +#define LOGO_RECS_SIDE 16 + //---------------------------------------------------------------------------------- // Global Variables Definition (local to this module) //---------------------------------------------------------------------------------- // Logo screen global variables -static int framesCounter; -static int finishScreen; +static int framesCounter = 0; +static int finishScreen = 0; -static Texture2D logoCW; +static int logoPositionX = 0; +static int logoPositionY = 0; -static float fadeValue; -static int showLogoFrames; -static bool fadeOut; +static int lettersCount = 0; + +static int topSideRecWidth = 0; +static int leftSideRecHeight = 0; + +static int bottomSideRecWidth = 0; +static int rightSideRecHeight = 0; + +static char raylib[8] = { 0 }; // raylib text array, max 8 letters +static int state = 0; // Tracking animation states (State Machine) +static float alpha = 1.0f; // Useful for fading + +static Texture2D texLogoCW = { 0 }; // Cinamon Works texture //---------------------------------------------------------------------------------- // Logo Screen Functions Definition @@ -47,53 +60,183 @@ static bool fadeOut; // Logo Screen Initialization logic void InitLogoScreen(void) { - framesCounter = 0; + // Initialize LOGO screen variables here! finishScreen = 0; + framesCounter = 0; + lettersCount = 0; - logoCW = LoadTexture("resources/textures/cw_logo.png"); + logoPositionX = GetScreenWidth()/2 - 128; + logoPositionY = GetScreenHeight()/2 - 128; - showLogoFrames = 60; - fadeValue = 0; + topSideRecWidth = LOGO_RECS_SIDE; + leftSideRecHeight = LOGO_RECS_SIDE; + bottomSideRecWidth = LOGO_RECS_SIDE; + rightSideRecHeight = LOGO_RECS_SIDE; - fadeOut = false; + for (int i = 0; i < 8; i++) raylib[i] = '\0'; + + state = 0; + alpha = 1.0f; + + texLogoCW = LoadTexture("resources/textures/cw_logo.png"); } // Logo Screen Update logic void UpdateLogoScreen(void) { - if (!fadeOut) - { - fadeValue += 0.02f; - if (fadeValue > 1.01f) + // Update LOGO screen variables here! + if (state == 0) // State 0: Small box blinking + { + framesCounter++; + + if (framesCounter == 80) { - fadeValue = 1.0f; - framesCounter++; - - if ((framesCounter%showLogoFrames) == 0) + state = 1; + framesCounter = 0; // Reset counter... will be used later... + } + } + else if (state == 1) // State 1: Top and left bars growing + { + topSideRecWidth += 8; + leftSideRecHeight += 8; + + if (topSideRecWidth == 256) state = 2; + } + else if (state == 2) // State 2: Bottom and right bars growing + { + bottomSideRecWidth += 8; + rightSideRecHeight += 8; + + if (bottomSideRecWidth == 256) state = 3; + } + else if (state == 3) // State 3: Letters appearing (one by one) + { + framesCounter++; + + if (framesCounter/10) // Every 12 frames, one more letter! + { + lettersCount++; + framesCounter = 0; + } + + switch (lettersCount) + { + case 1: raylib[0] = 'r'; break; + case 2: raylib[1] = 'a'; break; + case 3: raylib[2] = 'y'; break; + case 4: raylib[3] = 'l'; break; + case 5: raylib[4] = 'i'; break; + case 6: raylib[5] = 'b'; break; + default: break; + } + + // When all letters have appeared... + if (lettersCount >= 10) + { + state = 4; + framesCounter = 0; + } + } + else if (state == 4) + { + framesCounter++; + + if (framesCounter > 100) + { + alpha -= 0.02f; + + if (alpha <= 0.0f) { - fadeOut = true; - finishScreen = true; - } - } - } - - if (IsKeyPressed(KEY_ENTER)) finishScreen = true; + alpha = 0.0f; + framesCounter = 0; + state = 5; + } + } + } + else if (state == 5) + { + alpha += 0.02f; + if (alpha >= 1.0f) alpha = 1.0f; + + framesCounter++; + if (framesCounter > 200) + { + framesCounter = 0; + state = 6; + } + } + else if (state == 6) + { + alpha -= 0.02f; + if (alpha >= 1.0f) alpha = 1.0f; + + framesCounter++; + if (framesCounter > 100) + { + framesCounter = 0; + finishScreen = 1; + } + } } // Logo Screen Draw logic void DrawLogoScreen(void) { - DrawTexture(logoCW, GetScreenWidth()/2 - logoCW.width/2, GetScreenHeight()/2 - logoCW.height/2, Fade(WHITE, fadeValue)); + if (state == 0) + { + if ((framesCounter/10)%2) DrawRectangle(logoPositionX, logoPositionY, 16, 16, BLACK); + } + else if (state == 1) + { + DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, BLACK); + DrawRectangle(logoPositionX, logoPositionY, 16, leftSideRecHeight, BLACK); + } + else if (state == 2) + { + DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, BLACK); + DrawRectangle(logoPositionX, logoPositionY, 16, leftSideRecHeight, BLACK); + + DrawRectangle(logoPositionX + 240, logoPositionY, 16, rightSideRecHeight, BLACK); + DrawRectangle(logoPositionX, logoPositionY + 240, bottomSideRecWidth, 16, BLACK); + } + else if (state == 3) + { + DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, Fade(BLACK, alpha)); + DrawRectangle(logoPositionX, logoPositionY + 16, 16, leftSideRecHeight - 32, Fade(BLACK, alpha)); + + DrawRectangle(logoPositionX + 240, logoPositionY + 16, 16, rightSideRecHeight - 32, Fade(BLACK, alpha)); + DrawRectangle(logoPositionX, logoPositionY + 240, bottomSideRecWidth, 16, Fade(BLACK, alpha)); + + DrawRectangle(GetScreenWidth()/2 - 112, GetScreenHeight()/2 - 112, 224, 224, Fade(RAYWHITE, alpha)); + + DrawText(raylib, GetScreenWidth()/2 - 44, GetScreenHeight()/2 + 48, 50, Fade(BLACK, alpha)); + } + else if (state == 4) + { + DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, Fade(BLACK, alpha)); + DrawRectangle(logoPositionX, logoPositionY + 16, 16, leftSideRecHeight - 32, Fade(BLACK, alpha)); + + DrawRectangle(logoPositionX + 240, logoPositionY + 16, 16, rightSideRecHeight - 32, Fade(BLACK, alpha)); + DrawRectangle(logoPositionX, logoPositionY + 240, bottomSideRecWidth, 16, Fade(BLACK, alpha)); + + DrawRectangle(GetScreenWidth()/2 - 112, GetScreenHeight()/2 - 112, 224, 224, Fade(RAYWHITE, alpha)); + + DrawText(raylib, GetScreenWidth()/2 - 44, GetScreenHeight()/2 + 48, 50, Fade(BLACK, alpha)); + + if (framesCounter > 20) DrawText("powered by", logoPositionX, logoPositionY - 27, 20, Fade(DARKGRAY, alpha)); + } + else if ((state == 5) || (state == 6)) DrawTexture(texLogoCW, GetScreenWidth()/2 - texLogoCW.width/2, GetScreenHeight()/2 - texLogoCW.height/2, Fade(WHITE, alpha)); } // Logo Screen Unload logic void UnloadLogoScreen(void) { - UnloadTexture(logoCW); + // Unload LOGO screen variables here! + UnloadTexture(texLogoCW); } // Logo Screen should finish? int FinishLogoScreen(void) { return finishScreen; -} \ No newline at end of file +} diff --git a/games/transmission/transmission.c b/games/transmission/transmission.c index 9fc3d802b..79097b069 100644 --- a/games/transmission/transmission.c +++ b/games/transmission/transmission.c @@ -1,13 +1,14 @@ /******************************************************************************************* * -* raylib - transmission mission +* TRANSMISSION MISSION [GLOBAL GAME JAM 2018] * -* Code and transmit the right message +* Code the different filtration messages to be send to newspaper +* to avoid being understood in case of interception. * -* This game has been created using raylib (www.raylib.com) +* This game has been created using raylib 1.8 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * -* Copyright (c) 2014-2019 Ramon Santamaria (@raysan5) +* Copyright (c) 2018 Ramon Santamaria (@raysan5) * ********************************************************************************************/ @@ -53,13 +54,9 @@ static void UpdateDrawFrame(void); // Update and Draw one frame //---------------------------------------------------------------------------------- int main(void) { - // Initialization + // Initialization (Note windowTitle is unused on Android) //--------------------------------------------------------- -#ifndef PLATFORM_ANDROID - SetConfigFlags(FLAG_SHOW_LOGO); // | FLAG_FULLSCREEN_MODE); -#endif - // Note windowTitle is unused on Android - InitWindow(screenWidth, screenHeight, "raylib game - transmission mission"); + InitWindow(screenWidth, screenHeight, "transmission mission [GGJ18]"); // Global data loading (assets that must be available in all screens, i.e. fonts) InitAudioDevice(); @@ -73,7 +70,7 @@ int main(void) fontMission = LoadFontEx("resources/fonts/traveling_typewriter.ttf", 64, 0, 250); texButton = LoadTexture("resources/textures/title_ribbon.png"); - // UI BUTTON + // UI BUTTON recButton.width = texButton.width; recButton.height = texButton.height; recButton.x = screenWidth - recButton.width; @@ -124,7 +121,7 @@ int main(void) UnloadFont(fontMission); UnloadTexture(texButton); - + CloseAudioDevice(); // Close audio context CloseWindow(); // Close window and OpenGL context @@ -441,7 +438,7 @@ bool IsButtonPressed() } } else fadeButton = 0.80f; - + return false; } diff --git a/games/wave_collector/Makefile b/games/wave_collector/Makefile index 703383b89..894cc7e7d 100644 --- a/games/wave_collector/Makefile +++ b/games/wave_collector/Makefile @@ -24,28 +24,43 @@ .PHONY: all clean # Define required raylib variables -# WARNING: To compile to HTML5, code must be redesigned to use emscripten.h and emscripten_set_main_loop() -PLATFORM ?= PLATFORM_DESKTOP -RAYLIB_PATH ?= ..\.. -PROJECT_NAME ?= wave_collector +PROJECT_NAME ?= wave_collector +RAYLIB_VERSION ?= 2.5.0 +RAYLIB_API_VERSION ?= 2 +RAYLIB_PATH ?= C:\GitHub\raylib -# Default path for raylib on Raspberry Pi, if installed in different path, update it! -ifeq ($(PLATFORM),PLATFORM_RPI) - RAYLIB_PATH ?= /home/pi/raylib -endif +# Define default options + +# One of PLATFORM_DESKTOP, PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB +PLATFORM ?= PLATFORM_DESKTOP + +# Locations of your newly installed library and associated headers. See ../src/Makefile +# On Linux, if you have installed raylib but cannot compile the examples, check that +# the *_INSTALL_PATH values here are the same as those in src/Makefile or point to known locations. +# To enable system-wide compile-time and runtime linking to libraylib.so, run ../src/$ sudo make install RAYLIB_LIBTYPE_SHARED. +# To enable compile-time linking to a special version of libraylib.so, change these variables here. +# To enable runtime linking to a special version of libraylib.so, see EXAMPLE_RUNTIME_PATH below. +# If there is a libraylib in both EXAMPLE_RUNTIME_PATH and RAYLIB_INSTALL_PATH, at runtime, +# the library at EXAMPLE_RUNTIME_PATH, if present, will take precedence over the one at RAYLIB_INSTALL_PATH. +# RAYLIB_INSTALL_PATH should be the desired full path to libraylib. No relative paths. +DESTDIR ?= /usr/local +RAYLIB_INSTALL_PATH ?= $(DESTDIR)/lib +# RAYLIB_H_INSTALL_PATH locates the installed raylib header and associated source files. +RAYLIB_H_INSTALL_PATH ?= $(DESTDIR)/include # Library type used for raylib: STATIC (.a) or SHARED (.so/.dll) -RAYLIB_LIBTYPE ?= STATIC +RAYLIB_LIBTYPE ?= STATIC + +# Build mode for project: DEBUG or RELEASE +BUILD_MODE ?= RELEASE # Use external GLFW library instead of rglfw module -USE_EXTERNAL_GLFW ?= FALSE +# TODO: Review usage on Linux. Target version of choice. Switch on -lglfw or -lglfw3 +USE_EXTERNAL_GLFW ?= FALSE # Use Wayland display server protocol on Linux desktop # by default it uses X11 windowing system -USE_WAYLAND_DISPLAY ?= FALSE - -# NOTE: On PLATFORM_WEB OpenAL Soft backend is used by default (check raylib/src/Makefile) - +USE_WAYLAND_DISPLAY ?= FALSE # Determine PLATFORM_OS in case PLATFORM_DESKTOP selected ifeq ($(PLATFORM),PLATFORM_DESKTOP) @@ -82,40 +97,50 @@ ifeq ($(PLATFORM),PLATFORM_RPI) endif endif +# RAYLIB_PATH adjustment for different platforms. +# If using GNU make, we can get the full path to the top of the tree. Windows? BSD? +# Required for ldconfig or other tools that do not perform path expansion. +ifeq ($(PLATFORM),PLATFORM_DESKTOP) + ifeq ($(PLATFORM_OS),LINUX) + RAYLIB_PREFIX ?= .. + RAYLIB_PATH = $(realpath $(RAYLIB_PREFIX)) + endif +endif +# Default path for raylib on Raspberry Pi, if installed in different path, update it! +# This is not currently used by src/Makefile. Not sure of its origin or usage. Refer to wiki. +# TODO: update install: target in src/Makefile for RPI, consider relation to LINUX. +ifeq ($(PLATFORM),PLATFORM_RPI) + RAYLIB_PATH ?= /home/pi/raylib +endif + ifeq ($(PLATFORM),PLATFORM_WEB) # Emscripten required variables - EMSDK_PATH = C:/emsdk - EMSCRIPTEN_VERSION = 1.37.28 - CLANG_VERSION=e1.37.28_64bit - PYTHON_VERSION=2.7.5.3_64bit - NODE_VERSION=4.1.1_64bit - export PATH=$(EMSDK_PATH);$(EMSDK_PATH)\clang\$(CLANG_VERSION);$(EMSDK_PATH)\node\$(NODE_VERSION)\bin;$(EMSDK_PATH)\python\$(PYTHON_VERSION);$(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION);C:\raylib\MinGW\bin:$$(PATH) - EMSCRIPTEN=$(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION) + EMSDK_PATH ?= C:/emsdk + EMSCRIPTEN_VERSION ?= 1.38.32 + CLANG_VERSION = e$(EMSCRIPTEN_VERSION)_64bit + PYTHON_VERSION = 2.7.13.1_64bit\python-2.7.13.amd64 + NODE_VERSION = 8.9.1_64bit + export PATH = $(EMSDK_PATH);$(EMSDK_PATH)\clang\$(CLANG_VERSION);$(EMSDK_PATH)\node\$(NODE_VERSION)\bin;$(EMSDK_PATH)\python\$(PYTHON_VERSION);$(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION);C:\raylib\MinGW\bin:$$(PATH) + EMSCRIPTEN = $(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION) endif -RAYLIB_RELEASE_PATH ?= $(RAYLIB_PATH)/release/libs +# Define raylib release directory for compiled library. +# RAYLIB_RELEASE_PATH points to provided binaries or your freshly built version +RAYLIB_RELEASE_PATH ?= $(RAYLIB_PATH)/src -# Define raylib release directory for compiled library -ifeq ($(PLATFORM),PLATFORM_DESKTOP) - ifeq ($(PLATFORM_OS),WINDOWS) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/win32/mingw32 - endif - ifeq ($(PLATFORM_OS),LINUX) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/linux - endif - ifeq ($(PLATFORM_OS),OSX) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/osx - endif - ifeq ($(PLATFORM_OS),BSD) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/bsd - endif -endif -ifeq ($(PLATFORM),PLATFORM_RPI) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/rpi -endif -ifeq ($(PLATFORM),PLATFORM_WEB) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/html5 -endif +# EXAMPLE_RUNTIME_PATH embeds a custom runtime location of libraylib.so or other desired libraries +# into each example binary compiled with RAYLIB_LIBTYPE=SHARED. It defaults to RAYLIB_RELEASE_PATH +# so that these examples link at runtime with your version of libraylib.so in ../release/libs/linux +# without formal installation from ../src/Makefile. It aids portability and is useful if you have +# multiple versions of raylib, have raylib installed to a non-standard location, or want to +# bundle libraylib.so with your game. Change it to your liking. +# NOTE: If, at runtime, there is a libraylib.so at both EXAMPLE_RUNTIME_PATH and RAYLIB_INSTALL_PATH, +# The library at EXAMPLE_RUNTIME_PATH, if present, will take precedence over RAYLIB_INSTALL_PATH, +# Implemented for LINUX below with CFLAGS += -Wl,-rpath,$(EXAMPLE_RUNTIME_PATH) +# To see the result, run readelf -d core/core_basic_window; looking at the RPATH or RUNPATH attribute. +# To see which libraries a built example is linking to, ldd core/core_basic_window; +# Look for libraylib.so.1 => $(RAYLIB_INSTALL_PATH)/libraylib.so.1 or similar listing. +EXAMPLE_RUNTIME_PATH ?= $(RAYLIB_RELEASE_PATH) # Define default C compiler: gcc # NOTE: define g++ compiler if using C++ @@ -140,6 +165,8 @@ ifeq ($(PLATFORM),PLATFORM_RPI) endif ifeq ($(PLATFORM),PLATFORM_WEB) # HTML5 emscripten compiler + # WARNING: To compile to HTML5, code must be redesigned + # to use emscripten.h and emscripten_set_main_loop() CC = emcc endif @@ -154,7 +181,7 @@ endif # Define compiler flags: # -O1 defines optimization level -# -g enable debugging +# -g include debug information on compilation # -s strip unnecessary data from build # -Wall turns on most, but not all, compiler warnings # -std=c99 defines C language mode (standard C from 1999 revision) @@ -163,56 +190,92 @@ endif # -D_DEFAULT_SOURCE use with -std=c99 on Linux and PLATFORM_WEB, required for timespec CFLAGS += -O1 -s -Wall -std=c99 -D_DEFAULT_SOURCE -Wno-missing-braces +ifeq ($(BUILD_MODE),DEBUG) + CFLAGS += -g +endif + # Additional flags for compiler (if desired) #CFLAGS += -Wextra -Wmissing-prototypes -Wstrict-prototypes ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),WINDOWS) - # resources file contains windows exe icon + # resource file contains windows executable icon and properties # -Wl,--subsystem,windows hides the console window CFLAGS += $(RAYLIB_PATH)/raylib.rc.data -Wl,--subsystem,windows endif ifeq ($(PLATFORM_OS),LINUX) - CFLAGS += -D_DEFAULT_SOURCE + ifeq ($(RAYLIB_LIBTYPE),STATIC) + CFLAGS += -D_DEFAULT_SOURCE + endif + ifeq ($(RAYLIB_LIBTYPE),SHARED) + # Explicitly enable runtime link to libraylib.so + CFLAGS += -Wl,-rpath,$(EXAMPLE_RUNTIME_PATH) + endif endif endif ifeq ($(PLATFORM),PLATFORM_RPI) CFLAGS += -std=gnu99 endif ifeq ($(PLATFORM),PLATFORM_WEB) - # -O2 # if used, also set --memory-init-file 0 - # --memory-init-file 0 # to avoid an external memory initialization code file (.mem) - # -s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing + # -Os # size optimization + # -O2 # optimization level 2, if used, also set --memory-init-file 0 + # -s USE_GLFW=3 # Use glfw3 library (context/input management) + # -s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing -> WARNING: Audio buffers could FAIL! # -s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB) # -s USE_PTHREADS=1 # multithreading support - # -s WASM=1 # support Web Assembly (https://github.com/kripken/emscripten/wiki/WebAssembly) + # -s WASM=0 # disable Web Assembly, emitted by default + # -s EMTERPRETIFY=1 # enable emscripten code interpreter (very slow) + # -s EMTERPRETIFY_ASYNC=1 # support synchronous loops by emterpreter + # -s FORCE_FILESYSTEM=1 # force filesystem to load/save files data + # -s ASSERTIONS=1 # enable runtime checks for common memory allocation errors (-O1 and above turn it off) + # --profiling # include information for code profiling + # --memory-init-file 0 # to avoid an external memory initialization code file (.mem) # --preload-file resources # specify a resources folder for data compilation - CFLAGS += -s USE_GLFW=3 -s ASSERTIONS=1 -s WASM=1 --profiling --preload-file resources - + CFLAGS += -Os -s USE_GLFW=3 -s TOTAL_MEMORY=67108864 --preload-file resources + ifeq ($(BUILD_MODE), DEBUG) + CFLAGS += -s ASSERTIONS=1 --profiling + endif + # Define a custom shell .html and output extension - CFLAGS += --shell-file $(RAYLIB_PATH)\templates\web_shell\shell.html + CFLAGS += --shell-file $(RAYLIB_PATH)/src/shell.html EXT = .html endif # Define include paths for required headers # NOTE: Several external required libraries (stb and others) -INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/release/include -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external +INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external # Define additional directories containing required header files ifeq ($(PLATFORM),PLATFORM_RPI) - # RPI requried libraries + # RPI required libraries INCLUDE_PATHS += -I/opt/vc/include INCLUDE_PATHS += -I/opt/vc/include/interface/vmcs_host/linux INCLUDE_PATHS += -I/opt/vc/include/interface/vcos/pthreads endif +ifeq ($(PLATFORM),PLATFORM_DESKTOP) + ifeq ($(PLATFORM_OS),BSD) + # Consider -L$(RAYLIB_H_INSTALL_PATH) + INCLUDE_PATHS += -I/usr/local/include + endif + ifeq ($(PLATFORM_OS),LINUX) + # Reset everything. + # Precedence: immediately local, installed version, raysan5 provided libs -I$(RAYLIB_H_INSTALL_PATH) -I$(RAYLIB_PATH)/release/include + INCLUDE_PATHS = -I$(RAYLIB_H_INSTALL_PATH) -isystem. -isystem$(RAYLIB_PATH)/src -isystem$(RAYLIB_PATH)/release/include -isystem$(RAYLIB_PATH)/src/external + endif +endif -# Define library paths containing required libs -LDFLAGS = -L. -L$(RAYLIB_RELEASE_PATH) -L$(RAYLIB_PATH)/src +# Define library paths containing required libs. +LDFLAGS = -L. -L$(RAYLIB_RELEASE_PATH) -L$(RAYLIB_PATH)/src ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),BSD) - INCLUDE_PATHS += -I/usr/local/include + # Consider -L$(RAYLIB_INSTALL_PATH) LDFLAGS += -L. -Lsrc -L/usr/local/lib endif + ifeq ($(PLATFORM_OS),LINUX) + # Reset everything. + # Precedence: immediately local, installed version, raysan5 provided libs + LDFLAGS = -L. -L$(RAYLIB_INSTALL_PATH) -L$(RAYLIB_RELEASE_PATH) + endif endif ifeq ($(PLATFORM),PLATFORM_RPI) @@ -224,7 +287,10 @@ endif ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),WINDOWS) # Libraries for Windows desktop compilation - LDLIBS = -lraylib -lopengl32 -lgdi32 + # NOTE: WinMM library required to set high-res timer resolution + LDLIBS = -lraylib -lopengl32 -lgdi32 -lwinmm + # Required for physac examples + #LDLIBS += -static -lpthread endif ifeq ($(PLATFORM_OS),LINUX) # Libraries for Debian GNU/Linux desktop compiling @@ -240,6 +306,10 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(USE_WAYLAND_DISPLAY),TRUE) LDLIBS += -lwayland-client -lwayland-cursor -lwayland-egl -lxkbcommon endif + # Explicit link to libc + ifeq ($(RAYLIB_LIBTYPE),SHARED) + LDLIBS += -lc + endif endif ifeq ($(PLATFORM_OS),OSX) # Libraries for OSX 10.9 desktop compiling @@ -247,7 +317,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) LDLIBS = -lraylib -framework OpenGL -framework OpenAL -framework Cocoa endif ifeq ($(PLATFORM_OS),BSD) - # Libraries for FreeBSD desktop compiling + # Libraries for FreeBSD, OpenBSD, NetBSD, DragonFly desktop compiling # NOTE: Required packages: mesa-libs LDLIBS = -lraylib -lGL -lpthread -lm @@ -270,11 +340,12 @@ ifeq ($(PLATFORM),PLATFORM_WEB) endif # Define all source files required -PROJECT_SOURCE_FILES ?= wave_collector.c \ - screens/screen_logo.c \ - screens/screen_title.c \ - screens/screen_gameplay.c \ - screens/screen_ending.c +PROJECT_SOURCE_FILES ?= \ + wave_collector.c \ + screens/screen_logo.c \ + screens/screen_title.c \ + screens/screen_gameplay.c \ + screens/screen_ending.c # Define all object files from source files OBJS = $(patsubst %.c, %.o, $(PROJECT_SOURCE_FILES)) @@ -309,7 +380,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) del *.o *.exe /s endif ifeq ($(PLATFORM_OS),LINUX) - find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -f + find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -fv endif ifeq ($(PLATFORM_OS),OSX) find . -type f -perm +ugo+x -delete @@ -318,7 +389,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) endif ifeq ($(PLATFORM),PLATFORM_RPI) find . -type f -executable -delete - rm -f *.o + rm -fv *.o endif ifeq ($(PLATFORM),PLATFORM_WEB) del *.o *.html *.js diff --git a/games/wave_collector/Makefile.Android b/games/wave_collector/Makefile.Android index f082ab230..29d437b1b 100644 --- a/games/wave_collector/Makefile.Android +++ b/games/wave_collector/Makefile.Android @@ -22,24 +22,33 @@ #************************************************************************************************** # Define required raylib variables -PLATFORM ?= PLATFORM_ANDROID -RAYLIB_PATH ?= ..\.. +PLATFORM ?= PLATFORM_ANDROID +RAYLIB_PATH ?= ..\.. + +# Define Android architecture (armeabi-v7a, arm64-v8a, x86, x86-64) and API version +ANDROID_ARCH ?= ARM +ANDROID_API_VERSION = 21 +ifeq ($(ANDROID_ARCH),ARM) + ANDROID_ARCH_NAME = armeabi-v7a +endif +ifeq ($(ANDROID_ARCH),ARM64) + ANDROID_ARCH_NAME = arm64-v8a +endif # Required path variables # NOTE: JAVA_HOME must be set to JDK -ANDROID_HOME = C:/android-sdk -ANDROID_NDK = C:/android-ndk -ANDROID_TOOLCHAIN = C:/android_toolchain_arm_api16 -ANDROID_BUILD_TOOLS = $(ANDROID_HOME)/build-tools/26.0.2 -ANDROID_PLATFORM_TOOLS = $(ANDROID_HOME)/platform-tools -JAVA_HOME = C:/PROGRA~1/Java/jdk1.8.0_144 +JAVA_HOME ?= C:/JavaJDK +ANDROID_HOME = C:/android-sdk +ANDROID_TOOLCHAIN = C:/android_toolchain_$(ANDROID_ARCH)_API$(ANDROID_API_VERSION) +ANDROID_BUILD_TOOLS = $(ANDROID_HOME)/build-tools/28.0.1 +ANDROID_PLATFORM_TOOLS = $(ANDROID_HOME)/platform-tools # Android project configuration variables -PROJECT_NAME ?= raylib_game -PROJECT_LIBRARY_NAME ?= main -PROJECT_BUILD_PATH ?= android.$(PROJECT_NAME) +PROJECT_NAME ?= raylib_game +PROJECT_LIBRARY_NAME ?= main +PROJECT_BUILD_PATH ?= android.$(PROJECT_NAME) PROJECT_RESOURCES_PATH ?= resources -PROJECT_SOURCE_FILES ?= raylib_game.c +PROJECT_SOURCE_FILES ?= raylib_game.c # Some source files are placed in directories, when compiling to some # output directory other than source, that directory must pre-exist. @@ -61,30 +70,43 @@ APP_KEYSTORE_PASS ?= raylib # Library type used for raylib: STATIC (.a) or SHARED (.so/.dll) RAYLIB_LIBTYPE ?= STATIC -RAYLIB_LIB_PATH = $(RAYLIB_PATH)\release\libs\android\armeabi-v7a + +# Library path for libraylib.a/libraylib.so +RAYLIB_LIB_PATH = $(RAYLIB_PATH)\src # Shared libs must be added to APK if required # NOTE: Generated NativeLoader.java automatically load those libraries ifeq ($(RAYLIB_LIBTYPE),SHARED) - PROJECT_SHARED_LIBS = lib/armeabi-v7a/libraylib.so + PROJECT_SHARED_LIBS = lib/$(ANDROID_ARCH_NAME)/libraylib.so endif # Compiler and archiver -# NOTE: GCC is being deprectated in Android NDK r16 -CC = $(ANDROID_TOOLCHAIN)/bin/arm-linux-androideabi-gcc -AR = $(ANDROID_TOOLCHAIN)/bin/arm-linux-androideabi-ar +# NOTE: GCC is being deprecated in Android NDK r16 +ifeq ($(ANDROID_ARCH),ARM) + CC = $(ANDROID_TOOLCHAIN)/bin/arm-linux-androideabi-clang + AR = $(ANDROID_TOOLCHAIN)/bin/arm-linux-androideabi-ar +endif +ifeq ($(ANDROID_ARCH),ARM64) + CC = $(ANDROID_TOOLCHAIN)/bin/aarch64-linux-android-clang + AR = $(ANDROID_TOOLCHAIN)/bin/aarch64-linux-android-ar +endif # Compiler flags for arquitecture -CFLAGS = -std=c99 -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 +ifeq ($(ANDROID_ARCH),ARM) + CFLAGS = -std=c99 -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 +endif +ifeq ($(ANDROID_ARCH),ARM64) + CFLAGS = -std=c99 -target aarch64 -mfix-cortex-a53-835769 +endif # Compilation functions attributes options CFLAGS += -ffunction-sections -funwind-tables -fstack-protector-strong -fPIC # Compiler options for the linker CFLAGS += -Wall -Wa,--noexecstack -Wformat -Werror=format-security -no-canonical-prefixes # Preprocessor macro definitions -CFLAGS += -DANDROID -DPLATFORM_ANDROID -D__ANDROID_API__=16 +CFLAGS += -DANDROID -DPLATFORM_ANDROID -D__ANDROID_API__=$(ANDROID_API_VERSION) # Paths containing required header files -INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/release/include -I$(RAYLIB_PATH)/src/external/android/native_app_glue +INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external/android/native_app_glue # Linker options LDFLAGS = -Wl,-soname,lib$(PROJECT_LIBRARY_NAME).so -Wl,--exclude-libs,libatomic.a @@ -92,11 +114,11 @@ LDFLAGS += -Wl,--build-id -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,relro -Wl # Force linking of library module to define symbol LDFLAGS += -u ANativeActivity_onCreate # Library paths containing required libs -LDFLAGS += -L. -L$(PROJECT_BUILD_PATH)/obj -L$(PROJECT_BUILD_PATH)/lib/armeabi-v7a +LDFLAGS += -L. -L$(PROJECT_BUILD_PATH)/obj -L$(PROJECT_BUILD_PATH)/lib/$(ANDROID_ARCH_NAME) -L$(ANDROID_TOOLCHAIN)\sysroot\usr\lib # Define any libraries to link into executable # if you want to link libraries (libname.so or libname.a), use the -lname -LDLIBS = -lraylib -lnative_app_glue -llog -landroid -lEGL -lGLESv2 -lOpenSLES -latomic -lc -lm -ldl +LDLIBS = -lm -lc -lraylib -llog -landroid -lEGL -lGLESv2 -lOpenSLES -ldl # Generate target objects list from PROJECT_SOURCE_FILES OBJS = $(patsubst %.c, $(PROJECT_BUILD_PATH)/obj/%.o, $(PROJECT_SOURCE_FILES)) @@ -110,7 +132,6 @@ all: create_temp_project_dirs \ generate_android_manifest \ generate_apk_keystore \ config_project_package \ - compile_native_app_glue \ compile_project_code \ compile_project_class \ compile_project_class_dex \ @@ -127,7 +148,7 @@ create_temp_project_dirs: if not exist $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME) mkdir $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME) if not exist $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME)\$(APP_PRODUCT_NAME) mkdir $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME)\$(APP_PRODUCT_NAME) if not exist $(PROJECT_BUILD_PATH)\lib mkdir $(PROJECT_BUILD_PATH)\lib - if not exist $(PROJECT_BUILD_PATH)\lib\armeabi-v7a mkdir $(PROJECT_BUILD_PATH)\lib\armeabi-v7a + if not exist $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME) mkdir $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME) if not exist $(PROJECT_BUILD_PATH)\bin mkdir $(PROJECT_BUILD_PATH)\bin if not exist $(PROJECT_BUILD_PATH)\res mkdir $(PROJECT_BUILD_PATH)\res if not exist $(PROJECT_BUILD_PATH)\res\drawable-ldpi mkdir $(PROJECT_BUILD_PATH)\res\drawable-ldpi @@ -147,10 +168,10 @@ endef # NOTE: If using shared libs they are loaded by generated NativeLoader.java copy_project_required_libs: ifeq ($(RAYLIB_LIBTYPE),SHARED) - copy /Y $(RAYLIB_LIB_PATH)\libraylib.so $(PROJECT_BUILD_PATH)\lib\armeabi-v7a\libraylib.so + copy /Y $(RAYLIB_LIB_PATH)\libraylib.so $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME)\libraylib.so endif ifeq ($(RAYLIB_LIBTYPE),STATIC) - copy /Y $(RAYLIB_LIB_PATH)\libraylib.a $(PROJECT_BUILD_PATH)\lib\armeabi-v7a\libraylib.a + copy /Y $(RAYLIB_LIB_PATH)\libraylib.a $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME)\libraylib.a endif # Copy project required resources: strings.xml, icon.png, assets @@ -185,7 +206,7 @@ generate_android_manifest: @echo ^> $(PROJECT_BUILD_PATH)/AndroidManifest.xml @echo package="com.$(APP_COMPANY_NAME).$(APP_PRODUCT_NAME)" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml @echo android:versionCode="$(APP_VERSION_CODE)" android:versionName="$(APP_VERSION_NAME)" ^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml - @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml @echo ^> $(PROJECT_BUILD_PATH)/AndroidManifest.xml @@ -210,7 +231,7 @@ generate_apk_keystore: # Config project package and resource using AndroidManifest.xml and res/values/strings.xml # NOTE: Generates resources file: src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/R.java config_project_package: - $(ANDROID_BUILD_TOOLS)/aapt package -f -m -S $(PROJECT_BUILD_PATH)/res -J $(PROJECT_BUILD_PATH)/src -M $(PROJECT_BUILD_PATH)/AndroidManifest.xml -I $(ANDROID_HOME)/platforms/android-16/android.jar + $(ANDROID_BUILD_TOOLS)/aapt package -f -m -S $(PROJECT_BUILD_PATH)/res -J $(PROJECT_BUILD_PATH)/src -M $(PROJECT_BUILD_PATH)/AndroidManifest.xml -I $(ANDROID_HOME)/platforms/android-$(ANDROID_API_VERSION)/android.jar # Compile native_app_glue code as static library: obj/libnative_app_glue.a compile_native_app_glue: @@ -219,7 +240,7 @@ compile_native_app_glue: # Compile project code into a shared library: lib/lib$(PROJECT_LIBRARY_NAME).so compile_project_code: $(OBJS) - $(CC) -o $(PROJECT_BUILD_PATH)/lib/armeabi-v7a/lib$(PROJECT_LIBRARY_NAME).so $(OBJS) -shared $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) + $(CC) -o $(PROJECT_BUILD_PATH)/lib/$(ANDROID_ARCH_NAME)/lib$(PROJECT_LIBRARY_NAME).so $(OBJS) -shared $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) # Compile all .c files required into object (.o) files # NOTE: Those files will be linked into a shared library @@ -228,7 +249,7 @@ $(PROJECT_BUILD_PATH)/obj/%.o:%.c # Compile project .java code into .class (Java bytecode) compile_project_class: - $(JAVA_HOME)/bin/javac -verbose -source 1.7 -target 1.7 -d $(PROJECT_BUILD_PATH)/obj -bootclasspath $(JAVA_HOME)/jre/lib/rt.jar -classpath $(ANDROID_HOME)/platforms/android-16/android.jar;$(PROJECT_BUILD_PATH)/obj -sourcepath $(PROJECT_BUILD_PATH)/src $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/R.java $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java + $(JAVA_HOME)/bin/javac -verbose -source 1.7 -target 1.7 -d $(PROJECT_BUILD_PATH)/obj -bootclasspath $(JAVA_HOME)/jre/lib/rt.jar -classpath $(ANDROID_HOME)/platforms/android-$(ANDROID_API_VERSION)/android.jar;$(PROJECT_BUILD_PATH)/obj -sourcepath $(PROJECT_BUILD_PATH)/src $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/R.java $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java # Compile .class files into Dalvik executable bytecode (.dex) # NOTE: Since Android 5.0, Dalvik interpreter (JIT) has been replaced by ART (AOT) @@ -239,8 +260,8 @@ compile_project_class_dex: # NOTE: Requires compiled classes.dex and lib$(PROJECT_LIBRARY_NAME).so # NOTE: Use -A resources to define additional directory in which to find raw asset files create_project_apk_package: - $(ANDROID_BUILD_TOOLS)/aapt package -f -M $(PROJECT_BUILD_PATH)/AndroidManifest.xml -S $(PROJECT_BUILD_PATH)/res -A $(PROJECT_BUILD_PATH)/assets -I $(ANDROID_HOME)/platforms/android-16/android.jar -F $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).unsigned.apk $(PROJECT_BUILD_PATH)/bin - cd $(PROJECT_BUILD_PATH) && $(ANDROID_BUILD_TOOLS)/aapt add bin/$(PROJECT_NAME).unsigned.apk lib/armeabi-v7a/lib$(PROJECT_LIBRARY_NAME).so $(PROJECT_SHARED_LIBS) + $(ANDROID_BUILD_TOOLS)/aapt package -f -M $(PROJECT_BUILD_PATH)/AndroidManifest.xml -S $(PROJECT_BUILD_PATH)/res -A $(PROJECT_BUILD_PATH)/assets -I $(ANDROID_HOME)/platforms/android-$(ANDROID_API_VERSION)/android.jar -F $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).unsigned.apk $(PROJECT_BUILD_PATH)/bin + cd $(PROJECT_BUILD_PATH) && $(ANDROID_BUILD_TOOLS)/aapt add bin/$(PROJECT_NAME).unsigned.apk lib/$(ANDROID_ARCH_NAME)/lib$(PROJECT_LIBRARY_NAME).so $(PROJECT_SHARED_LIBS) # Create signed APK package using generated Key: bin/$(PROJECT_NAME).signed.apk sign_project_apk_package: @@ -253,7 +274,11 @@ zipalign_project_apk_package: # Install $(PROJECT_NAME).apk to default emulator/device # NOTE: Use -e (emulator) or -d (device) parameters if required install: - $(ANDROID_PLATFORM_TOOLS)/adb install -r $(PROJECT_NAME).apk + $(ANDROID_PLATFORM_TOOLS)/adb install --abi $(ANDROID_ARCH_NAME) -rds $(PROJECT_NAME).apk + +# Check supported ABI for the device (armeabi-v7a, arm64-v8a, x86, x86_64) +check_device_abi: + $(ANDROID_PLATFORM_TOOLS)/adb shell getprop ro.product.cpu.abi # Monitorize output log coming from device, only raylib tag logcat: diff --git a/games/wave_collector/wave_collector.c b/games/wave_collector/wave_collector.c index 0a04310d4..64881816d 100644 --- a/games/wave_collector/wave_collector.c +++ b/games/wave_collector/wave_collector.c @@ -1,6 +1,6 @@ /******************************************************************************************* * -* GLOBAL GAME JAM 2017 - WAVE COLLECTOR +* WAVE COLLECTOR [GLOBAL GAME JAM 2017] * * The ultimate wave particles collector is here! * You must follow the wave and collect all the particles @@ -58,8 +58,8 @@ static void UpdateDrawFrame(void); // Update and Draw one frame //---------------------------------------------------------------------------------- int main(int argc, char *argv[]) { - // Initialization - //--------------------------------------------------------- + // Initialization + //--------------------------------------------------------- #if defined(PLATFORM_DESKTOP) // TODO: Support for dropped files on the exe @@ -85,7 +85,7 @@ int main(int argc, char *argv[]) SetConfigFlags(FLAG_MSAA_4X_HINT); #endif // Note windowTitle is unused on Android - InitWindow(screenWidth, screenHeight, "GGJ17 - WAVE COLLECTOR"); + InitWindow(screenWidth, screenHeight, "WAVE COLLECTOR [GGJ17]"); // Global data loading (assets that must be available in all screens, i.e. fonts) InitAudioDevice(); @@ -299,7 +299,7 @@ static void UpdateDrawFrame(void) case ENDING: DrawEndingScreen(); break; default: break; } - + // Draw full screen rectangle in front of everything if (onTransition) DrawTransition(); diff --git a/projects/4coder/Makefile b/projects/4coder/Makefile index 3cffaaba1..08d4da59a 100644 --- a/projects/4coder/Makefile +++ b/projects/4coder/Makefile @@ -24,29 +24,43 @@ .PHONY: all clean # Define required raylib variables -# WARNING: To compile to HTML5, code must be redesigned to use emscripten.h and emscripten_set_main_loop() -PLATFORM ?= PLATFORM_DESKTOP -RAYLIB_PATH ?= ../.. -PROJECT_NAME ?= game -DEBUGGING ?= FALSE +PROJECT_NAME ?= game +RAYLIB_VERSION ?= 2.5.0 +RAYLIB_API_VERSION ?= 2 +RAYLIB_PATH ?= ..\.. -# Default path for raylib on Raspberry Pi, if installed in different path, update it! -ifeq ($(PLATFORM),PLATFORM_RPI) - RAYLIB_PATH ?= /home/pi/raylib -endif +# Define default options + +# One of PLATFORM_DESKTOP, PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB +PLATFORM ?= PLATFORM_DESKTOP + +# Locations of your newly installed library and associated headers. See ../src/Makefile +# On Linux, if you have installed raylib but cannot compile the examples, check that +# the *_INSTALL_PATH values here are the same as those in src/Makefile or point to known locations. +# To enable system-wide compile-time and runtime linking to libraylib.so, run ../src/$ sudo make install RAYLIB_LIBTYPE_SHARED. +# To enable compile-time linking to a special version of libraylib.so, change these variables here. +# To enable runtime linking to a special version of libraylib.so, see EXAMPLE_RUNTIME_PATH below. +# If there is a libraylib in both EXAMPLE_RUNTIME_PATH and RAYLIB_INSTALL_PATH, at runtime, +# the library at EXAMPLE_RUNTIME_PATH, if present, will take precedence over the one at RAYLIB_INSTALL_PATH. +# RAYLIB_INSTALL_PATH should be the desired full path to libraylib. No relative paths. +DESTDIR ?= /usr/local +RAYLIB_INSTALL_PATH ?= $(DESTDIR)/lib +# RAYLIB_H_INSTALL_PATH locates the installed raylib header and associated source files. +RAYLIB_H_INSTALL_PATH ?= $(DESTDIR)/include # Library type used for raylib: STATIC (.a) or SHARED (.so/.dll) -RAYLIB_LIBTYPE ?= STATIC +RAYLIB_LIBTYPE ?= STATIC + +# Build mode for project: DEBUG or RELEASE +BUILD_MODE ?= RELEASE # Use external GLFW library instead of rglfw module -USE_EXTERNAL_GLFW ?= FALSE +# TODO: Review usage on Linux. Target version of choice. Switch on -lglfw or -lglfw3 +USE_EXTERNAL_GLFW ?= FALSE # Use Wayland display server protocol on Linux desktop # by default it uses X11 windowing system -USE_WAYLAND_DISPLAY ?= FALSE - -# NOTE: On PLATFORM_WEB OpenAL Soft backend is used by default (check raylib/src/Makefile) - +USE_WAYLAND_DISPLAY ?= FALSE # Determine PLATFORM_OS in case PLATFORM_DESKTOP selected ifeq ($(PLATFORM),PLATFORM_DESKTOP) @@ -54,7 +68,6 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) # ifeq ($(UNAME),Msys) -> Windows ifeq ($(OS),Windows_NT) PLATFORM_OS=WINDOWS - export PATH := C:/raylib/mingw32/bin:$(PATH) else UNAMEOS=$(shell uname) ifeq ($(UNAMEOS),Linux) @@ -84,40 +97,50 @@ ifeq ($(PLATFORM),PLATFORM_RPI) endif endif +# RAYLIB_PATH adjustment for different platforms. +# If using GNU make, we can get the full path to the top of the tree. Windows? BSD? +# Required for ldconfig or other tools that do not perform path expansion. +ifeq ($(PLATFORM),PLATFORM_DESKTOP) + ifeq ($(PLATFORM_OS),LINUX) + RAYLIB_PREFIX ?= .. + RAYLIB_PATH = $(realpath $(RAYLIB_PREFIX)) + endif +endif +# Default path for raylib on Raspberry Pi, if installed in different path, update it! +# This is not currently used by src/Makefile. Not sure of its origin or usage. Refer to wiki. +# TODO: update install: target in src/Makefile for RPI, consider relation to LINUX. +ifeq ($(PLATFORM),PLATFORM_RPI) + RAYLIB_PATH ?= /home/pi/raylib +endif + ifeq ($(PLATFORM),PLATFORM_WEB) # Emscripten required variables - EMSDK_PATH = C:/emsdk - EMSCRIPTEN_VERSION = 1.38.8 - CLANG_VERSION = e1.38.8_64bit + EMSDK_PATH ?= C:/emsdk + EMSCRIPTEN_VERSION ?= 1.38.31 + CLANG_VERSION = e$(EMSCRIPTEN_VERSION)_64bit PYTHON_VERSION = 2.7.13.1_64bit\python-2.7.13.amd64 NODE_VERSION = 8.9.1_64bit export PATH = $(EMSDK_PATH);$(EMSDK_PATH)\clang\$(CLANG_VERSION);$(EMSDK_PATH)\node\$(NODE_VERSION)\bin;$(EMSDK_PATH)\python\$(PYTHON_VERSION);$(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION);C:\raylib\MinGW\bin:$$(PATH) EMSCRIPTEN = $(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION) endif -RAYLIB_RELEASE_PATH ?= $(RAYLIB_PATH)/release/libs +# Define raylib release directory for compiled library. +# RAYLIB_RELEASE_PATH points to provided binaries or your freshly built version +RAYLIB_RELEASE_PATH ?= $(RAYLIB_PATH)/src -# Define raylib release directory for compiled library -ifeq ($(PLATFORM),PLATFORM_DESKTOP) - ifeq ($(PLATFORM_OS),WINDOWS) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/win32/mingw32 - endif - ifeq ($(PLATFORM_OS),LINUX) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/linux - endif - ifeq ($(PLATFORM_OS),OSX) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/osx - endif - ifeq ($(PLATFORM_OS),BSD) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/bsd - endif -endif -ifeq ($(PLATFORM),PLATFORM_RPI) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/rpi -endif -ifeq ($(PLATFORM),PLATFORM_WEB) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/html5 -endif +# EXAMPLE_RUNTIME_PATH embeds a custom runtime location of libraylib.so or other desired libraries +# into each example binary compiled with RAYLIB_LIBTYPE=SHARED. It defaults to RAYLIB_RELEASE_PATH +# so that these examples link at runtime with your version of libraylib.so in ../release/libs/linux +# without formal installation from ../src/Makefile. It aids portability and is useful if you have +# multiple versions of raylib, have raylib installed to a non-standard location, or want to +# bundle libraylib.so with your game. Change it to your liking. +# NOTE: If, at runtime, there is a libraylib.so at both EXAMPLE_RUNTIME_PATH and RAYLIB_INSTALL_PATH, +# The library at EXAMPLE_RUNTIME_PATH, if present, will take precedence over RAYLIB_INSTALL_PATH, +# Implemented for LINUX below with CFLAGS += -Wl,-rpath,$(EXAMPLE_RUNTIME_PATH) +# To see the result, run readelf -d core/core_basic_window; looking at the RPATH or RUNPATH attribute. +# To see which libraries a built example is linking to, ldd core/core_basic_window; +# Look for libraylib.so.1 => $(RAYLIB_INSTALL_PATH)/libraylib.so.1 or similar listing. +EXAMPLE_RUNTIME_PATH ?= $(RAYLIB_RELEASE_PATH) # Define default C compiler: gcc # NOTE: define g++ compiler if using C++ @@ -142,6 +165,8 @@ ifeq ($(PLATFORM),PLATFORM_RPI) endif ifeq ($(PLATFORM),PLATFORM_WEB) # HTML5 emscripten compiler + # WARNING: To compile to HTML5, code must be redesigned + # to use emscripten.h and emscripten_set_main_loop() CC = emcc endif @@ -152,78 +177,105 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),LINUX) MAKE = make endif - ifeq ($(PLATFORM_OS),OSX) - MAKE = make - endif endif # Define compiler flags: # -O1 defines optimization level -# -g enable debugging +# -g include debug information on compilation # -s strip unnecessary data from build # -Wall turns on most, but not all, compiler warnings # -std=c99 defines C language mode (standard C from 1999 revision) # -std=gnu99 defines C language mode (GNU C from 1999 revision) # -Wno-missing-braces ignore invalid warning (GCC bug 53119) # -D_DEFAULT_SOURCE use with -std=c99 on Linux and PLATFORM_WEB, required for timespec -ifeq ($(DEBUGGING), TRUE) +CFLAGS += -O1 -s -Wall -std=c99 -D_DEFAULT_SOURCE -Wno-missing-braces + +ifeq ($(BUILD_MODE),DEBUG) CFLAGS += -g -else - CFLAGS += -O1 -s endif -CFLAGS += -Wall -std=c99 -D_DEFAULT_SOURCE -Wno-missing-braces # Additional flags for compiler (if desired) #CFLAGS += -Wextra -Wmissing-prototypes -Wstrict-prototypes ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),WINDOWS) - # resources file contains windows exe icon + # resource file contains windows executable icon and properties # -Wl,--subsystem,windows hides the console window - CFLAGS += -Wl,--subsystem,windows - LDFLAGS += $(RAYLIB_PATH)/raylib.rc.data + CFLAGS += $(RAYLIB_PATH)/src/raylib.rc.data -Wl,--subsystem,windows endif ifeq ($(PLATFORM_OS),LINUX) - CFLAGS += -D_DEFAULT_SOURCE + ifeq ($(RAYLIB_LIBTYPE),STATIC) + CFLAGS += -D_DEFAULT_SOURCE + endif + ifeq ($(RAYLIB_LIBTYPE),SHARED) + # Explicitly enable runtime link to libraylib.so + CFLAGS += -Wl,-rpath,$(EXAMPLE_RUNTIME_PATH) + endif endif endif ifeq ($(PLATFORM),PLATFORM_RPI) CFLAGS += -std=gnu99 endif ifeq ($(PLATFORM),PLATFORM_WEB) - # -O2 # if used, also set --memory-init-file 0 - # --memory-init-file 0 # to avoid an external memory initialization code file (.mem) - # -s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing + # -Os # size optimization + # -O2 # optimization level 2, if used, also set --memory-init-file 0 + # -s USE_GLFW=3 # Use glfw3 library (context/input management) + # -s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing -> WARNING: Audio buffers could FAIL! # -s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB) # -s USE_PTHREADS=1 # multithreading support - # -s WASM=1 # support Web Assembly (https://github.com/kripken/emscripten/wiki/WebAssembly) + # -s WASM=0 # disable Web Assembly, emitted by default + # -s EMTERPRETIFY=1 # enable emscripten code interpreter (very slow) + # -s EMTERPRETIFY_ASYNC=1 # support synchronous loops by emterpreter + # -s FORCE_FILESYSTEM=1 # force filesystem to load/save files data + # -s ASSERTIONS=1 # enable runtime checks for common memory allocation errors (-O1 and above turn it off) + # --profiling # include information for code profiling + # --memory-init-file 0 # to avoid an external memory initialization code file (.mem) # --preload-file resources # specify a resources folder for data compilation - CFLAGS += -s USE_GLFW=3 -s ASSERTIONS=1 -s WASM=1 --profiling --preload-file resources - + CFLAGS += -Os -s USE_GLFW=3 -s TOTAL_MEMORY=16777216 --preload-file resources + ifeq ($(BUILD_MODE), DEBUG) + CFLAGS += -s ASSERTIONS=1 --profiling + endif + # Define a custom shell .html and output extension - CFLAGS += --shell-file $(RAYLIB_PATH)\templates\web_shell\shell.html + CFLAGS += --shell-file $(RAYLIB_PATH)/src/shell.html EXT = .html endif # Define include paths for required headers # NOTE: Several external required libraries (stb and others) -INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/release/include -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external +INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external # Define additional directories containing required header files ifeq ($(PLATFORM),PLATFORM_RPI) - # RPI requried libraries + # RPI required libraries INCLUDE_PATHS += -I/opt/vc/include INCLUDE_PATHS += -I/opt/vc/include/interface/vmcs_host/linux INCLUDE_PATHS += -I/opt/vc/include/interface/vcos/pthreads endif +ifeq ($(PLATFORM),PLATFORM_DESKTOP) + ifeq ($(PLATFORM_OS),BSD) + # Consider -L$(RAYLIB_H_INSTALL_PATH) + INCLUDE_PATHS += -I/usr/local/include + endif + ifeq ($(PLATFORM_OS),LINUX) + # Reset everything. + # Precedence: immediately local, installed version, raysan5 provided libs -I$(RAYLIB_H_INSTALL_PATH) -I$(RAYLIB_PATH)/release/include + INCLUDE_PATHS = -I$(RAYLIB_H_INSTALL_PATH) -isystem. -isystem$(RAYLIB_PATH)/src -isystem$(RAYLIB_PATH)/release/include -isystem$(RAYLIB_PATH)/src/external + endif +endif -# Define library paths containing required libs -LDFLAGS += -L. -L$(RAYLIB_RELEASE_PATH) -L$(RAYLIB_PATH)/src +# Define library paths containing required libs. +LDFLAGS = -L. -L$(RAYLIB_RELEASE_PATH) -L$(RAYLIB_PATH)/src ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),BSD) - INCLUDE_PATHS += -I/usr/local/include + # Consider -L$(RAYLIB_INSTALL_PATH) LDFLAGS += -L. -Lsrc -L/usr/local/lib endif + ifeq ($(PLATFORM_OS),LINUX) + # Reset everything. + # Precedence: immediately local, installed version, raysan5 provided libs + LDFLAGS = -L. -L$(RAYLIB_INSTALL_PATH) -L$(RAYLIB_RELEASE_PATH) + endif endif ifeq ($(PLATFORM),PLATFORM_RPI) @@ -235,8 +287,8 @@ endif ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),WINDOWS) # Libraries for Windows desktop compilation - LDLIBS = -lraylib -lopengl32 -lgdi32 - + # NOTE: WinMM library required to set high-res timer resolution + LDLIBS = -lraylib -lopengl32 -lgdi32 -lwinmm # Required for physac examples #LDLIBS += -static -lpthread endif @@ -254,11 +306,15 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(USE_WAYLAND_DISPLAY),TRUE) LDLIBS += -lwayland-client -lwayland-cursor -lwayland-egl -lxkbcommon endif + # Explicit link to libc + ifeq ($(RAYLIB_LIBTYPE),SHARED) + LDLIBS += -lc + endif endif ifeq ($(PLATFORM_OS),OSX) # Libraries for OSX 10.9 desktop compiling # NOTE: Required packages: libopenal-dev libegl1-mesa-dev - LDLIBS = -lraylib -framework OpenGL -framework Cocoa -framework IOKit -framework CoreFoundation -framework CoreVideo + LDLIBS = -lraylib -framework OpenGL -framework OpenAL -framework Cocoa endif ifeq ($(PLATFORM_OS),BSD) # Libraries for FreeBSD, OpenBSD, NetBSD, DragonFly desktop compiling @@ -326,7 +382,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) del *.o *.exe /s endif ifeq ($(PLATFORM_OS),LINUX) - find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -f + find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -fv endif ifeq ($(PLATFORM_OS),OSX) find . -type f -perm +ugo+x -delete @@ -335,7 +391,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) endif ifeq ($(PLATFORM),PLATFORM_RPI) find . -type f -executable -delete - rm -f *.o + rm -fv *.o endif ifeq ($(PLATFORM),PLATFORM_WEB) del *.o *.html *.js diff --git a/projects/4coder/Makefile.Android b/projects/4coder/Makefile.Android index b6c68417f..29d437b1b 100644 --- a/projects/4coder/Makefile.Android +++ b/projects/4coder/Makefile.Android @@ -22,33 +22,33 @@ #************************************************************************************************** # Define required raylib variables -PLATFORM ?= PLATFORM_ANDROID -RAYLIB_PATH ?= ..\.. +PLATFORM ?= PLATFORM_ANDROID +RAYLIB_PATH ?= ..\.. # Define Android architecture (armeabi-v7a, arm64-v8a, x86, x86-64) and API version -ANDROID_ARCH ?= ARM -ANDROID_API_VERSION = 21 +ANDROID_ARCH ?= ARM +ANDROID_API_VERSION = 21 ifeq ($(ANDROID_ARCH),ARM) - ANDROID_ARCH_NAME = armeabi-v7a + ANDROID_ARCH_NAME = armeabi-v7a endif ifeq ($(ANDROID_ARCH),ARM64) - ANDROID_ARCH_NAME = arm64-v8a + ANDROID_ARCH_NAME = arm64-v8a endif # Required path variables # NOTE: JAVA_HOME must be set to JDK -JAVA_HOME ?= C:/JavaJDK -ANDROID_HOME = C:/android-sdk -ANDROID_TOOLCHAIN = C:/android_toolchain_$(ANDROID_ARCH)_API$(ANDROID_API_VERSION) -ANDROID_BUILD_TOOLS = $(ANDROID_HOME)/build-tools/28.0.1 -ANDROID_PLATFORM_TOOLS = $(ANDROID_HOME)/platform-tools +JAVA_HOME ?= C:/JavaJDK +ANDROID_HOME = C:/android-sdk +ANDROID_TOOLCHAIN = C:/android_toolchain_$(ANDROID_ARCH)_API$(ANDROID_API_VERSION) +ANDROID_BUILD_TOOLS = $(ANDROID_HOME)/build-tools/28.0.1 +ANDROID_PLATFORM_TOOLS = $(ANDROID_HOME)/platform-tools # Android project configuration variables -PROJECT_NAME ?= raylib_game -PROJECT_LIBRARY_NAME ?= main -PROJECT_BUILD_PATH ?= android.$(PROJECT_NAME) +PROJECT_NAME ?= raylib_game +PROJECT_LIBRARY_NAME ?= main +PROJECT_BUILD_PATH ?= android.$(PROJECT_NAME) PROJECT_RESOURCES_PATH ?= resources -PROJECT_SOURCE_FILES ?= raylib_game.c +PROJECT_SOURCE_FILES ?= raylib_game.c # Some source files are placed in directories, when compiling to some # output directory other than source, that directory must pre-exist. @@ -70,7 +70,9 @@ APP_KEYSTORE_PASS ?= raylib # Library type used for raylib: STATIC (.a) or SHARED (.so/.dll) RAYLIB_LIBTYPE ?= STATIC -RAYLIB_LIB_PATH = $(RAYLIB_PATH)\release\libs\android\$(ANDROID_ARCH_NAME) + +# Library path for libraylib.a/libraylib.so +RAYLIB_LIB_PATH = $(RAYLIB_PATH)\src # Shared libs must be added to APK if required # NOTE: Generated NativeLoader.java automatically load those libraries @@ -104,7 +106,7 @@ CFLAGS += -Wall -Wa,--noexecstack -Wformat -Werror=format-security -no-canonical CFLAGS += -DANDROID -DPLATFORM_ANDROID -D__ANDROID_API__=$(ANDROID_API_VERSION) # Paths containing required header files -INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/release/include -I$(RAYLIB_PATH)/src/external/android/native_app_glue +INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external/android/native_app_glue # Linker options LDFLAGS = -Wl,-soname,lib$(PROJECT_LIBRARY_NAME).so -Wl,--exclude-libs,libatomic.a diff --git a/projects/4coder/main.c b/projects/4coder/main.c index e79184226..47e16b885 100644 --- a/projects/4coder/main.c +++ b/projects/4coder/main.c @@ -2,38 +2,38 @@ #include "raylib.h" int main() { - int screenWidth = 800; - int screenHeight = 450; + int screenWidth = 800; + int screenHeight = 450; - InitWindow(screenWidth, screenHeight, "raylib"); + InitWindow(screenWidth, screenHeight, "raylib"); - Camera cam; - cam.position = (Vector3){ 0.f, 10.f, 8.f }; - cam.target = (Vector3){ 0.f, 0.f, 0.f }; - cam.up = (Vector3){ 0.f, 1.f, 0.f }; - cam.fovy = 60.f; - cam.type = CAMERA_PERSPECTIVE; + Camera cam; + cam.position = (Vector3){ 0.f, 10.f, 8.f }; + cam.target = (Vector3){ 0.f, 0.f, 0.f }; + cam.up = (Vector3){ 0.f, 1.f, 0.f }; + cam.fovy = 60.f; + cam.type = CAMERA_PERSPECTIVE; - Vector3 cubePos = { 0.f, 0.f, 0.f }; + Vector3 cubePos = { 0.f, 0.f, 0.f }; - SetTargetFPS(60); + SetTargetFPS(60); - while (!WindowShouldClose()) { - cam.position.x = sin(GetTime()) * 10.f; - cam.position.z = cos(GetTime()) * 10.f; + while (!WindowShouldClose()) { + cam.position.x = sin(GetTime()) * 10.f; + cam.position.z = cos(GetTime()) * 10.f; - BeginDrawing(); - ClearBackground(RAYWHITE); - BeginMode3D(cam); - DrawCube(cubePos, 2.f, 2.f, 2.f, RED); - DrawCubeWires(cubePos, 2.f, 2.f, 2.f, MAROON); - DrawGrid(10, 1.f); - EndMode3D(); - DrawText("This is a raylib example", 10, 40, 20, DARKGRAY); - DrawFPS(10, 10); - EndDrawing(); - } - - CloseWindow(); - return 0; + BeginDrawing(); + ClearBackground(RAYWHITE); + BeginMode3D(cam); + DrawCube(cubePos, 2.f, 2.f, 2.f, RED); + DrawCubeWires(cubePos, 2.f, 2.f, 2.f, MAROON); + DrawGrid(10, 1.f); + EndMode3D(); + DrawText("This is a raylib example", 10, 40, 20, DARKGRAY); + DrawFPS(10, 10); + EndDrawing(); + } + + CloseWindow(); + return 0; } \ No newline at end of file diff --git a/projects/CMake/CMakeLists.txt b/projects/CMake/CMakeLists.txt index cf1d65a62..ef0d3c1b1 100644 --- a/projects/CMake/CMakeLists.txt +++ b/projects/CMake/CMakeLists.txt @@ -1,7 +1,8 @@ cmake_minimum_required(VERSION 3.11) # FetchContent is available in 3.11+ project(example) -find_package(raylib 2.0 QUIET) # Let CMake search for a raylib-config.cmake +# Set this to the minimal version you want to support +find_package(raylib 2.5 QUIET) # Let CMake search for a raylib-config.cmake # You could change the QUIET above to REQUIRED and remove this if() clause # This part downloads raylib and builds it if it's not installed on your system diff --git a/projects/CodeBlocks/core_basic_window.cbp b/projects/CodeBlocks/core_basic_window.cbp index 10390e256..c4b22a9e0 100644 --- a/projects/CodeBlocks/core_basic_window.cbp +++ b/projects/CodeBlocks/core_basic_window.cbp @@ -13,11 +13,11 @@