diff options
51 files changed, 1121 insertions, 1195 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d98ffea..6d5994f4 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,7 @@ option(BUILD_EXAMPLES "Build the examples." ON) option(BUILD_GAMES "Build the example games." ON) option(ENABLE_ASAN "Enable AddressSanitizer (ASAN) for debugging (degrades performance)" OFF) option(ENABLE_UBSAN "Enable UndefinedBehaviorSanitizer (UBSan) for debugging" OFF) +option(ENABLE_MSAN "Enable MemorySanitizer (MSan) for debugging (not recommended for run with ASAN)" OFF) if(CMAKE_VERSION VERSION_LESS "3.1") if(CMAKE_C_COMPILER_ID STREQUAL "GNU") @@ -40,6 +41,14 @@ if (ENABLE_UBSAN) add_if_flag_works(-fno-omit-frame-pointer CMAKE_C_FLAGS CMAKE_LINKER_FLAGS) add_if_flag_works(-fsanitize=undefined CMAKE_C_FLAGS CMAKE_LINKER_FLAGS) endif() +if (ENABLE_MSAN) + add_if_flag_works(-fno-omit-frame-pointer CMAKE_C_FLAGS CMAKE_LINKER_FLAGS) + add_if_flag_works(-fsanitize=memory CMAKE_C_FLAGS CMAKE_LINKER_FLAGS) +endif() + +if (ENABLE_MSAN AND ENABLE_ASAN) + MESSAGE(WARNING "Compiling with both AddressSanitizer and MemorySanitizer is not recommended") +endif() add_subdirectory(src release) @@ -73,12 +73,12 @@ attached to 3d models or used as fullscreen postrocessing effects. A bunch of po 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/develop/src/camera.c) module offers to the user multiple preconfigured ready-to-use camera systems (free camera, 1st person, 3rd person). -Camera modes are very easy to use, just check examples: [core_3d_camera_free.c](https://github.com/raysan5/raylib/blob/develop/examples/core_3d_camera_free.c) and [core_3d_camera_first_person.c](https://github.com/raysan5/raylib/blob/develop/examples/core_3d_camera_first_person.c). +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/develop/src/gestures.h) module simplifies gestures detection on Android and HTML5 programs. +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/develop/src/raygui.h), the new IMGUI (Immediate Mode GUI) module offers a set of functions to create simple user interfaces, +[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. Most of the examples have been completely rewritten and +10 new examples have been added to show the new raylib features. @@ -91,18 +91,18 @@ 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. -First big addition is a set of [Image manipulation functions](https://github.com/raysan5/raylib/blob/develop/src/raylib.h#L673) have been added to crop, resize, colorize, flip, dither and even draw image-to-image or text-to-image. +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. -New [physac](https://github.com/raysan5/raylib/blob/develop/src/physac.h) physics module for basic 2D physics support. Still in development but already functional. +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/develop/src/raymath.h) module has been reviewed; some bugs have been solved and the module has been converted to a header-only file for easier portability, optionally, functions can also be used as inline. +[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/develop/src/gestures.c) module has redesigned and simplified, now it can process touch events from any source, including mouse. +[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`). @@ -110,7 +110,7 @@ Gamepad support has also been added (experimental). Other important improvements are the functional raycast system for 3D picking, including some ray collision-detection functions, and the addition of two simple functions for persistent data storage. Now raylib user can save and load game data in a file (only some platforms supported). -A simple [easings](https://github.com/raysan5/raylib/blob/develop/src/easings.h) module has also been added for values animation. +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. @@ -122,7 +122,7 @@ notes on raylib 1.5 On July 2016, after 5 months of raylib 1.4 release, arrives raylib 1.5. This new version is the biggest boost of the library until now, lots of parts of the library have been redesigned, lots of bugs have been solved and some **AMAZING** new features have been added. -VR support: raylib supports **Oculus Rift CV1**, one of the most anticipated VR devices in the market. Additionally, raylib supports simulated VR stereo rendering, independent of the VR device; it means, raylib can generate stereo renders with custom head-mounted-display device parameteres, that way, any VR device in the market can be **simulated in any platform** just configuring device parameters (and consequently, lens distortion). To enable VR is [extremely easy](https://github.com/raysan5/raylib/blob/develop/examples/core_oculus_rift.c). +VR support: raylib supports **Oculus Rift CV1**, one of the most anticipated VR devices in the market. Additionally, raylib supports simulated VR stereo rendering, independent of the VR device; it means, raylib can generate stereo renders with custom head-mounted-display device parameteres, that way, any VR device in the market can be **simulated in any platform** just configuring device parameters (and consequently, lens distortion). To enable VR is [extremely easy](https://github.com/raysan5/raylib/blob/master/examples/core_oculus_rift.c). New materials system: now raylib supports standard material properties for 3D models, including diffuse-ambient-specular colors and diffuse-normal-specular textures. Just assign values to standard material and everything is processed internally. @@ -130,15 +130,15 @@ New lighting system: added support for up to 8 configurable lights and 3 light t Complete gamepad support on Raspberry Pi: Gamepad system has been completely redesigned. Now multiple gamepads can be easily configured and used; gamepad data is read and processed in raw mode in a second thread. -Redesigned physics module: [physac](https://github.com/raysan5/raylib/blob/develop/src/physac.h) module has been converted to header only and usage [has been simplified](https://github.com/raysan5/raylib/blob/develop/examples/physics_basic_rigidbody.c). Performance has also been singnificantly improved, now physic objects are managed internally in a second thread. +Redesigned physics module: [physac](https://github.com/raysan5/raylib/blob/master/src/physac.h) module has been converted to header only and usage [has been simplified](https://github.com/raysan5/raylib/blob/master/examples/physics_basic_rigidbody.c). Performance has also been singnificantly improved, now physic objects are managed internally in a second thread. Audio chiptunese support and mixing channels: Added support for module audio music (.xm, .mod) loading and playing. Multiple mixing channels are now also supported. All this features thanks to the amazing work of @kd7tck. -Other additions include a [2D camera system](https://github.com/raysan5/raylib/blob/develop/examples/core_2d_camera.c), render textures for offline render (and most comprehensive [postprocessing](https://github.com/raysan5/raylib/blob/develop/examples/shaders_postprocessing.c)) or support for legacy OpenGL 2.1 on desktop platforms. +Other additions include a [2D camera system](https://github.com/raysan5/raylib/blob/master/examples/core_2d_camera.c), render textures for offline render (and most comprehensive [postprocessing](https://github.com/raysan5/raylib/blob/master/examples/shaders_postprocessing.c)) or support for legacy OpenGL 2.1 on desktop platforms. -This new version is so massive that is difficult to list all the improvements, most of raylib modules have been reviewed and [rlgl](https://github.com/raysan5/raylib/blob/develop/src/rlgl.c) module has been completely redesigned to accomodate to new material-lighting systems and stereo rendering. You can check [CHANGELOG](https://github.com/raysan5/raylib/blob/develop/CHANGELOG) file for a more detailed list of changes. +This new version is so massive that is difficult to list all the improvements, most of raylib modules have been reviewed and [rlgl](https://github.com/raysan5/raylib/blob/master/src/rlgl.c) module has been completely redesigned to accomodate to new material-lighting systems and stereo rendering. You can check [CHANGELOG](https://github.com/raysan5/raylib/blob/master/CHANGELOG) file for a more detailed list of changes. -Up to 8 new code examples have been added to show the new raylib features and also some samples to show the usage of [rlgl](https://github.com/raysan5/raylib/blob/develop/examples/rlgl_standalone.c) and [audio](https://github.com/raysan5/raylib/blob/develop/examples/audio_standalone.c) raylib modules as standalone libraries. +Up to 8 new code examples have been added to show the new raylib features and also some samples to show the usage of [rlgl](https://github.com/raysan5/raylib/blob/master/examples/rlgl_standalone.c) and [audio](https://github.com/raysan5/raylib/blob/master/examples/audio_standalone.c) raylib modules as standalone libraries. Lots of code changes (+400 commits) and lots of hours of hard work have concluded in this amazing new raylib 1.5. @@ -149,7 +149,7 @@ On November 2016, only 4 months after raylib 1.5, arrives raylib 1.6. This new v Complete [raylib Lua binding](https://github.com/raysan5/raylib-lua). All raylib functions plus the +60 code examples have been ported to Lua, now Lua users can enjoy coding videogames in Lua while using all the internal power of raylib. This addition also open the doors to Lua scripting support for a future raylib-based engine, being able to move game logic (Init, Update, Draw, De-Init) to Lua scripts while keep using raylib functionality. -Completely redesigned [audio module](https://github.com/raysan5/raylib/blob/develop/src/audio.c). Based on the new direction taken in raylib 1.5, it has been further improved and more functionality added (+20 new functions) to allow raw audio processing and streaming. [FLAC file format support](https://github.com/raysan5/raylib/blob/develop/src/external/dr_flac.h) has also been added. In the same line, [OpenAL Soft](https://github.com/kcat/openal-soft) backend is now provided as a static library in Windows to allow static linking and get ride of OpenAL32.dll. Now raylib Windows games are completey self-contained, no external libraries required any more! +Completely redesigned [audio module](https://github.com/raysan5/raylib/blob/master/src/audio.c). Based on the new direction taken in raylib 1.5, it has been further improved and more functionality added (+20 new functions) to allow raw audio processing and streaming. [FLAC file format support](https://github.com/raysan5/raylib/blob/master/src/external/dr_flac.h) has also been added. In the same line, [OpenAL Soft](https://github.com/kcat/openal-soft) backend is now provided as a static library in Windows to allow static linking and get ride of OpenAL32.dll. Now raylib Windows games are completey self-contained, no external libraries required any more! [Physac](https://github.com/victorfisac/Physac) module has been moved to its own repository and it has been improved A LOT, actually, library has been completely rewritten from scratch by [@victorfisac](https://github.com/victorfisac), multiple samples have been added together with countless new features to match current standard 2D physic libraries. Results are amazing! @@ -187,17 +187,17 @@ notes on raylib 1.8 October 2017, around 5 months after latest raylib version, another release is published: raylib 1.8. Again, several modules of the library have been reviewed and some new functionality added. Main changes of this new release are: -[Procedural image generation](https://github.com/raysan5/raylib/blob/develop/examples/textures/textures_image_generation.c) function, a set of new functions have been added to generate gradients, checked, noise and cellular images from scratch. Image generation could be useful for certain textures or learning pourpouses. +[Procedural image generation](https://github.com/raysan5/raylib/blob/master/examples/textures/textures_image_generation.c) function, a set of new functions have been added to generate gradients, checked, noise and cellular images from scratch. Image generation could be useful for certain textures or learning pourpouses. -[Parametric mesh generation](https://github.com/raysan5/raylib/blob/develop/examples/models/models_mesh_generation.c) functions, create 3d meshes from scratch just defining a set of parameters, meshes like cube, sphere, cylinder, torus, knot and more can be very useful for prototyping or for lighting and texture testing. +[Parametric mesh generation](https://github.com/raysan5/raylib/blob/master/examples/models/models_mesh_generation.c) functions, create 3d meshes from scratch just defining a set of parameters, meshes like cube, sphere, cylinder, torus, knot and more can be very useful for prototyping or for lighting and texture testing. -PBR Materials support, a completely redesigned shaders and material system allows advance materials definition and usage, with fully customizable shaders. Some new functions have been added to generate the environment textures required for PBR shading and a a new complete [PBR material example](https://github.com/raysan5/raylib/blob/develop/examples/models/models_material_pbr.c) is also provided for reference. +PBR Materials support, a completely redesigned shaders and material system allows advance materials definition and usage, with fully customizable shaders. Some new functions have been added to generate the environment textures required for PBR shading and a a new complete [PBR material example](https://github.com/raysan5/raylib/blob/master/examples/models/models_material_pbr.c) is also provided for reference. -Custom Android APK build pipeline with [simple Makefile](https://github.com/raysan5/raylib/blob/develop/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. +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/develop/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/develop/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.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. -[raymath](https://github.com/raysan5/raylib/blob/develop/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/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. 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). @@ -13,6 +13,7 @@ pure spartan-programmers way. Are you ready to learn? Jump to [code examples!](h [](https://travis-ci.org/raysan5/raylib) [](https://ci.appveyor.com/project/raysan5/raylib) [](https://gitter.im/raylib/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) +[](https://discord.gg/VkzNHUE) [](LICENSE.md) [](https://twitter.com/raysan5) diff --git a/examples/models/models_material_pbr.c b/examples/models/models_material_pbr.c index 9f576348..d98d7eac 100644 --- a/examples/models/models_material_pbr.c +++ b/examples/models/models_material_pbr.c @@ -113,7 +113,7 @@ static Material LoadMaterialPBR(Color albedo, float metalness, float roughness) mat.shader.locs[LOC_MAP_METALNESS] = GetShaderLocation(mat.shader, "metalness.sampler"); mat.shader.locs[LOC_MAP_NORMAL] = GetShaderLocation(mat.shader, "normals.sampler"); mat.shader.locs[LOC_MAP_ROUGHNESS] = GetShaderLocation(mat.shader, "roughness.sampler"); - mat.shader.locs[LOC_MAP_OCCUSION] = GetShaderLocation(mat.shader, "occlusion.sampler"); + mat.shader.locs[LOC_MAP_OCCLUSION] = GetShaderLocation(mat.shader, "occlusion.sampler"); //mat.shader.locs[LOC_MAP_EMISSION] = GetShaderLocation(mat.shader, "emission.sampler"); //mat.shader.locs[LOC_MAP_HEIGHT] = GetShaderLocation(mat.shader, "height.sampler"); mat.shader.locs[LOC_MAP_IRRADIANCE] = GetShaderLocation(mat.shader, "irradianceMap"); diff --git a/examples/models/models_orthographic_projection.c b/examples/models/models_orthographic_projection.c new file mode 100644 index 00000000..2c2a89d1 --- /dev/null +++ b/examples/models/models_orthographic_projection.c @@ -0,0 +1,112 @@ +/******************************************************************************************* +* +* 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.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" + +#define FOVY_PERSPECTIVE 45.0f +#define WIDTH_ORTHOGRAPHIC 10.0f + +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + int screenWidth = 800; + 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 }; + + 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 + //---------------------------------------------------------------------------------- + // + + // Input + //---------------------------------------------------------------------------------- + if(IsKeyPressed(KEY_SPACE)) + { + if(camera.type == CAMERA_PERSPECTIVE) + { + camera.fovy = WIDTH_ORTHOGRAPHIC; + camera.type = CAMERA_ORTHOGRAPHIC; + } + else + { + camera.fovy = FOVY_PERSPECTIVE; + camera.type = CAMERA_PERSPECTIVE; + } + } + + + // Draw + //---------------------------------------------------------------------------------- + + + BeginDrawing(); + + ClearBackground(RAYWHITE); + + Begin3dMode(camera); + + DrawCube((Vector3){-4.0f, 0.0f, 2.0f}, 2.0f, 5.0f, 2.0f, RED); + DrawCubeWires((Vector3){-4.0f, 0.0f, 2.0f}, 2.0f, 5.0f, 2.0f, GOLD); + DrawCubeWires((Vector3){-4.0f, 0.0f, -2.0f}, 3.0f, 6.0f, 2.0f, MAROON); + + DrawSphere((Vector3){-1.0f, 0.0f, -2.0f}, 1.0f, GREEN); + DrawSphereWires((Vector3){1.0f, 0.0f, 2.0f}, 2.0f, 16, 16, LIME); + + DrawCylinder((Vector3){4.0f, 0.0f, -2.0f}, 1.0f, 2.0f, 3.0f, 4, SKYBLUE); + DrawCylinderWires((Vector3){4.0f, 0.0f, -2.0f}, 1.0f, 2.0f, 3.0f, 4, DARKBLUE); + DrawCylinderWires((Vector3){4.5f, -1.0f, 2.0f}, 1.0f, 1.0f, 2.0f, 6, BROWN); + + DrawCylinder((Vector3){1.0f, 0.0f, -4.0f}, 0.0f, 1.5f, 3.0f, 8, GOLD); + DrawCylinderWires((Vector3){1.0f, 0.0f, -4.0f}, 0.0f, 1.5f, 3.0f, 8, PINK); + + DrawGrid(10, 1.0f); // Draw a grid + + End3dMode(); + + DrawFPS(10, 10); + + DrawText("Press Spacebar to switch camera type", 10, 40, 24, BLACK); + + if(camera.type == CAMERA_ORTHOGRAPHIC) + { + DrawText("Orthographic", 10, 65, 24, BLACK); + } + else if(camera.type == CAMERA_PERSPECTIVE) + { + DrawText("Perspective", 10, 65, 24, BLACK); + } + + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} diff --git a/examples/models/models_skybox.c b/examples/models/models_skybox.c index 46297e41..9f0d8c17 100644 --- a/examples/models/models_skybox.c +++ b/examples/models/models_skybox.c @@ -62,7 +62,7 @@ int main() Begin3dMode(camera); - DrawModel(skybox, Vector3Zero(), 1.0f, WHITE); + DrawModel(skybox, (Vector3){0, 0, 0}, 1.0f, WHITE); DrawGrid(10, 1.0f); diff --git a/examples/models/resources/shaders/pbr.vs b/examples/models/resources/shaders/pbr.vs index e852ac1a..885cb199 100644 --- a/examples/models/resources/shaders/pbr.vs +++ b/examples/models/resources/shaders/pbr.vs @@ -12,7 +12,7 @@ in vec3 vertexPosition; in vec2 vertexTexCoord; in vec3 vertexNormal; -in vec3 vertexTangent; +in vec4 vertexTangent; // Input uniform values uniform mat4 mvp; @@ -28,7 +28,7 @@ out vec3 fragBinormal; void main() { // Calculate binormal from vertex normal and tangent - vec3 vertexBinormal = cross(vertexNormal, vertexTangent); + vec3 vertexBinormal = cross(vertexNormal, vec3(vertexTangent)); // Calculate fragment normal based on normal transformations mat3 normalMatrix = transpose(inverse(mat3(mMatrix))); @@ -39,7 +39,7 @@ void main() // Send vertex attributes to fragment shader fragTexCoord = vertexTexCoord; fragNormal = normalize(normalMatrix*vertexNormal); - fragTangent = normalize(normalMatrix*vertexTangent); + fragTangent = normalize(normalMatrix*vec3(vertexTangent)); fragTangent = normalize(fragTangent - dot(fragTangent, fragNormal)*fragNormal); fragBinormal = normalize(normalMatrix*vertexBinormal); fragBinormal = cross(fragNormal, fragTangent); diff --git a/examples/physac/physics_demo.c b/examples/physac/physics_demo.c index 1b54d51b..d66d2fbe 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 $(RAYLIB_DIR)\raylib\raylib_icon -static -lraylib -lpthread * -lglfw3 -lopengl32 -lgdi32 -lopenal32 -lwinmm -std=c99 -Wl,--subsystem,windows -Wl,-allow-multiple-definition * -* Copyright (c) 2017 Victor Fisac +* Copyright (c) 2016-2018 Victor Fisac * ********************************************************************************************/ @@ -32,6 +32,7 @@ int main() // Physac logo drawing position int logoX = screenWidth - MeasureText("Physac", 30) - 10; int logoY = 15; + bool needsReset = false; // Initialize physics and default physics bodies InitPhysics(); @@ -52,10 +53,9 @@ int main() { // Update //---------------------------------------------------------------------------------- - if (IsKeyPressed('R')) // Reset physics input + // Delay initialization of variables due to physics reset async + if (needsReset) { - ResetPhysics(); - floor = CreatePhysicsBodyRectangle((Vector2){ screenWidth/2, screenHeight }, 500, 100, 10); floor->enabled = false; @@ -63,6 +63,13 @@ int main() circle->enabled = false; } + // Reset physics input + if (IsKeyPressed('R')) + { + ResetPhysics(); + needsReset = true; + } + // Physics body creation inputs if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) CreatePhysicsBodyPolygon(GetMousePosition(), GetRandomValue(20, 80), GetRandomValue(3, 8), 10); else if (IsMouseButtonPressed(MOUSE_RIGHT_BUTTON)) CreatePhysicsBodyCircle(GetMousePosition(), GetRandomValue(10, 45), 10); diff --git a/examples/physac/physics_friction.c b/examples/physac/physics_friction.c index 9472729a..4c81e8c8 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 $(RAYLIB_DIR)\raylib\raylib_icon -static -lraylib -lpthread * -lglfw3 -lopengl32 -lgdi32 -lopenal32 -lwinmm -std=c99 -Wl,--subsystem,windows -Wl,-allow-multiple-definition * -* Copyright (c) 2017 Victor Fisac +* Copyright (c) 2016-2018 Victor Fisac * ********************************************************************************************/ diff --git a/examples/physac/physics_movement.c b/examples/physac/physics_movement.c index 4b2c9ab0..f828c054 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 $(RAYLIB_DIR)\raylib\raylib_icon -static -lraylib -lpthread * -lglfw3 -lopengl32 -lgdi32 -lopenal32 -lwinmm -std=c99 -Wl,--subsystem,windows -Wl,-allow-multiple-definition * -* Copyright (c) 2017 Victor Fisac +* Copyright (c) 2016-2018 Victor Fisac * ********************************************************************************************/ diff --git a/examples/physac/physics_restitution.c b/examples/physac/physics_restitution.c index 2be8f42e..93939ebb 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 $(RAYLIB_DIR)\raylib\raylib_icon -static -lraylib -lpthread * -lglfw3 -lopengl32 -lgdi32 -lopenal32 -lwinmm -std=c99 -Wl,--subsystem,windows -Wl,-allow-multiple-definition * -* Copyright (c) 2017 Victor Fisac +* Copyright (c) 2016-2018 Victor Fisac * ********************************************************************************************/ diff --git a/examples/physac/physics_shatter.c b/examples/physac/physics_shatter.c index 07c3c4b3..8102e162 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 $(RAYLIB_DIR)\raylib\raylib_icon -static -lraylib -lpthread * -lglfw3 -lopengl32 -lgdi32 -lopenal32 -lwinmm -std=c99 -Wl,--subsystem,windows -Wl,-allow-multiple-definition * -* Copyright (c) 2017 Victor Fisac +* Copyright (c) 2016-2018 Victor Fisac * ********************************************************************************************/ @@ -32,6 +32,7 @@ int main() // Physac logo drawing position int logoX = screenWidth - MeasureText("Physac", 30) - 10; int logoY = 15; + bool needsReset = false; // Initialize physics and default physics bodies InitPhysics(); @@ -48,14 +49,19 @@ int main() { // Update //---------------------------------------------------------------------------------- - if (IsKeyPressed('R')) // Reset physics input + // Delay initialization of variables due to physics reset asynchronous + if (needsReset) { - ResetPhysics(); - // Create random polygon physics body to shatter CreatePhysicsBodyPolygon((Vector2){ screenWidth/2, screenHeight/2 }, GetRandomValue(80, 200), GetRandomValue(3, 8), 10); } + if (IsKeyPressed('R')) // Reset physics input + { + ResetPhysics(); + needsReset = true; + } + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) // Physics shatter input { // Note: some values need to be stored in variables due to asynchronous changes during main thread diff --git a/games/arkanoid.c b/games/arkanoid.c index 1da80a1e..2a4a2e53 100644 --- a/games/arkanoid.c +++ b/games/arkanoid.c @@ -18,10 +18,6 @@ #include <time.h> #include <math.h> -#if defined(PLATFORM_ANDROID) - #include "android_native_app_glue.h" -#endif - #if defined(PLATFORM_WEB) #include <emscripten/emscripten.h> #endif @@ -83,19 +79,11 @@ static void UpdateDrawFrame(void); // Update and Draw (one frame) //------------------------------------------------------------------------------------ // Program main entry point //------------------------------------------------------------------------------------ -#if defined(PLATFORM_ANDROID) -void android_main(struct android_app *app) -#else int main(void) -#endif { - // Initialization + // Initialization (Note windowTitle is unused on Android) //--------------------------------------------------------- -#if defined(PLATFORM_ANDROID) - InitWindow(screenWidth, screenHeight, app); -#else InitWindow(screenWidth, screenHeight, "sample game: arkanoid"); -#endif InitGame(); @@ -122,9 +110,8 @@ int main(void) CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- -#if !defined(PLATFORM_ANDROID) + return 0; -#endif } //------------------------------------------------------------------------------------ @@ -338,4 +325,4 @@ void UpdateDrawFrame(void) { UpdateGame(); DrawGame(); -}
\ No newline at end of file +} diff --git a/games/asteroids.c b/games/asteroids.c index dc8a9e07..80096de6 100644 --- a/games/asteroids.c +++ b/games/asteroids.c @@ -15,10 +15,6 @@ #include <math.h> -#if defined(PLATFORM_ANDROID) - #include "android_native_app_glue.h" -#endif - #if defined(PLATFORM_WEB) #include <emscripten/emscripten.h> #endif @@ -101,19 +97,11 @@ static void UpdateDrawFrame(void); // Update and Draw (one frame) //------------------------------------------------------------------------------------ // Program main entry point //------------------------------------------------------------------------------------ -#if defined(PLATFORM_ANDROID) -void android_main(struct android_app *app) -#else int main(void) -#endif { - // Initialization + // Initialization (Note windowTitle is unused on Android) //--------------------------------------------------------- -#if defined(PLATFORM_ANDROID) - InitWindow(screenWidth, screenHeight, app); -#else InitWindow(screenWidth, screenHeight, "sample game: asteroids"); -#endif InitGame(); @@ -140,9 +128,8 @@ int main(void) CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- -#if !defined(PLATFORM_ANDROID) + return 0; -#endif } //------------------------------------------------------------------------------------ @@ -578,4 +565,4 @@ void UpdateDrawFrame(void) { UpdateGame(); DrawGame(); -}
\ No newline at end of file +} diff --git a/games/asteroids_survival.c b/games/asteroids_survival.c index 12759606..8086433e 100644 --- a/games/asteroids_survival.c +++ b/games/asteroids_survival.c @@ -15,10 +15,6 @@ #include <math.h> -#if defined(PLATFORM_ANDROID) - #include "android_native_app_glue.h" -#endif - #if defined(PLATFORM_WEB) #include <emscripten/emscripten.h> #endif @@ -84,19 +80,11 @@ static void UpdateDrawFrame(void); // Update and Draw (one frame) //------------------------------------------------------------------------------------ // Program main entry point //------------------------------------------------------------------------------------ -#if defined(PLATFORM_ANDROID) -void android_main(struct android_app *app) -#else int main(void) -#endif { - // Initialization + // Initialization (Note windowTitle is unused on Android) //--------------------------------------------------------- -#if defined(PLATFORM_ANDROID) - InitWindow(screenWidth, screenHeight, app); -#else InitWindow(screenWidth, screenHeight, "sample game: asteroids survival"); -#endif InitGame(); @@ -123,9 +111,8 @@ int main(void) CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- -#if !defined(PLATFORM_ANDROID) + return 0; -#endif } //------------------------------------------------------------------------------------ @@ -388,4 +375,4 @@ void UpdateDrawFrame(void) { UpdateGame(); DrawGame(); -}
\ No newline at end of file +} diff --git a/games/floppy.c b/games/floppy.c index d7c4f129..2ca91a14 100644 --- a/games/floppy.c +++ b/games/floppy.c @@ -13,10 +13,6 @@ #include "raylib.h" -#if defined(PLATFORM_ANDROID) - #include "android_native_app_glue.h" -#endif - #if defined(PLATFORM_WEB) #include <emscripten/emscripten.h> #endif @@ -72,19 +68,11 @@ static void UpdateDrawFrame(void); // Update and Draw (one frame) //------------------------------------------------------------------------------------ // Program main entry point //------------------------------------------------------------------------------------ -#if defined(PLATFORM_ANDROID) -void android_main(struct android_app *app) -#else int main(void) -#endif { // Initialization //--------------------------------------------------------- -#if defined(PLATFORM_ANDROID) - InitWindow(screenWidth, screenHeight, app); -#else InitWindow(screenWidth, screenHeight, "sample game: floppy"); -#endif InitGame(); @@ -111,9 +99,8 @@ int main(void) CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- -#if !defined(PLATFORM_ANDROID) + return 0; -#endif } //------------------------------------------------------------------------------------ // Module Functions Definitions (local) @@ -250,4 +237,4 @@ void UpdateDrawFrame(void) { UpdateGame(); DrawGame(); -}
\ No newline at end of file +} diff --git a/games/gold_fever.c b/games/gold_fever.c index 1d8b6b7c..c5f36efa 100644 --- a/games/gold_fever.c +++ b/games/gold_fever.c @@ -13,10 +13,6 @@ #include "raylib.h" -#if defined(PLATFORM_ANDROID) - #include "android_native_app_glue.h" -#endif - #if defined(PLATFORM_WEB) #include <emscripten/emscripten.h> #endif @@ -81,19 +77,11 @@ static void UpdateDrawFrame(void); // Update and Draw (one frame) //------------------------------------------------------------------------------------ // Program main entry point //------------------------------------------------------------------------------------ -#if defined(PLATFORM_ANDROID) -void android_main(struct android_app *app) -#else int main(void) -#endif { - // Initialization + // Initialization (Note windowTitle is unused on Android) //--------------------------------------------------------- -#if defined(PLATFORM_ANDROID) - InitWindow(screenWidth, screenHeight, app); -#else InitWindow(screenWidth, screenHeight, "sample game: gold fever"); -#endif InitGame(); @@ -120,9 +108,8 @@ int main(void) CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- -#if !defined(PLATFORM_ANDROID) + return 0; -#endif } //------------------------------------------------------------------------------------ @@ -291,4 +278,4 @@ void UpdateDrawFrame(void) { UpdateGame(); DrawGame(); -}
\ No newline at end of file +} diff --git a/games/gorilas.c b/games/gorilas.c index 75decd96..9ef71b55 100644 --- a/games/gorilas.c +++ b/games/gorilas.c @@ -18,10 +18,6 @@ #include <time.h> #include <math.h> -#if defined(PLATFORM_ANDROID) - #include "android_native_app_glue.h" -#endif - #if defined(PLATFORM_WEB) #include <emscripten/emscripten.h> #endif @@ -120,19 +116,11 @@ static bool UpdateBall(int playerTurn); //------------------------------------------------------------------------------------ // Program main entry point //------------------------------------------------------------------------------------ -#if defined(PLATFORM_ANDROID) -void android_main(struct android_app *app) -#else int main(void) -#endif { - // Initialization + // Initialization (Note windowTitle is unused on Android) //--------------------------------------------------------- -#if defined(PLATFORM_ANDROID) - InitWindow(screenWidth, screenHeight, app); -#else InitWindow(screenWidth, screenHeight, "sample game: gorilas"); -#endif InitGame(); @@ -159,9 +147,8 @@ int main(void) CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- -#if !defined(PLATFORM_ANDROID) + return 0; -#endif } //------------------------------------------------------------------------------------ @@ -576,4 +563,4 @@ static bool UpdateBall(int playerTurn) } return false; -}
\ No newline at end of file +} diff --git a/games/just_do/just_do.c b/games/just_do/just_do.c index a9fef18c..c7c76af9 100644 --- a/games/just_do/just_do.c +++ b/games/just_do/just_do.c @@ -16,10 +16,6 @@ #include "raylib.h" #include "screens/screens.h" // NOTE: Defines currentScreen -#if defined(PLATFORM_ANDROID) - #include "android_native_app_glue.h" -#endif - #if defined(PLATFORM_WEB) #include <emscripten/emscripten.h> #endif @@ -53,19 +49,11 @@ void UpdateDrawFrame(void); // Update and Draw one frame //---------------------------------------------------------------------------------- // Main entry point //---------------------------------------------------------------------------------- -#if defined(PLATFORM_ANDROID) -void android_main(struct android_app *app) -#else int main(void) -#endif { - // Initialization + // Initialization (Note windowTitle is unused on Android) //--------------------------------------------------------- -#if defined(PLATFORM_ANDROID) - InitWindow(screenWidth, screenHeight, app); -#else InitWindow(screenWidth, screenHeight, "GGJ15 - JUST DO"); -#endif // Load global data here (assets that must be available in all screens, i.e. fonts) InitAudioDevice(); @@ -104,9 +92,8 @@ int main(void) CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- -#if !defined(PLATFORM_ANDROID) + return 0; -#endif } //---------------------------------------------------------------------------------- @@ -370,4 +357,4 @@ void UpdateDrawFrame(void) EndDrawing(); //---------------------------------------------------------------------------------- -}
\ No newline at end of file +} diff --git a/games/koala_seasons/koala_seasons.c b/games/koala_seasons/koala_seasons.c index 770cf3de..8657d3d5 100644 --- a/games/koala_seasons/koala_seasons.c +++ b/games/koala_seasons/koala_seasons.c @@ -15,10 +15,6 @@ #include "raylib.h" #include "screens/screens.h" // NOTE: Defines currentScreen -#if defined(PLATFORM_ANDROID) - #include "android_native_app_glue.h" -#endif - #if defined(PLATFORM_WEB) #include <emscripten/emscripten.h> #endif @@ -47,12 +43,7 @@ void UpdateDrawFrame(void); // Update and Draw one frame //---------------------------------------------------------------------------------- // Main entry point //---------------------------------------------------------------------------------- -#if defined(PLATFORM_ANDROID) -void android_main(struct android_app *app) -#else -int main(void) -#endif -{ +int main(void) { // Initialization //--------------------------------------------------------- const int screenWidth = 1280; @@ -62,11 +53,8 @@ int main(void) //ShowLogo(); //SetConfigFlags(FLAG_FULLSCREEN_MODE); -#if defined(PLATFORM_ANDROID) - InitWindow(screenWidth, screenHeight, app); -#else + // Note that windowTitle is ignored on Android InitWindow(screenWidth, screenHeight, windowTitle); -#endif // Load global data here (assets that must be available in all screens, i.e. fonts) font = LoadSpriteFont("resources/graphics/mainfont.png"); @@ -145,9 +133,8 @@ int main(void) CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- -#if !defined(PLATFORM_ANDROID) + return 0; -#endif } void TransitionToScreen(int screen) @@ -282,4 +269,4 @@ void UpdateDrawFrame(void) EndDrawing(); //---------------------------------------------------------------------------------- -}
\ No newline at end of file +} diff --git a/games/light_my_ritual/light_my_ritual.c b/games/light_my_ritual/light_my_ritual.c index bc5a4623..985baa04 100644 --- a/games/light_my_ritual/light_my_ritual.c +++ b/games/light_my_ritual/light_my_ritual.c @@ -19,10 +19,6 @@ #include <stdlib.h> -#if defined(PLATFORM_ANDROID) - #include "android_native_app_glue.h" -#endif - #if defined(PLATFORM_WEB) #include <emscripten/emscripten.h> #endif @@ -55,19 +51,11 @@ void UpdateDrawFrame(void); // Update and Draw one frame //---------------------------------------------------------------------------------- // Main entry point //---------------------------------------------------------------------------------- -#if defined(PLATFORM_ANDROID) -void android_main(struct android_app *app) -#else int main(void) -#endif { - // Initialization + // Initialization (Note windowTitle is unused on Android) //--------------------------------------------------------- -#if defined(PLATFORM_ANDROID) - InitWindow(screenWidth, screenHeight, app); -#else InitWindow(screenWidth, screenHeight, "GGJ16 - LIGHT MY RITUAL!"); -#endif // Global data loading (assets that must be available in all screens, i.e. fonts) InitAudioDevice(); @@ -129,9 +117,8 @@ int main(void) CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- -#if !defined(PLATFORM_ANDROID) + return 0; -#endif } void TransitionToScreen(int screen) diff --git a/games/missile_commander.c b/games/missile_commander.c index 245cefd1..15e06f6d 100644 --- a/games/missile_commander.c +++ b/games/missile_commander.c @@ -18,10 +18,6 @@ #include <time.h> #include <math.h> -#if defined(PLATFORM_ANDROID) - #include "android_native_app_glue.h" -#endif - #if defined(PLATFORM_WEB) #include <emscripten/emscripten.h> #endif @@ -119,19 +115,11 @@ static void UpdateIncomingFire(); //------------------------------------------------------------------------------------ // Program main entry point //------------------------------------------------------------------------------------ -#if defined(PLATFORM_ANDROID) -void android_main(struct android_app *app) -#else int main(void) -#endif { - // Initialization + // Initialization (Note windowTitle is unused on Android) //--------------------------------------------------------- -#if defined(PLATFORM_ANDROID) - InitWindow(screenWidth, screenHeight, app); -#else InitWindow(screenWidth, screenHeight, "sample game: missile commander"); -#endif InitGame(); @@ -158,9 +146,8 @@ int main(void) CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- -#if !defined(PLATFORM_ANDROID) + return 0; -#endif } //-------------------------------------------------------------------------------------- @@ -544,4 +531,4 @@ static void UpdateIncomingFire() missileIndex++; if (missileIndex == MAX_MISSILES) missileIndex = 0; } -}
\ No newline at end of file +} diff --git a/games/pang.c b/games/pang.c index 731234ae..a81f32f0 100644 --- a/games/pang.c +++ b/games/pang.c @@ -15,10 +15,6 @@ #include <math.h> -#if defined(PLATFORM_ANDROID) - #include "android_native_app_glue.h" -#endif - #if defined(PLATFORM_WEB) #include <emscripten/emscripten.h> #endif @@ -110,19 +106,11 @@ static void UpdateDrawFrame(void); // Update and Draw (one frame) //------------------------------------------------------------------------------------ // Program main entry point //------------------------------------------------------------------------------------ -#if defined(PLATFORM_ANDROID) -void android_main(struct android_app *app) -#else int main(void) -#endif { - // Initialization + // Initialization (Note windowTitle is unused on Android) //--------------------------------------------------------- -#if defined(PLATFORM_ANDROID) - InitWindow(screenWidth, screenHeight, app); -#else InitWindow(screenWidth, screenHeight, "sample game: pang"); -#endif InitGame(); @@ -149,9 +137,8 @@ int main(void) CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- -#if !defined(PLATFORM_ANDROID) + return 0; -#endif } //------------------------------------------------------------------------------------ @@ -637,4 +624,4 @@ void UpdateDrawFrame(void) { UpdateGame(); DrawGame(); -}
\ No newline at end of file +} diff --git a/games/skully_escape/skully_escape.c b/games/skully_escape/skully_escape.c index 3a0e4cb0..dc545117 100644 --- a/games/skully_escape/skully_escape.c +++ b/games/skully_escape/skully_escape.c @@ -14,10 +14,6 @@ #include "player.h" -#if defined(PLATFORM_ANDROID) - #include "android_native_app_glue.h" -#endif - #if defined(PLATFORM_WEB) #include <emscripten/emscripten.h> #endif @@ -52,19 +48,11 @@ void UpdateDrawFrame(void); // Update and Draw one frame //---------------------------------------------------------------------------------- // Main entry point //---------------------------------------------------------------------------------- -#if defined(PLATFORM_ANDROID) -void android_main(struct android_app *app) -#else int main(void) -#endif { - // Initialization + // Initialization (Note windowTitle is unused on Android) //--------------------------------------------------------- -#if defined(PLATFORM_ANDROID) - InitWindow(screenWidth, screenHeight, app); -#else InitWindow(screenWidth, screenHeight, "SKULLY ESCAPE [KING GAMEJAM]"); -#endif // Global data loading (assets that must be available in all screens, i.e. fonts) InitAudioDevice(); @@ -112,9 +100,8 @@ int main(void) CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- -#if !defined(PLATFORM_ANDROID) + return 0; -#endif } void TransitionToScreen(int screen) diff --git a/games/snake.c b/games/snake.c index c971ce15..40d66da8 100644 --- a/games/snake.c +++ b/games/snake.c @@ -13,10 +13,6 @@ #include "raylib.h" -#if defined(PLATFORM_ANDROID) - #include "android_native_app_glue.h" -#endif - #if defined(PLATFORM_WEB) #include <emscripten/emscripten.h> #endif @@ -73,19 +69,11 @@ static void UpdateDrawFrame(void); // Update and Draw (one frame) //------------------------------------------------------------------------------------ // Program main entry point //------------------------------------------------------------------------------------ -#if defined(PLATFORM_ANDROID) -void android_main(struct android_app *app) -#else int main(void) -#endif { - // Initialization + // Initialization (Note windowTitle is unused on Android) //--------------------------------------------------------- -#if defined(PLATFORM_ANDROID) - InitWindow(screenWidth, screenHeight, app); -#else InitWindow(screenWidth, screenHeight, "sample game: snake"); -#endif InitGame(); @@ -112,9 +100,8 @@ int main(void) CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- -#if !defined(PLATFORM_ANDROID) + return 0; -#endif } //------------------------------------------------------------------------------------ @@ -298,4 +285,4 @@ void UpdateDrawFrame(void) { UpdateGame(); DrawGame(); -}
\ No newline at end of file +} diff --git a/games/space_invaders.c b/games/space_invaders.c index b80de050..97f14547 100644 --- a/games/space_invaders.c +++ b/games/space_invaders.c @@ -13,10 +13,6 @@ #include "raylib.h" -#if defined(PLATFORM_ANDROID) - #include "android_native_app_glue.h" -#endif - #if defined(PLATFORM_WEB) #include <emscripten/emscripten.h> #endif @@ -90,19 +86,11 @@ static void UpdateDrawFrame(void); // Update and Draw (one frame) //------------------------------------------------------------------------------------ // Program main entry point //------------------------------------------------------------------------------------ -#if defined(PLATFORM_ANDROID) -void android_main(struct android_app *app) -#else int main(void) -#endif { - // Initialization + // Initialization (Note windowTitle is unused on Android) //--------------------------------------------------------- -#if defined(PLATFORM_ANDROID) - InitWindow(screenWidth, screenHeight, app); -#else InitWindow(screenWidth, screenHeight, "sample game: space invaders"); -#endif InitGame(); @@ -129,9 +117,8 @@ int main(void) CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- -#if !defined(PLATFORM_ANDROID) + return 0; -#endif } //------------------------------------------------------------------------------------ @@ -410,4 +397,4 @@ void UpdateDrawFrame(void) { UpdateGame(); DrawGame(); -}
\ No newline at end of file +} diff --git a/games/tetris.c b/games/tetris.c index e02d7f18..3c9d5c5c 100644 --- a/games/tetris.c +++ b/games/tetris.c @@ -18,10 +18,6 @@ #include <time.h> #include <math.h> -#if defined(PLATFORM_ANDROID) - #include "android_native_app_glue.h" -#endif - #if defined(PLATFORM_WEB) #include <emscripten/emscripten.h> #endif @@ -109,19 +105,11 @@ static void DeleteCompleteLines(); //------------------------------------------------------------------------------------ // Program main entry point //------------------------------------------------------------------------------------ -#if defined(PLATFORM_ANDROID) -void android_main(struct android_app *app) -#else int main(void) -#endif { - // Initialization + // Initialization (Note windowTitle is unused on Android) //--------------------------------------------------------- -#if defined(PLATFORM_ANDROID) - InitWindow(screenWidth, screenHeight, app); -#else InitWindow(screenWidth, screenHeight, "sample game: tetris"); -#endif InitGame(); @@ -148,9 +136,8 @@ int main(void) CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- -#if !defined(PLATFORM_ANDROID) + return 0; -#endif } //-------------------------------------------------------------------------------------- @@ -841,4 +828,4 @@ static void DeleteCompleteLines() } } } -}
\ No newline at end of file +} diff --git a/games/transmission/transmission.c b/games/transmission/transmission.c index a508b5d2..37824a7b 100644 --- a/games/transmission/transmission.c +++ b/games/transmission/transmission.c @@ -17,10 +17,6 @@ #include <stdlib.h> #include <stdio.h> -#if defined(PLATFORM_ANDROID) - #include "android_native_app_glue.h" -#endif - #if defined(PLATFORM_WEB) #include <emscripten/emscripten.h> #endif @@ -55,20 +51,15 @@ static void UpdateDrawFrame(void); // Update and Draw one frame //---------------------------------------------------------------------------------- // Main entry point //---------------------------------------------------------------------------------- -#if defined(PLATFORM_ANDROID) -void android_main(struct android_app *app) -#else int main(void) -#endif { // Initialization //--------------------------------------------------------- -#if defined(PLATFORM_ANDROID) - InitWindow(screenWidth, screenHeight, app); -#else +#ifndef PLATFORM_ANDROID SetConfigFlags(FLAG_SHOW_LOGO); // | FLAG_FULLSCREEN_MODE); - InitWindow(screenWidth, screenHeight, "raylib game - transmission mission"); #endif + // Note windowTitle is unused on Android + InitWindow(screenWidth, screenHeight, "raylib game - transmission mission"); // Global data loading (assets that must be available in all screens, i.e. fonts) InitAudioDevice(); @@ -138,9 +129,8 @@ int main(void) CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- -#if !defined(PLATFORM_ANDROID) + return 0; -#endif } //---------------------------------------------------------------------------------- @@ -462,4 +452,4 @@ void DrawButton(const char *text) Vector2 measure = MeasureTextEx(fontMission, text, fontSizeButton, 0); Vector2 textPos = {textPositionButton.x - measure.x/2 + 10, textPositionButton.y - measure.y/2 - 10}; DrawTextEx(fontMission, text, textPos , fontSizeButton, 0, textColorButton); -}
\ No newline at end of file +} diff --git a/games/wave_collector/wave_collector.c b/games/wave_collector/wave_collector.c index e28c0b84..2099b74c 100644 --- a/games/wave_collector/wave_collector.c +++ b/games/wave_collector/wave_collector.c @@ -22,10 +22,6 @@ #include <stdio.h> // Required for: printf() #include <string.h> // Required for: strcpy() -#if defined(PLATFORM_ANDROID) - #include "android_native_app_glue.h" -#endif - #if defined(PLATFORM_WEB) #include <emscripten/emscripten.h> #endif @@ -60,11 +56,7 @@ static void UpdateDrawFrame(void); // Update and Draw one frame //---------------------------------------------------------------------------------- // Main entry point //---------------------------------------------------------------------------------- -#if defined(PLATFORM_ANDROID) -void android_main(struct android_app *app) -#else int main(int argc, char *argv[]) -#endif { // Initialization //--------------------------------------------------------- @@ -89,12 +81,11 @@ int main(int argc, char *argv[]) } #endif -#if defined(PLATFORM_ANDROID) - InitWindow(screenWidth, screenHeight, app); -#else +#ifndef PLATFORM_ANDROID SetConfigFlags(FLAG_MSAA_4X_HINT); - InitWindow(screenWidth, screenHeight, "GGJ17 - WAVE COLLECTOR"); #endif + // Note windowTitle is unused on Android + InitWindow(screenWidth, screenHeight, "GGJ17 - WAVE COLLECTOR"); // Global data loading (assets that must be available in all screens, i.e. fonts) InitAudioDevice(); @@ -143,9 +134,8 @@ int main(int argc, char *argv[]) CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- -#if !defined(PLATFORM_ANDROID) + return 0; -#endif } //---------------------------------------------------------------------------------- diff --git a/project/vs2015.UWP/raylib.App.UWP/App.cpp b/project/vs2015.UWP/raylib.App.UWP/App.cpp index 375b668c..6ce6915c 100644 --- a/project/vs2015.UWP/raylib.App.UWP/App.cpp +++ b/project/vs2015.UWP/raylib.App.UWP/App.cpp @@ -18,16 +18,21 @@ using namespace Platform; using namespace raylibUWP; /* -To-do list +TODO list: - Cache reference to our CoreWindow? - - Implement gestures + - Implement gestures support */ +// Declare uwpWindow as exter to be used by raylib internals +// NOTE: It should be properly assigned before calling InitWindow() +extern "C" { EGLNativeWindowType uwpWindow; }; + /* INPUT CODE */ // Stand-ins for "core.c" variables #define MAX_GAMEPADS 4 // Max number of gamepads supported #define MAX_GAMEPAD_BUTTONS 32 // Max bumber of buttons supported (per gamepad) #define MAX_GAMEPAD_AXIS 8 // Max number of axis supported (per gamepad) + static bool gamepadReady[MAX_GAMEPADS] = { false }; // Flag to know if gamepad is ready static float gamepadAxisState[MAX_GAMEPADS][MAX_GAMEPAD_AXIS]; // Gamepad axis state static char previousGamepadState[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Previous gamepad buttons state @@ -36,7 +41,6 @@ static char currentGamepadState[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Curre static char previousKeyState[512] = { 0 }; // Contains previous frame keyboard state static char currentKeyState[512] = { 0 }; // Contains current frame keyboard state -//... static char previousMouseState[3] = { 0 }; // Registers previous mouse button state static char currentMouseState[3] = { 0 }; // Registers current mouse button state static int previousMouseWheelY = 0; // Registers previous mouse wheel variation @@ -46,7 +50,7 @@ static bool cursorOnScreen = false; // Tracks if cursor is inside client static bool cursorHidden = false; // Track if cursor is hidden static Vector2 mousePosition; -static Vector2 mouseDelta; // NOTE: Added to keep track of mouse movement while the cursor is locked - no equivalent in "core.c" +static Vector2 mouseDelta; // NOTE: Added to keep track of mouse movement while the cursor is locked - no equivalent in "core.c" static bool toggleCursorLock; CoreCursor ^regularCursor = ref new CoreCursor(CoreCursorType::Arrow, 0); // The "visible arrow" cursor type @@ -122,7 +126,7 @@ void ProcessKeyEvent(Windows::System::VirtualKey key, int action) } } -/* CALLBACKS */ +// Callbacks void App::PointerPressed(CoreWindow^ window, PointerEventArgs^ args) { if (args->CurrentPoint->Properties->IsLeftButtonPressed) @@ -206,6 +210,7 @@ void UWPSetMousePosition(Vector2 position) window->PointerPosition = mousePosScreen; mousePosition = position; } + // Enables cursor (unlock cursor) void UWPEnableCursor() { @@ -321,8 +326,7 @@ bool UWPIsKeyPressed(int key) { bool pressed = false; - if ((currentKeyState[key] != previousKeyState[key]) && (currentKeyState[key] == 1)) - pressed = true; + if ((currentKeyState[key] != previousKeyState[key]) && (currentKeyState[key] == 1)) pressed = true; else pressed = false; return pressed; @@ -422,7 +426,10 @@ void App::SetWindow(CoreWindow^ window) currentDisplayInformation->OrientationChanged += ref new TypedEventHandler<DisplayInformation^, Object^>(this, &App::OnOrientationChanged); // The CoreWindow has been created, so EGL can be initialized. - InitWindow(800, 450, (EGLNativeWindowType)window); + + uwpWindow = (EGLNativeWindowType)window; + + InitWindow(800, 450, NULL); } // Initializes scene resources @@ -446,7 +453,6 @@ void App::Run() ClearBackground(RAYWHITE); - posX += gamepadAxisState[GAMEPAD_PLAYER1][GAMEPAD_XBOX_AXIS_LEFT_X] * 5; posY += gamepadAxisState[GAMEPAD_PLAYER1][GAMEPAD_XBOX_AXIS_LEFT_Y] * -5; DrawRectangle(posX, posY, 400, 100, RED); @@ -455,38 +461,32 @@ void App::Run() DrawCircle(mousePosition.x, mousePosition.y, 40, BLUE); - if(UWPIsKeyDown(KEY_S)) - { - DrawCircle(100, 100, 100, BLUE); - } + if (UWPIsKeyDown(KEY_S)) DrawCircle(100, 100, 100, BLUE); - if(UWPIsKeyPressed(KEY_A)) + if (UWPIsKeyPressed(KEY_A)) { posX -= 50; UWPEnableCursor(); } + if (UWPIsKeyPressed(KEY_D)) { posX += 50; - UWPDisableCursor(); } - if(currentKeyState[KEY_LEFT_ALT]) - DrawRectangle(250, 250, 20, 20, BLACK); - if (currentKeyState[KEY_BACKSPACE]) - DrawRectangle(280, 250, 20, 20, BLACK); - - if (currentMouseState[MOUSE_LEFT_BUTTON]) - DrawRectangle(280, 250, 20, 20, BLACK); + if (currentKeyState[KEY_LEFT_ALT]) DrawRectangle(250, 250, 20, 20, BLACK); + if (currentKeyState[KEY_BACKSPACE]) DrawRectangle(280, 250, 20, 20, BLACK); + if (currentMouseState[MOUSE_LEFT_BUTTON]) DrawRectangle(280, 250, 20, 20, BLACK); static int pos = 0; pos -= currentMouseWheelY; - DrawRectangle(280, pos + 50, 20, 20, BLACK); + DrawRectangle(280, pos + 50, 20, 20, BLACK); DrawRectangle(250, 280 + (time++ % 60), 10, 10, PURPLE); EndDrawing(); + UWP_PollInput(); CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); diff --git a/project/vs2015.UWP/raylib.App.UWP/Package.appxmanifest b/project/vs2015.UWP/raylib.App.UWP/Package.appxmanifest index f0f56862..56020a50 100644 --- a/project/vs2015.UWP/raylib.App.UWP/Package.appxmanifest +++ b/project/vs2015.UWP/raylib.App.UWP/Package.appxmanifest @@ -4,7 +4,7 @@ <mp:PhoneIdentity PhoneProductId="56d2ca94-c361-4e9f-9a33-bacd751552fa" PhonePublisherId="00000000-0000-0000-0000-000000000000" /> <Properties> <DisplayName>raylibUWP</DisplayName> - <PublisherDisplayName>Alumno</PublisherDisplayName> + <PublisherDisplayName>raysan5</PublisherDisplayName> <Logo>Assets\StoreLogo.png</Logo> </Properties> <Dependencies> diff --git a/project/vs2015.UWP/raylib.App.UWP/raylib.App.UWP.vcxproj b/project/vs2015.UWP/raylib.App.UWP/raylib.App.UWP.vcxproj index bc7f27d2..6af9db60 100644 --- a/project/vs2015.UWP/raylib.App.UWP/raylib.App.UWP.vcxproj +++ b/project/vs2015.UWP/raylib.App.UWP/raylib.App.UWP.vcxproj @@ -34,7 +34,7 @@ <AppContainerApplication>true</AppContainerApplication> <ApplicationType>Windows Store</ApplicationType> <WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion> - <WindowsTargetPlatformMinVersion>10.0.10586.0</WindowsTargetPlatformMinVersion> + <WindowsTargetPlatformMinVersion>10.0.14393.0</WindowsTargetPlatformMinVersion> <ApplicationTypeRevision>10.0</ApplicationTypeRevision> <ProjectName>raylib.App.UWP</ProjectName> </PropertyGroup> diff --git a/project/vs2015.UWP/raylib/raylib.vcxproj b/project/vs2015.UWP/raylib/raylib.vcxproj index 32e59759..c1fbca50 100644 --- a/project/vs2015.UWP/raylib/raylib.vcxproj +++ b/project/vs2015.UWP/raylib/raylib.vcxproj @@ -28,7 +28,7 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <ConfigurationType>StaticLibrary</ConfigurationType> <UseDebugLibraries>true</UseDebugLibraries> - <PlatformToolset>v141</PlatformToolset> + <PlatformToolset>v140</PlatformToolset> <CharacterSet>Unicode</CharacterSet> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> diff --git a/release/include/raylib.h b/release/include/raylib.h index dc02370d..acca46bd 100644 --- a/release/include/raylib.h +++ b/release/include/raylib.h @@ -1,6 +1,6 @@ /********************************************************************************************** * -* raylib v1.9-dev +* raylib v1.9.6-dev * * A simple and easy-to-use library to learn videogames programming (www.raylib.com) * @@ -103,11 +103,23 @@ #define KEY_SPACE 32 #define KEY_ESCAPE 256 #define KEY_ENTER 257 +#define KEY_TAB 258 #define KEY_BACKSPACE 259 +#define KEY_INSERT 260 +#define KEY_DELETE 261 #define KEY_RIGHT 262 #define KEY_LEFT 263 #define KEY_DOWN 264 #define KEY_UP 265 +#define KEY_PAGE_UP 266 +#define KEY_PAGE_DOWN 267 +#define KEY_HOME 268 +#define KEY_END 269 +#define KEY_CAPS_LOCK 280 +#define KEY_SCROLL_LOCK 281 +#define KEY_NUM_LOCK 282 +#define KEY_PRINT_SCREEN 283 +#define KEY_PAUSE 284 #define KEY_F1 290 #define KEY_F2 291 #define KEY_F3 292 @@ -310,6 +322,14 @@ typedef struct Vector3 { float z; } Vector3; +// Vector4 type +typedef struct Vector4 { + float x; + float y; + float z; + float w; +} Vector4; + // Matrix type (OpenGL style 4x4 - right handed, column major) typedef struct Matrix { float m0, m4, m8, m12; @@ -378,12 +398,19 @@ typedef struct SpriteFont { CharInfo *chars; // Characters info data } SpriteFont; +// Camera projection modes +typedef enum { + CAMERA_PERSPECTIVE = 0, + CAMERA_ORTHOGRAPHIC +} CameraType; + // Camera type, defines a camera position/orientation in 3d space typedef struct Camera { Vector3 position; // Camera position Vector3 target; // Camera target it looks-at Vector3 up; // Camera up vector (rotation over its axis) - float fovy; // Camera field-of-view apperture in Y (degrees) + float fovy; // Camera field-of-view apperture in Y (degrees) in perspective, used as near plane width in orthographic + CameraType type; // Camera type, controlling projection type, either CAMERA_PERSPECTIVE or CAMERA_ORTHOGRAPHIC. } Camera; // Camera2D type, defines a 2d camera @@ -410,7 +437,7 @@ typedef struct Mesh { float *texcoords; // Vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1) float *texcoords2; // Vertex second texture coordinates (useful for lightmaps) (shader-location = 5) float *normals; // Vertex normals (XYZ - 3 components per vertex) (shader-location = 2) - float *tangents; // Vertex tangents (XYZ - 3 components per vertex) (shader-location = 4) + float *tangents; // Vertex tangents (XYZW - 4 components per vertex) (shader-location = 4) unsigned char *colors; // Vertex colors (RGBA - 4 components per vertex) (shader-location = 3) unsigned short *indices;// Vertex indices (in case vertex data comes indexed) @@ -541,7 +568,7 @@ typedef enum { LOC_MAP_METALNESS, // LOC_MAP_SPECULAR LOC_MAP_NORMAL, LOC_MAP_ROUGHNESS, - LOC_MAP_OCCUSION, + LOC_MAP_OCCLUSION, LOC_MAP_EMISSION, LOC_MAP_HEIGHT, LOC_MAP_CUBEMAP, @@ -672,8 +699,9 @@ extern "C" { // Prevents name mangling of functions //------------------------------------------------------------------------------------ // Window-related functions -RLAPI void InitWindow(int width, int height, void *data); // Initialize window and OpenGL context +RLAPI void InitWindow(int width, int height, const char *title); // Initialize window and OpenGL context RLAPI void CloseWindow(void); // Close window and unload OpenGL context +RLAPI bool IsWindowReady(void); // Check if window has been initialized successfully RLAPI bool WindowShouldClose(void); // Check if KEY_ESCAPE pressed or Close icon pressed RLAPI bool IsWindowMinimized(void); // Check if window has been minimized (or lost focus) RLAPI void ToggleFullscreen(void); // Toggle fullscreen mode (only PLATFORM_DESKTOP) @@ -682,6 +710,7 @@ RLAPI void SetWindowTitle(const char *title); // Set title f RLAPI void SetWindowPosition(int x, int y); // Set window position on screen (only PLATFORM_DESKTOP) RLAPI void SetWindowMonitor(int monitor); // Set monitor for the current window (fullscreen mode) RLAPI void SetWindowMinSize(int width, int height); // Set window minimum dimensions (for FLAG_WINDOW_RESIZABLE) +RLAPI void SetWindowSize(int width, int height); // Set window dimensions RLAPI int GetScreenWidth(void); // Get current screen width RLAPI int GetScreenHeight(void); // Get current screen height @@ -704,7 +733,7 @@ RLAPI void BeginTextureMode(RenderTexture2D target); // Initializes RLAPI void EndTextureMode(void); // Ends drawing to render texture // Screen-space-related functions -RLAPI Ray GetMouseRay(Vector2 mousePosition, Camera camera); // Returns a ray trace from mouse position +RLAPI Ray GetMouseRay(Vector2 mousePosition, Camera camera); // Returns a ray trace from mouse position RLAPI Vector2 GetWorldToScreen(Vector3 position, Camera camera); // Returns the screen space position for a 3d world space position RLAPI Matrix GetCameraMatrix(Camera camera); // Returns camera transform matrix (view matrix) @@ -715,17 +744,11 @@ RLAPI float GetFrameTime(void); // Returns tim RLAPI double GetTime(void); // Returns elapsed time in seconds since InitWindow() // Color-related functions -RLAPI int GetHexValue(Color color); // Returns hexadecimal value for a Color +RLAPI float *ColorToFloat(Color color); // Returns normalized float array for a Color +RLAPI int ColorToInt(Color color); // Returns hexadecimal value for a Color +RLAPI Vector3 ColorToHSV(Color color); // Returns HSV values for a Color RLAPI Color GetColor(int hexValue); // Returns a Color struct from hexadecimal value RLAPI Color Fade(Color color, float alpha); // Color fade-in or fade-out, alpha goes from 0.0f to 1.0f -RLAPI float *ColorToFloat(Color color); // Converts Color to float array and normalizes - -// Math useful functions (available from raymath.h) -RLAPI float *Vector3ToFloat(Vector3 vec); // Returns Vector3 as float array -RLAPI float *MatrixToFloat(Matrix mat); // Returns Matrix as float array -RLAPI Vector3 Vector3Zero(void); // Vector with components value 0.0f -RLAPI Vector3 Vector3One(void); // Vector with components value 1.0f -RLAPI Matrix MatrixIdentity(void); // Returns identity matrix // Misc. functions RLAPI void ShowLogo(void); // Activate raylib logo at startup (can be done with flags) @@ -783,6 +806,7 @@ RLAPI int GetMouseX(void); // Returns mouse p RLAPI int GetMouseY(void); // Returns mouse position Y RLAPI Vector2 GetMousePosition(void); // Returns mouse position XY RLAPI void SetMousePosition(Vector2 position); // Set mouse position XY +RLAPI void SetMouseScale(float scale); // Set mouse scaling RLAPI int GetMouseWheelMove(void); // Returns mouse wheel movement Y // Input-related functions: touch @@ -839,6 +863,7 @@ RLAPI void DrawRectangleGradientV(int posX, int posY, int width, int height, Col RLAPI void DrawRectangleGradientH(int posX, int posY, int width, int height, Color color1, Color color2);// Draw a horizontal-gradient-filled rectangle RLAPI void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4); // Draw a gradient-filled rectangle with custom vertex colors RLAPI void DrawRectangleLines(int posX, int posY, int width, int height, Color color); // Draw rectangle outline +RLAPI void DrawRectangleLinesEx(Rectangle rec, int lineThick, Color color); // Draw rectangle outline with extended parameters RLAPI void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw a color-filled triangle RLAPI void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline RLAPI void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a regular polygon (Vector version) @@ -886,6 +911,7 @@ RLAPI void ImageAlphaPremultiply(Image *image); RLAPI void ImageCrop(Image *image, Rectangle crop); // Crop an image to a defined rectangle RLAPI void ImageResize(Image *image, int newWidth, int newHeight); // Resize and image (bilinear filtering) RLAPI void ImageResizeNN(Image *image,int newWidth,int newHeight); // Resize and image (Nearest-Neighbor scaling algorithm) +RLAPI void ImageMipmaps(Image *image); // Generate all mipmap levels for a provided image RLAPI void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp); // Dither image data to 16bpp or lower (Floyd-Steinberg dithering) RLAPI Image ImageText(const char *text, int fontSize, Color color); // Create an image from text (default font) RLAPI Image ImageTextEx(SpriteFont font, const char *text, float fontSize, int spacing, Color tint); // Create an image from text (custom sprite font) @@ -908,7 +934,7 @@ RLAPI Image GenImageGradientH(int width, int height, Color left, Color right); RLAPI Image GenImageGradientRadial(int width, int height, float density, Color inner, Color outer); // Generate image: radial gradient RLAPI Image GenImageChecked(int width, int height, int checksX, int checksY, Color col1, Color col2); // Generate image: checked RLAPI Image GenImageWhiteNoise(int width, int height, float factor); // Generate image: white noise -RLAPI Image GenImagePerlinNoise(int width, int height, float scale); // Generate image: perlin noise +RLAPI Image GenImagePerlinNoise(int width, int height, int offsetX, int offsetY, float scale); // Generate image: perlin noise RLAPI Image GenImageCellular(int width, int height, int tileSize); // Generate image: cellular algorithm. Bigger tileSize means bigger cells // Texture2D configuration functions @@ -932,19 +958,20 @@ RLAPI void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle dest RLAPI SpriteFont GetDefaultFont(void); // Get the default SpriteFont RLAPI SpriteFont LoadSpriteFont(const char *fileName); // Load SpriteFont from file into GPU memory (VRAM) RLAPI SpriteFont LoadSpriteFontEx(const char *fileName, int fontSize, int charsCount, int *fontChars); // Load SpriteFont from file with extended parameters -RLAPI void UnloadSpriteFont(SpriteFont spriteFont); // Unload SpriteFont from GPU memory (VRAM) +RLAPI void UnloadSpriteFont(SpriteFont font); // Unload SpriteFont from GPU memory (VRAM) // Text drawing functions RLAPI void DrawFPS(int posX, int posY); // Shows current FPS RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font) -RLAPI void DrawTextEx(SpriteFont spriteFont, const char* text, Vector2 position, // Draw text using SpriteFont and additional parameters +RLAPI void DrawTextEx(SpriteFont font, const char* text, Vector2 position, // Draw text using SpriteFont and additional parameters float fontSize, int spacing, Color tint); // Text misc. functions RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font -RLAPI Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, float fontSize, int spacing); // Measure string size for SpriteFont +RLAPI Vector2 MeasureTextEx(SpriteFont font, const char *text, float fontSize, int spacing); // Measure string size for SpriteFont RLAPI const char *FormatText(const char *text, ...); // Formatting of text with variables to 'embed' RLAPI const char *SubText(const char *text, int position, int length); // Get a piece of a text string +RLAPI int GetGlyphIndex(SpriteFont font, int character); // Returns index position for a unicode character on sprite font //------------------------------------------------------------------------------------ // Basic 3d Shapes Drawing Functions (Module: models) @@ -981,6 +1008,11 @@ RLAPI void UnloadModel(Model model); RLAPI Mesh LoadMesh(const char *fileName); // Load mesh from file RLAPI void UnloadMesh(Mesh *mesh); // Unload mesh from memory (RAM and/or VRAM) +// Mesh manipulation functions +RLAPI BoundingBox MeshBoundingBox(Mesh mesh); // Compute mesh bounding box limits +RLAPI void MeshTangents(Mesh *mesh); // Compute mesh tangents +RLAPI void MeshBinormals(Mesh *mesh); // Compute mesh binormals + // Mesh generation functions RLAPI Mesh GenMeshPlane(float width, float length, int resX, int resZ); // Generate plane mesh (with subdivisions) RLAPI Mesh GenMeshCube(float width, float height, float length); // Generate cuboid mesh @@ -1010,7 +1042,6 @@ RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRe Vector3 center, float size, Color tint); // Draw a billboard texture defined by sourceRec // Collision detection functions -RLAPI BoundingBox CalculateBoundingBox(Mesh mesh); // Calculate mesh bounding box limits RLAPI bool CheckCollisionSpheres(Vector3 centerA, float radiusA, Vector3 centerB, float radiusB); // Detect collision between two spheres RLAPI bool CheckCollisionBoxes(BoundingBox box1, BoundingBox box2); // Detect collision between two bounding boxes RLAPI bool CheckCollisionBoxSphere(BoundingBox box, Vector3 centerSphere, float radiusSphere); // Detect collision between box and sphere @@ -1029,7 +1060,8 @@ RLAPI RayHitInfo GetCollisionRayGround(Ray ray, float groundHeight); // Shader loading/unloading functions RLAPI char *LoadText(const char *fileName); // Load chars array from text file -RLAPI Shader LoadShader(char *vsFileName, char *fsFileName); // Load shader from files and bind default locations +RLAPI Shader LoadShader(const char *vsFileName, const char *fsFileName); // Load shader from files and bind default locations +RLAPI Shader LoadShaderCode(char *vsCode, char *fsCode); // Load shader from code strings and bind default locations RLAPI void UnloadShader(Shader shader); // Unload shader from GPU memory (VRAM) RLAPI Shader GetShaderDefault(void); // Get default shader diff --git a/release/libs/android/armeabi-v7a/libraylib.a b/release/libs/android/armeabi-v7a/libraylib.a Binary files differindex b10e6b68..1e6a0088 100644 --- a/release/libs/android/armeabi-v7a/libraylib.a +++ b/release/libs/android/armeabi-v7a/libraylib.a diff --git a/release/libs/win32/mingw32/libraylib.a b/release/libs/win32/mingw32/libraylib.a Binary files differindex 7653d1d0..361aa73c 100644 --- a/release/libs/win32/mingw32/libraylib.a +++ b/release/libs/win32/mingw32/libraylib.a diff --git a/release/libs/win32/mingw32/libraylibdll.a b/release/libs/win32/mingw32/libraylibdll.a Binary files differindex 7d910eeb..b4f1cb6b 100644 --- a/release/libs/win32/mingw32/libraylibdll.a +++ b/release/libs/win32/mingw32/libraylibdll.a diff --git a/release/libs/win32/mingw32/raylib.dll b/release/libs/win32/mingw32/raylib.dll Binary files differindex c5387654..54d086ac 100644 --- a/release/libs/win32/mingw32/raylib.dll +++ b/release/libs/win32/mingw32/raylib.dll diff --git a/release/libs/win32/msvc/raylib.lib b/release/libs/win32/msvc/raylib.lib Binary files differindex 6983d9a8..45172565 100644 --- a/release/libs/win32/msvc/raylib.lib +++ b/release/libs/win32/msvc/raylib.lib diff --git a/src/Makefile b/src/Makefile index 7837b614..e6c3b7d8 100644 --- a/src/Makefile +++ b/src/Makefile @@ -450,8 +450,8 @@ else @echo "raylib dynamic library (raylib.dll) and import library (libraylibdll.a) generated!" endif ifeq ($(PLATFORM_OS),LINUX) - # Compile raylib shared library version $(RAYLIB_VERSION). - # WARNING: you should type "make clean" before doing this target + # Compile raylib shared library version $(RAYLIB_VERSION). + # WARNING: you should type "make clean" before doing this target $(CC) -shared -o $(RAYLIB_RELEASE_PATH)/libraylib.so.$(RAYLIB_VERSION) $(OBJS) -shared -Wl,-soname,libraylib.so.$(RAYLIB_API_VERSION) -lGL -lc -lm -lpthread -ldl -lrt @echo "raylib shared library generated (libraylib.so.$(RAYLIB_VERSION)) in $(RAYLIB_RELEASE_PATH)!" cd $(RAYLIB_RELEASE_PATH) && ln -fsv libraylib.so.$(RAYLIB_VERSION) libraylib.so.$(RAYLIB_API_VERSION) @@ -465,7 +465,7 @@ else cd $(RAYLIB_RELEASE_PATH) && ln -fs libraylib.$(RAYLIB_VERSION).dylib libraylib.dylib endif ifeq ($(PLATFORM_OS),FREEBSD) - # WARNING: you should type "gmake clean" before doing this target + # WARNING: you should type "gmake clean" before doing this target $(CC) -shared -o $(RAYLIB_RELEASE_PATH)/libraylib.$(RAYLIB_VERSION).so $(OBJS) -Wl,-soname,libraylib.$(RAYLIB_API_VERSION).so -lGL -lpthread @echo "raylib shared library generated (libraylib.$(RAYLIB_VERSION).so)!" cd $(RAYLIB_RELEASE_PATH) && ln -fs libraylib.$(RAYLIB_VERSION).so libraylib.$(RAYLIB_API_VERSION).so @@ -478,8 +478,8 @@ else cd $(RAYLIB_RELEASE_PATH) && ln -fs libraylib.$(RAYLIB_VERSION).so libraylib.so endif else - # Compile raylib static library version $(RAYLIB_VERSION) - # WARNING: You should type "make clean" before doing this target. + # Compile raylib static library version $(RAYLIB_VERSION) + # WARNING: You should type "make clean" before doing this target. $(AR) rcs $(RAYLIB_RELEASE_PATH)/libraylib.a $(OBJS) @echo "raylib static library generated (libraylib.a) in $(RAYLIB_RELEASE_PATH)!" endif @@ -552,24 +552,24 @@ RAYLIB_H_INSTALL_PATH ?= $(DESTDIR)/include install : ifeq ($(ROOT),root) ifeq ($(PLATFORM_OS),LINUX) - # Attention! You are root, writing files to $(RAYLIB_INSTALL_PATH) - # and $(RAYLIB_H_INSTALL_PATH). Consult this Makefile for more information. - # Prepare the environment as needed. + # Attention! You are root, writing files to $(RAYLIB_INSTALL_PATH) + # and $(RAYLIB_H_INSTALL_PATH). Consult this Makefile for more information. + # Prepare the environment as needed. mkdir --parents --verbose $(RAYLIB_INSTALL_PATH) mkdir --parents --verbose $(RAYLIB_H_INSTALL_PATH) - ifeq ($(RAYLIB_LIBTYPE),SHARED) - # Installing raylib to $(RAYLIB_INSTALL_PATH). + ifeq ($(RAYLIB_LIBTYPE),SHARED) + # Installing raylib to $(RAYLIB_INSTALL_PATH). cp --update --verbose $(RAYLIB_RELEASE_PATH)/libraylib.so.$(RAYLIB_VERSION) $(RAYLIB_INSTALL_PATH)/libraylib.so.$(RAYLIB_VERSION) cd $(RAYLIB_INSTALL_PATH); ln -fsv libraylib.so.$(RAYLIB_VERSION) libraylib.so.$(RAYLIB_API_VERSION) cd $(RAYLIB_INSTALL_PATH); ln -fsv libraylib.so.$(RAYLIB_API_VERSION) libraylib.so - # Uncomment to update the runtime linker cache with RAYLIB_INSTALL_PATH. - # Not necessary if later embedding RPATH in your executable. See examples/Makefile. + # Uncomment to update the runtime linker cache with RAYLIB_INSTALL_PATH. + # Not necessary if later embedding RPATH in your executable. See examples/Makefile. ldconfig $(RAYLIB_INSTALL_PATH) - else - # Installing raylib to $(RAYLIB_INSTALL_PATH). + else + # Installing raylib to $(RAYLIB_INSTALL_PATH). cp --update --verbose $(RAYLIB_RELEASE_PATH)/libraylib.a $(RAYLIB_INSTALL_PATH)/libraylib.a - endif - # Copying raylib development files to $(RAYLIB_H_INSTALL_PATH). + endif + # Copying raylib development files to $(RAYLIB_H_INSTALL_PATH). cp --update raylib.h $(RAYLIB_H_INSTALL_PATH)/raylib.h cp --update raymath.h $(RAYLIB_H_INSTALL_PATH)/raymath.h cp --update rlgl.h $(RAYLIB_H_INSTALL_PATH)/rlgl.h @@ -587,14 +587,14 @@ endif # TODO: see 'install' target. uninstall : ifeq ($(ROOT),root) - # WARNING: You are root, about to delete items from $(RAYLIB_INSTALL_PATH). - # and $(RAYLIB_H_INSTALL_PATH). Please confirm each item. + # WARNING: You are root, about to delete items from $(RAYLIB_INSTALL_PATH). + # and $(RAYLIB_H_INSTALL_PATH). Please confirm each item. ifeq ($(PLATFORM_OS),LINUX) ifeq ($(RAYLIB_LIBTYPE),SHARED) rm --force --interactive --verbose $(RAYLIB_INSTALL_PATH)/libraylib.so rm --force --interactive --verbose $(RAYLIB_INSTALL_PATH)/libraylib.so.$(RAYLIB_API_VERSION) rm --force --interactive --verbose $(RAYLIB_INSTALL_PATH)/libraylib.so.$(RAYLIB_VERSION) - # Uncomment to clean up the runtime linker cache. See install target. + # Uncomment to clean up the runtime linker cache. See install target. ldconfig else rm --force --interactive --verbose $(RAYLIB_INSTALL_PATH)/libraylib.a @@ -98,13 +98,12 @@ #define _POSIX_C_SOURCE 199309L // Required for CLOCK_MONOTONIC if compiled with c99 without gnu ext. #endif +#define RAYMATH_IMPLEMENTATION // Define external out-of-line implementation of raymath here +#include "raymath.h" // Required for: Vector3 and Matrix functions + #include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2 #include "utils.h" // Required for: fopen() Android mapping -#define RAYMATH_IMPLEMENTATION // Use raymath as a header-only library (includes implementation) -#define RAYMATH_EXTERN_INLINE // Compile raymath functions as static inline (remember, it's a compiler hint) -#include "raymath.h" // Required for: Vector3 and Matrix functions - #if defined(SUPPORT_GESTURES_SYSTEM) #define GESTURES_IMPLEMENTATION #include "gestures.h" // Gestures detection functionality @@ -127,6 +126,7 @@ #include <math.h> // Required for: tan() [Used in Begin3dMode() to set perspective] #include <string.h> // Required for: strrchr(), strcmp() //#include <errno.h> // Macros for reporting and retrieving error conditions through error codes +#include <ctype.h> // Required for: tolower() [Used in IsFileExtension()] #if defined(_WIN32) #include <direct.h> // Required for: _getch(), _chdir() @@ -238,9 +238,10 @@ static GLFWwindow *window; // Native window (graphic device static bool windowReady = false; // Check if window has been initialized successfully static bool windowMinimized = false; // Check if window has been minimized +static const char *windowTitle = NULL; // Window text title... #if defined(PLATFORM_ANDROID) -static struct android_app *app; // Android activity +static struct android_app *androidApp; // Android activity static struct android_poll_source *source; // Android events polling source static int ident, events; // Android ALooper_pollAll() variables static const char *internalDataPath; // Android internal data path to write data (/data/data/<package>/files) @@ -283,10 +284,10 @@ static bool windowShouldClose = false; // Flag to set window for closing #endif #if defined(PLATFORM_UWP) -static EGLNativeWindowType uwpWindow; +extern EGLNativeWindowType uwpWindow; // Native EGL window handler for UWP (external, defined in UWP App) #endif -// Display size-related data +// Screen related variables static unsigned int displayWidth, displayHeight; // Display width and height (monitor, device-screen, LCD, ...) static int screenWidth, screenHeight; // Screen width and height (used render area) static int renderWidth, renderHeight; // Framebuffer width and height (render area, including black bars if required) @@ -294,11 +295,11 @@ static int renderOffsetX = 0; // Offset X from render area (must b static int renderOffsetY = 0; // Offset Y from render area (must be divided by 2) static bool fullscreen = false; // Fullscreen mode (useful only for PLATFORM_DESKTOP) static Matrix downscaleView; // Matrix to downscale view (in case screen size bigger than display size) + static bool cursorHidden = false; // Track if cursor is hidden static bool cursorOnScreen = false; // Tracks if cursor is inside client area #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB) || defined(PLATFORM_UWP) -static const char *windowTitle = NULL; // Window text title... static int screenshotCounter = 0; // Screenshots counter // Register mouse states @@ -326,6 +327,7 @@ static int lastGamepadButtonPressed = -1; // Register last gamepad button pres static int gamepadAxisCount = 0; // Register number of available gamepad axis static Vector2 mousePosition; // Mouse position on screen +static float mouseScale = 1.0f; // Mouse default scale #if defined(PLATFORM_WEB) static bool toggleCursorLock = false; // Ask for cursor pointer lock on next click @@ -415,7 +417,7 @@ static void *GamepadThread(void *arg); // Mouse reading thread #endif #if defined(PLATFORM_UWP) -// Define functions required to manage inputs +// TODO: Define functions required to manage inputs #endif #if defined(_WIN32) @@ -426,29 +428,97 @@ static void *GamepadThread(void *arg); // Mouse reading thread //---------------------------------------------------------------------------------- // Module Functions Definition - Window and OpenGL Context Functions //---------------------------------------------------------------------------------- -#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB) || defined(PLATFORM_UWP) + +#if defined(PLATFORM_ANDROID) +// To allow easier porting to android, we allow the user to define a +// main function which we call from android_main, defined by ourselves +extern int main(int argc, char *argv[]); + +void android_main(struct android_app *app) +{ + char arg0[] = "raylib"; // NOTE: argv[] are mutable + androidApp = app; + + // TODO: Should we maybe report != 0 return codes somewhere? + (void)main(1, (char*[]) { arg0, NULL }); +} + +// TODO: Add this to header (if apps really need it) +struct android_app *GetAndroidApp(void) +{ + return androidApp; +} +#endif + // Initialize window and OpenGL context // NOTE: data parameter could be used to pass any kind of required data to the initialization -void InitWindow(int width, int height, void *data) +void InitWindow(int width, int height, const char *title) { - TraceLog(LOG_INFO, "Initializing raylib (v1.9.4-dev)"); + TraceLog(LOG_INFO, "Initializing raylib (v1.9.6-dev)"); -#if defined(PLATFORM_DESKTOP) - windowTitle = (char *)data; -#endif + windowTitle = title; +#if defined(PLATFORM_ANDROID) + screenWidth = width; + screenHeight = height; -#if defined(PLATFORM_UWP) - uwpWindow = (EGLNativeWindowType)data; -#endif + // Input data is android app pointer + internalDataPath = androidApp->activity->internalDataPath; - // Init hi-res timer - InitTimer(); + // Set desired windows flags before initializing anything + ANativeActivity_setWindowFlags(androidApp->activity, AWINDOW_FLAG_FULLSCREEN, 0); //AWINDOW_FLAG_SCALED, AWINDOW_FLAG_DITHER + //ANativeActivity_setWindowFlags(androidApp->activity, AWINDOW_FLAG_FORCE_NOT_FULLSCREEN, AWINDOW_FLAG_FULLSCREEN); + + int orientation = AConfiguration_getOrientation(androidApp->config); + + if (orientation == ACONFIGURATION_ORIENTATION_PORT) TraceLog(LOG_INFO, "PORTRAIT window orientation"); + else if (orientation == ACONFIGURATION_ORIENTATION_LAND) TraceLog(LOG_INFO, "LANDSCAPE window orientation"); + + // TODO: Automatic orientation doesn't seem to work + if (width <= height) + { + AConfiguration_setOrientation(androidApp->config, ACONFIGURATION_ORIENTATION_PORT); + TraceLog(LOG_WARNING, "Window set to portraid mode"); + } + else + { + AConfiguration_setOrientation(androidApp->config, ACONFIGURATION_ORIENTATION_LAND); + TraceLog(LOG_WARNING, "Window set to landscape mode"); + } + + //AConfiguration_getDensity(androidApp->config); + //AConfiguration_getKeyboard(androidApp->config); + //AConfiguration_getScreenSize(androidApp->config); + //AConfiguration_getScreenLong(androidApp->config); + + androidApp->onAppCmd = AndroidCommandCallback; + androidApp->onInputEvent = AndroidInputCallback; + + InitAssetManager(androidApp->activity->assetManager); + + TraceLog(LOG_INFO, "Android app initialized successfully"); + + // Wait for window to be initialized (display and context) + while (!windowReady) + { + // Process events loop + while ((ident = ALooper_pollAll(0, NULL, &events, (void**)&source)) >= 0) + { + // Process this event + if (source != NULL) source->process(androidApp, source); + // NOTE: Never close window, native activity is controlled by the system! + //if (androidApp->destroyRequested != 0) windowShouldClose = true; + } + } +#else // Init graphics device (display device and OpenGL context) // NOTE: returns true if window and graphic device has been initialized successfully windowReady = InitGraphicsDevice(width, height); if (!windowReady) return; + // Init hi-res timer + InitTimer(); + #if defined(SUPPORT_DEFAULT_FONT) // Load default font // NOTE: External function (defined in module: text) @@ -494,71 +564,8 @@ void InitWindow(int width, int height, void *data) SetTargetFPS(60); LogoAnimation(); } +#endif // defined(PLATFORM_ANDROID) } -#endif - -#if defined(PLATFORM_ANDROID) -// Initialize window and OpenGL context (and Android activity) -// NOTE: data parameter could be used to pass any kind of required data to the initialization -void InitWindow(int width, int height, void *data) -{ - TraceLog(LOG_INFO, "Initializing raylib (v1.9.4-dev)"); - - screenWidth = width; - screenHeight = height; - - // Input data is android app pointer - app = (struct android_app *)data; - internalDataPath = app->activity->internalDataPath; - - // Set desired windows flags before initializing anything - ANativeActivity_setWindowFlags(app->activity, AWINDOW_FLAG_FULLSCREEN, 0); //AWINDOW_FLAG_SCALED, AWINDOW_FLAG_DITHER - //ANativeActivity_setWindowFlags(app->activity, AWINDOW_FLAG_FORCE_NOT_FULLSCREEN, AWINDOW_FLAG_FULLSCREEN); - - int orientation = AConfiguration_getOrientation(app->config); - - if (orientation == ACONFIGURATION_ORIENTATION_PORT) TraceLog(LOG_INFO, "PORTRAIT window orientation"); - else if (orientation == ACONFIGURATION_ORIENTATION_LAND) TraceLog(LOG_INFO, "LANDSCAPE window orientation"); - - // TODO: Automatic orientation doesn't seem to work - if (width <= height) - { - AConfiguration_setOrientation(app->config, ACONFIGURATION_ORIENTATION_PORT); - TraceLog(LOG_WARNING, "Window set to portraid mode"); - } - else - { - AConfiguration_setOrientation(app->config, ACONFIGURATION_ORIENTATION_LAND); - TraceLog(LOG_WARNING, "Window set to landscape mode"); - } - - //AConfiguration_getDensity(app->config); - //AConfiguration_getKeyboard(app->config); - //AConfiguration_getScreenSize(app->config); - //AConfiguration_getScreenLong(app->config); - - app->onAppCmd = AndroidCommandCallback; - app->onInputEvent = AndroidInputCallback; - - InitAssetManager(app->activity->assetManager); - - TraceLog(LOG_INFO, "Android app initialized successfully"); - - // Wait for window to be initialized (display and context) - while (!windowReady) - { - // Process events loop - while ((ident = ALooper_pollAll(0, NULL, &events,(void**)&source)) >= 0) - { - // Process this event - if (source != NULL) source->process(app, source); - - // NOTE: Never close window, native activity is controlled by the system! - //if (app->destroyRequested != 0) windowShouldClose = true; - } - } -} -#endif // Close window and unload OpenGL context void CloseWindow(void) @@ -736,6 +743,15 @@ void SetWindowMinSize(int width, int height) #endif } +// Set window dimensions +void SetWindowSize(int width, int height) +{ +#if defined(PLATFORM_DESKTOP) + glfwSetWindowSize(window, width, height); +#endif +} + + // Get current screen width int GetScreenWidth(void) { @@ -909,13 +925,26 @@ void Begin3dMode(Camera camera) rlPushMatrix(); // Save previous matrix, which contains the settings for the 2d ortho projection rlLoadIdentity(); // Reset current matrix (PROJECTION) - // Setup perspective projection float aspect = (float)screenWidth/(float)screenHeight; - double top = 0.01*tan(camera.fovy*0.5*DEG2RAD); - double right = top*aspect; + + if(camera.type == CAMERA_PERSPECTIVE) + { + // Setup perspective projection + double top = 0.01*tan(camera.fovy*0.5*DEG2RAD); + double right = top*aspect; + + rlFrustum(-right, right, -top, top, 0.01, 1000.0); + } + else if(camera.type == CAMERA_ORTHOGRAPHIC) + { + // Setup orthographic projection + double top = camera.fovy/2.0; + double right = top*aspect; + + rlOrtho(-right,right,-top,top, 0.01, 1000.0); + } // NOTE: zNear and zFar values are important when computing depth buffer values - rlFrustum(-right, right, -top, top, 0.01, 1000.0); rlMatrixMode(RL_MODELVIEW); // Switch back to modelview matrix rlLoadIdentity(); // Reset current matrix (MODELVIEW) @@ -1003,22 +1032,47 @@ Ray GetMouseRay(Vector2 mousePosition, Camera camera) TraceLog(LOG_DEBUG, "Device coordinates: (%f, %f, %f)", deviceCoords.x, deviceCoords.y, deviceCoords.z); - // Calculate projection matrix from perspective - Matrix matProj = MatrixPerspective(camera.fovy*DEG2RAD, ((double)GetScreenWidth()/(double)GetScreenHeight()), 0.01, 1000.0); - // Calculate view matrix from camera look at Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up); + Matrix matProj; + + if(camera.type == CAMERA_PERSPECTIVE) + { + // Calculate projection matrix from perspective + matProj = MatrixPerspective(camera.fovy*DEG2RAD, ((double)GetScreenWidth()/(double)GetScreenHeight()), 0.01, 1000.0); + } + else if(camera.type == CAMERA_ORTHOGRAPHIC) + { + float aspect = (float)screenWidth/(float)screenHeight; + double top = camera.fovy/2.0; + double right = top*aspect; + // Calculate projection matrix from orthographic + matProj = MatrixOrtho(-right, right, -top, top, 0.01, 1000.0); + } + // Unproject far/near points Vector3 nearPoint = rlUnproject((Vector3){ deviceCoords.x, deviceCoords.y, 0.0f }, matProj, matView); Vector3 farPoint = rlUnproject((Vector3){ deviceCoords.x, deviceCoords.y, 1.0f }, matProj, matView); + // Unproject the mouse cursor in the near plane. + // We need this as the source position because orthographic projects, compared to perspect doesn't have a + // convergence point, meaning that the "eye" of the camera is more like a plane than a point. + Vector3 cameraPlanePointerPos = rlUnproject((Vector3){ deviceCoords.x, deviceCoords.y, -1.0f }, matProj, matView); + // Calculate normalized direction vector - Vector3 direction = Vector3Subtract(farPoint, nearPoint); - Vector3Normalize(&direction); + Vector3 direction = Vector3Normalize(Vector3Subtract(farPoint, nearPoint)); + + if(camera.type == CAMERA_PERSPECTIVE) + { + ray.position = camera.position; + } + else if(camera.type == CAMERA_ORTHOGRAPHIC) + { + ray.position = cameraPlanePointerPos; + } // Apply calculated vectors to ray - ray.position = camera.position; ray.direction = direction; return ray; @@ -1028,7 +1082,21 @@ Ray GetMouseRay(Vector2 mousePosition, Camera camera) Vector2 GetWorldToScreen(Vector3 position, Camera camera) { // Calculate projection matrix (from perspective instead of frustum - Matrix matProj = MatrixPerspective(camera.fovy*DEG2RAD, (double)GetScreenWidth()/(double)GetScreenHeight(), 0.01, 1000.0); + Matrix matProj; + + if(camera.type == CAMERA_PERSPECTIVE) + { + // Calculate projection matrix from perspective + matProj = MatrixPerspective(camera.fovy*DEG2RAD, ((double)GetScreenWidth()/(double)GetScreenHeight()), 0.01, 1000.0); + } + else if(camera.type == CAMERA_ORTHOGRAPHIC) + { + float aspect = (float)screenWidth/(float)screenHeight; + double top = camera.fovy/2.0; + double right = top*aspect; + // Calculate projection matrix from orthographic + matProj = MatrixOrtho(-right, right, -top, top, 0.01, 1000.0); + } // Calculate view matrix from camera look at (and transpose it) Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up); @@ -1037,10 +1105,10 @@ Vector2 GetWorldToScreen(Vector3 position, Camera camera) Quaternion worldPos = { position.x, position.y, position.z, 1.0f }; // Transform world position to view - QuaternionTransform(&worldPos, matView); + worldPos = QuaternionTransform(worldPos, matView); // Transform result to projection (clip space position) - QuaternionTransform(&worldPos, matProj); + worldPos = QuaternionTransform(worldPos, matProj); // Calculate normalized device coordinates (inverted y) Vector3 ndcPos = { worldPos.x/worldPos.w, -worldPos.y/worldPos.w, worldPos.z/worldPos.w }; @@ -1244,6 +1312,28 @@ bool IsFileExtension(const char *fileName, const char *ext) { if (strcmp(fileExt, ext) == 0) result = true; } + + if ((fileExt = strrchr(fileName, '.')) != NULL) + { + #if defined(_WIN32) + result = true; + int extLen = strlen(ext); + + if (strlen(fileExt) == extLen) + { + for (int i = 0; i < extLen; i++) + { + if (tolower(fileExt[i]) != tolower(ext[i])) + { + result = false; + break; + } + } + } + #else + if (strcmp(fileExt, ext) == 0) result = true; + #endif + } return result; } @@ -1253,7 +1343,7 @@ const char *GetExtension(const char *fileName) { const char *dot = strrchr(fileName, '.'); - if (!dot || dot == fileName) return ""; + if (!dot || dot == fileName) return NULL; return (dot + 1); } @@ -1648,7 +1738,7 @@ int GetMouseX(void) #if defined(PLATFORM_ANDROID) return (int)touchPosition[0].x; #else - return (int)mousePosition.x; + return (int)(mousePosition.x*mouseScale); #endif } @@ -1658,7 +1748,7 @@ int GetMouseY(void) #if defined(PLATFORM_ANDROID) return (int)touchPosition[0].x; #else - return (int)mousePosition.y; + return (int)(mousePosition.y*mouseScale); #endif } @@ -1668,7 +1758,7 @@ Vector2 GetMousePosition(void) #if defined(PLATFORM_ANDROID) return GetTouchPosition(0); #else - return mousePosition; + return (Vector2){ mousePosition.x*mouseScale, mousePosition.y*mouseScale }; #endif } @@ -1682,6 +1772,15 @@ void SetMousePosition(Vector2 position) #endif } +// Set mouse scaling +// NOTE: Useful when rendering to different size targets +void SetMouseScale(float scale) +{ +#if !defined(PLATFORM_ANDROID) + mouseScale = scale; +#endif +} + // Returns mouse wheel movement Y int GetMouseWheelMove(void) { @@ -2107,7 +2206,7 @@ static bool InitGraphicsDevice(int width, int height) } } - //SetupFramebufferSize(displayWidth, displayHeight); + //SetupFramebufferSize(displayWidth, displayHeight); EGLint numConfigs = 0; if ((eglChooseConfig(display, framebufferAttribs, &config, 1, &numConfigs) == EGL_FALSE) || (numConfigs == 0)) @@ -2161,9 +2260,9 @@ static bool InitGraphicsDevice(int width, int height) return false; } - // Get EGL display window size - eglQuerySurface(display, surface, EGL_WIDTH, &screenWidth); - eglQuerySurface(display, surface, EGL_HEIGHT, &screenHeight); + // Get EGL display window size + eglQuerySurface(display, surface, EGL_WIDTH, &screenWidth); + eglQuerySurface(display, surface, EGL_HEIGHT, &screenHeight); #else // PLATFORM_ANDROID, PLATFORM_RPI EGLint numConfigs; @@ -2204,8 +2303,8 @@ static bool InitGraphicsDevice(int width, int height) #if defined(PLATFORM_ANDROID) EGLint displayFormat; - displayWidth = ANativeWindow_getWidth(app->window); - displayHeight = ANativeWindow_getHeight(app->window); + displayWidth = ANativeWindow_getWidth(androidApp->window); + displayHeight = ANativeWindow_getHeight(androidApp->window); // EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is guaranteed to be accepted by ANativeWindow_setBuffersGeometry() // As soon as we picked a EGLConfig, we can safely reconfigure the ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID @@ -2215,10 +2314,10 @@ static bool InitGraphicsDevice(int width, int height) // NOTE: This function use and modify global module variables: screenWidth/screenHeight and renderWidth/renderHeight and downscaleView SetupFramebufferSize(displayWidth, displayHeight); - ANativeWindow_setBuffersGeometry(app->window, renderWidth, renderHeight, displayFormat); - //ANativeWindow_setBuffersGeometry(app->window, 0, 0, displayFormat); // Force use of native display size + ANativeWindow_setBuffersGeometry(androidApp->window, renderWidth, renderHeight, displayFormat); + //ANativeWindow_setBuffersGeometry(androidApp->window, 0, 0, displayFormat); // Force use of native display size - surface = eglCreateWindowSurface(display, config, app->window, NULL); + surface = eglCreateWindowSurface(display, config, androidApp->window, NULL); #endif // defined(PLATFORM_ANDROID) #if defined(PLATFORM_RPI) @@ -2282,8 +2381,8 @@ static bool InitGraphicsDevice(int width, int height) } #endif // defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) - renderWidth = screenWidth; - renderHeight = screenHeight; + renderWidth = screenWidth; + renderHeight = screenHeight; // Initialize OpenGL context (states and resources) // NOTE: screenWidth and screenHeight not used, just stored as globals @@ -2624,14 +2723,14 @@ static void PollInputEvents(void) while ((ident = ALooper_pollAll(appEnabled ? 0 : -1, NULL, &events,(void**)&source)) >= 0) { // Process this event - if (source != NULL) source->process(app, source); + if (source != NULL) source->process(androidApp, source); // NOTE: Never close window, native activity is controlled by the system! - if (app->destroyRequested != 0) + if (androidApp->destroyRequested != 0) { //TraceLog(LOG_INFO, "Closing Window..."); //windowShouldClose = true; - //ANativeActivity_finish(app->activity); + //ANativeActivity_finish(androidApp->activity); } } #endif @@ -2968,14 +3067,14 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd) case APP_CMD_DESTROY: { // TODO: Finish activity? - //ANativeActivity_finish(app->activity); + //ANativeActivity_finish(androidApp->activity); TraceLog(LOG_INFO, "APP_CMD_DESTROY"); } break; case APP_CMD_CONFIG_CHANGED: { - //AConfiguration_fromAssetManager(app->config, app->activity->assetManager); - //print_cur_config(app); + //AConfiguration_fromAssetManager(androidApp->config, androidApp->activity->assetManager); + //print_cur_config(androidApp); // Check screen orientation here! diff --git a/src/external/mini_al.h b/src/external/mini_al.h index 1374de5b..5036d267 100644 --- a/src/external/mini_al.h +++ b/src/external/mini_al.h @@ -6412,6 +6412,7 @@ static mal_result mal_device_init__alsa(mal_context* pContext, mal_device_type t free(NAME); free(DESC); free(IOID); + ppNextDeviceHint += 1; if (foundDevice) { break; @@ -6974,7 +6975,7 @@ static mal_result mal_device_init__oss(mal_context* pContext, mal_device_type ty // When not using MMAP mode, we need to use an intermediary buffer for the client <-> device transfer. We do // everything by the size of a fragment. - pDevice->oss.pIntermediaryBuffer = mal_malloc(fragmentSizeInBytes); + pDevice->oss.pIntermediaryBuffer = mal_malloc(actualFragmentSizeInBytes); if (pDevice->oss.pIntermediaryBuffer == NULL) { close(pDevice->oss.fd); return mal_post_error(pDevice, "[OSS] Failed to allocate memory for intermediary buffer.", MAL_OUT_OF_MEMORY); diff --git a/src/models.c b/src/models.c index aae3bd86..f9aa1805 100644 --- a/src/models.c +++ b/src/models.c @@ -1179,9 +1179,9 @@ Mesh GenMeshHeightmap(Image heightmap, Vector3 size) Color *pixels = GetImageData(heightmap); // NOTE: One vertex per pixel - int triangleCount = (mapX-1)*(mapZ-1)*2; // One quad every four pixels + mesh.triangleCount = (mapX-1)*(mapZ-1)*2; // One quad every four pixels - mesh.vertexCount = triangleCount*3; + mesh.vertexCount = mesh.triangleCount*3; mesh.vertices = (float *)malloc(mesh.vertexCount*3*sizeof(float)); mesh.normals = (float *)malloc(mesh.vertexCount*3*sizeof(float)); @@ -1584,6 +1584,7 @@ Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize) // Move data from mapVertices temp arays to vertices float array mesh.vertexCount = vCounter; + mesh.triangleCount = vCounter/3; mesh.vertices = (float *)malloc(mesh.vertexCount*3*sizeof(float)); mesh.normals = (float *)malloc(mesh.vertexCount*3*sizeof(float)); @@ -1758,8 +1759,8 @@ void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, Vec | | d-------c */ - Vector3Scale(&right, sizeRatio.x/2); - Vector3Scale(&up, sizeRatio.y/2); + right = Vector3Scale(right, sizeRatio.x/2); + up = Vector3Scale(up, sizeRatio.y/2); Vector3 p1 = Vector3Add(right, up); Vector3 p2 = Vector3Subtract(right, up); @@ -1888,16 +1889,14 @@ bool CheckCollisionRaySphereEx(Ray ray, Vector3 spherePosition, float sphereRadi if (d >= 0.0f) collision = true; - // Calculate collision point - Vector3 offset = ray.direction; + // Check if ray origin is inside the sphere to calculate the correct collision point float collisionDistance = 0; - // Check if ray origin is inside the sphere to calculate the correct collision point if (distance < sphereRadius) collisionDistance = vector + sqrtf(d); else collisionDistance = vector - sqrtf(d); - - Vector3Scale(&offset, collisionDistance); - Vector3 cPoint = Vector3Add(ray.position, offset); + + // Calculate collision point + Vector3 cPoint = Vector3Add(ray.position, Vector3Scale(ray.direction, collisionDistance)); collisionPoint->x = cPoint.x; collisionPoint->y = cPoint.y; @@ -2020,11 +2019,8 @@ RayHitInfo GetCollisionRayTriangle(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3) result.hit = true; result.distance = t; result.hit = true; - result.normal = Vector3CrossProduct(edge1, edge2); - Vector3Normalize(&result.normal); - Vector3 rayDir = ray.direction; - Vector3Scale(&rayDir, t); - result.position = Vector3Add(ray.position, rayDir); + result.normal = Vector3Normalize(Vector3CrossProduct(edge1, edge2)); + result.position = Vector3Add(ray.position, Vector3Scale(ray.direction, t)); } return result; @@ -2039,16 +2035,14 @@ RayHitInfo GetCollisionRayGround(Ray ray, float groundHeight) if (fabsf(ray.direction.y) > EPSILON) { - float t = (ray.position.y - groundHeight)/-ray.direction.y; + float distance = (ray.position.y - groundHeight)/-ray.direction.y; - if (t >= 0.0) + if (distance >= 0.0) { - Vector3 rayDir = ray.direction; - Vector3Scale(&rayDir, t); result.hit = true; - result.distance = t; + result.distance = distance; result.normal = (Vector3){ 0.0, 1.0, 0.0 }; - result.position = Vector3Add(ray.position, rayDir); + result.position = Vector3Add(ray.position, Vector3Scale(ray.direction, distance)); } } @@ -2299,7 +2293,7 @@ static Mesh LoadOBJ(const char *fileName) { // If normals not defined, they are calculated from the 3 vertices [N = (V2 - V1) x (V3 - V1)] Vector3 norm = Vector3CrossProduct(Vector3Subtract(midVertices[vCount[1]-1], midVertices[vCount[0]-1]), Vector3Subtract(midVertices[vCount[2]-1], midVertices[vCount[0]-1])); - Vector3Normalize(&norm); + norm = Vector3Normalize(norm); mesh.normals[nCounter] = norm.x; mesh.normals[nCounter + 1] = norm.y; diff --git a/src/physac.h b/src/physac.h index 463d8950..7fa62545 100644 --- a/src/physac.h +++ b/src/physac.h @@ -43,7 +43,7 @@ * NOTE 2: Physac requires static C library linkage to avoid dependency on MinGW DLL (-static -lpthread) * * Use the following code to compile: -* gcc -o $(NAME_PART).exe $(FILE_NAME) -s icon\physac_icon -static -lraylib -lpthread -lopengl32 -lgdi32 -std=c99 +* gcc -o $(NAME_PART).exe $(FILE_NAME) -s $(RAYLIB_DIR)\raylib\raylib_icon -static -lraylib -lpthread -lopengl32 -lgdi32 -std=c99 * * VERY THANKS TO: * Ramon Santamaria (github: @raysan5) @@ -51,7 +51,7 @@ * * LICENSE: zlib/libpng * -* Copyright (c) 2016-2017 Victor Fisac (github: @victorfisac) +* Copyright (c) 2016-2018 Victor Fisac (github: @victorfisac) * * 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. @@ -132,8 +132,7 @@ typedef enum PhysicsShapeType { PHYSICS_CIRCLE, PHYSICS_POLYGON } PhysicsShapeTy typedef struct PhysicsBodyData *PhysicsBody; // Mat2 type (used for polygon shape rotation matrix) -typedef struct Mat2 -{ +typedef struct Mat2 { float m00; float m01; float m10; @@ -142,15 +141,15 @@ typedef struct Mat2 typedef struct PolygonData { unsigned int vertexCount; // Current used vertex and normals count - Vector2 vertices[PHYSAC_MAX_VERTICES]; // Polygon vertex positions vectors + Vector2 positions[PHYSAC_MAX_VERTICES]; // Polygon vertex positions vectors Vector2 normals[PHYSAC_MAX_VERTICES]; // Polygon vertex normals vectors - Mat2 transform; // Vertices transform matrix 2x2 } PolygonData; typedef struct PhysicsShape { PhysicsShapeType type; // Physics shape type (circle or polygon) PhysicsBody body; // Shape physics body reference float radius; // Circle shape radius (used for circle shapes) + Mat2 transform; // Vertices transform matrix 2x2 PolygonData vertexData; // Polygon shape vertices position and normals data (just used for polygon shapes) } PhysicsShape; @@ -194,11 +193,6 @@ extern "C" { // Prevents name mangling of fun #endif //---------------------------------------------------------------------------------- -// Global Variables Definition -//---------------------------------------------------------------------------------- -//... - -//---------------------------------------------------------------------------------- // Module Functions Declaration //---------------------------------------------------------------------------------- PHYSACDEF void InitPhysics(void); // Initializes physics values, pointers and creates physics loop thread @@ -274,11 +268,8 @@ PHYSACDEF void ClosePhysics(void); #define max(a,b) (((a)>(b))?(a):(b)) #define PHYSAC_FLT_MAX 3.402823466e+38f #define PHYSAC_EPSILON 0.000001f - -//---------------------------------------------------------------------------------- -// Types and Structures Definition -//---------------------------------------------------------------------------------- -// ... +#define PHYSAC_K 1.0f/3.0f +#define PHYSAC_VECTOR_ZERO (Vector2){ 0.0f, 0.0f } //---------------------------------------------------------------------------------- // Global Variables Definition @@ -289,15 +280,15 @@ static pthread_t physicsThreadId; // Physics thread id static unsigned int usedMemory = 0; // Total allocated dynamic memory static bool physicsThreadEnabled = false; // Physics thread enabled state -static double baseTime = 0; // Offset time for MONOTONIC clock -static double startTime = 0; // Start time in milliseconds -static double deltaTime = 0; // Delta time used for physics steps -static double currentTime = 0; // Current time in milliseconds -static uint64_t frequency = 0.0; // Hi-res clock frequency +static double baseTime = 0.0; // Offset time for MONOTONIC clock +static double startTime = 0.0; // Start time in milliseconds +static double deltaTime = 0.0; // Delta time used for physics steps +static double currentTime = 0.0; // Current time in milliseconds +static uint64_t frequency = 0; // Hi-res clock frequency -static double accumulator = 0; // Physics time step delta time accumulator +static double accumulator = 0.0; // Physics time step delta time accumulator static unsigned int stepsCount = 0; // Total physics steps processed -static Vector2 gravityForce = { 0, 9.81f/1000 }; // Physics world gravity force +static Vector2 gravityForce = { 0.0f, 9.81f/1000 }; // Physics world gravity force static PhysicsBody bodies[PHYSAC_MAX_BODIES]; // Physics bodies pointers array static unsigned int physicsBodiesCount = 0; // Physics world current bodies counter static PhysicsManifold contacts[PHYSAC_MAX_MANIFOLDS]; // Physics bodies pointers array @@ -306,10 +297,12 @@ static unsigned int physicsManifoldsCount = 0; // Physics world cur //---------------------------------------------------------------------------------- // Module Internal Functions Declaration //---------------------------------------------------------------------------------- +static int FindAvailableBodyIndex(); // Finds a valid index for a new physics body initialization static PolygonData CreateRandomPolygon(float radius, int sides); // Creates a random polygon shape with max vertex distance from polygon pivot static PolygonData CreateRectanglePolygon(Vector2 pos, Vector2 size); // Creates a rectangle polygon shape based on a min and max positions static void *PhysicsLoop(void *arg); // Physics loop thread function static void PhysicsStep(void); // Physics steps calculations (dynamics, collisions and position corrections) +static int FindAvailableManifoldIndex(); // Finds a valid index for a new manifold initialization static PhysicsManifold CreatePhysicsManifold(PhysicsBody a, PhysicsBody b); // Creates a new physics manifold to solve collision static void DestroyPhysicsManifold(PhysicsManifold manifold); // Unitializes and destroys a physics manifold static void SolvePhysicsManifold(PhysicsManifold manifold); // Solves a created physics manifold between two physics bodies @@ -347,7 +340,7 @@ static Vector2 Vector2Add(Vector2 v1, Vector2 v2); static Vector2 Vector2Subtract(Vector2 v1, Vector2 v2); // Returns the subtract of two given vectors #endif -static inline Mat2 Mat2Radians(float radians); // Creates a matrix 2x2 from a given radians value +static Mat2 Mat2Radians(float radians); // Creates a matrix 2x2 from a given radians value static void Mat2Set(Mat2 *matrix, float radians); // Set values from radians to a created matrix 2x2 static inline Mat2 Mat2Transpose(Mat2 matrix); // Returns the transpose of a given matrix 2x2 static inline Vector2 Mat2MultiplyVector2(Mat2 matrix, Vector2 vector); // Multiplies a vector by a matrix 2x2 @@ -395,56 +388,35 @@ PHYSACDEF PhysicsBody CreatePhysicsBodyRectangle(Vector2 pos, float width, float PhysicsBody newBody = (PhysicsBody)PHYSAC_MALLOC(sizeof(PhysicsBodyData)); usedMemory += sizeof(PhysicsBodyData); - int newId = -1; - for (int i = 0; i < PHYSAC_MAX_BODIES; i++) - { - int currentId = i; - - // Check if current id already exist in other physics body - for (int k = 0; k < physicsBodiesCount; k++) - { - if (bodies[k]->id == currentId) - { - currentId++; - break; - } - } - - // If it is not used, use it as new physics body id - if (currentId == i) - { - newId = i; - break; - } - } - + int newId = FindAvailableBodyIndex(); if (newId != -1) { // Initialize new body with generic values newBody->id = newId; newBody->enabled = true; newBody->position = pos; - newBody->velocity = (Vector2){ 0 }; - newBody->force = (Vector2){ 0 }; - newBody->angularVelocity = 0; - newBody->torque = 0; - newBody->orient = 0; + newBody->velocity = (Vector2){ 0.0f }; + newBody->force = (Vector2){ 0.0f }; + newBody->angularVelocity = 0.0f; + newBody->torque = 0.0f; + newBody->orient = 0.0f; newBody->shape.type = PHYSICS_POLYGON; newBody->shape.body = newBody; + newBody->shape.radius = 0.0f; + newBody->shape.transform = Mat2Radians(0.0f); newBody->shape.vertexData = CreateRectanglePolygon(pos, (Vector2){ width, height }); // Calculate centroid and moment of inertia - Vector2 center = { 0 }; - float area = 0; - float inertia = 0; - const float k = 1.0f/3.0f; + Vector2 center = { 0.0f, 0.0f }; + float area = 0.0f; + float inertia = 0.0f; for (int i = 0; i < newBody->shape.vertexData.vertexCount; i++) { // Triangle vertices, third vertex implied as (0, 0) - Vector2 p1 = newBody->shape.vertexData.vertices[i]; + Vector2 p1 = newBody->shape.vertexData.positions[i]; int nextIndex = (((i + 1) < newBody->shape.vertexData.vertexCount) ? (i + 1) : 0); - Vector2 p2 = newBody->shape.vertexData.vertices[nextIndex]; + Vector2 p2 = newBody->shape.vertexData.positions[nextIndex]; float D = MathCrossVector2(p1, p2); float triangleArea = D/2; @@ -452,12 +424,12 @@ PHYSACDEF PhysicsBody CreatePhysicsBodyRectangle(Vector2 pos, float width, float area += triangleArea; // Use area to weight the centroid average, not just vertex position - center.x += triangleArea*k*(p1.x + p2.x); - center.y += triangleArea*k*(p1.y + p2.y); + center.x += triangleArea*PHYSAC_K*(p1.x + p2.x); + center.y += triangleArea*PHYSAC_K*(p1.y + p2.y); float intx2 = p1.x*p1.x + p2.x*p1.x + p2.x*p2.x; float inty2 = p1.y*p1.y + p2.y*p1.y + p2.y*p2.y; - inertia += (0.25f*k*D)*(intx2 + inty2); + inertia += (0.25f*PHYSAC_K*D)*(intx2 + inty2); } center.x *= 1.0f/area; @@ -467,8 +439,8 @@ PHYSACDEF PhysicsBody CreatePhysicsBodyRectangle(Vector2 pos, float width, float // Note: this is not really necessary for (int i = 0; i < newBody->shape.vertexData.vertexCount; i++) { - newBody->shape.vertexData.vertices[i].x -= center.x; - newBody->shape.vertexData.vertices[i].y -= center.y; + newBody->shape.vertexData.positions[i].x -= center.x; + newBody->shape.vertexData.positions[i].y -= center.y; } newBody->mass = density*area; @@ -477,7 +449,7 @@ PHYSACDEF PhysicsBody CreatePhysicsBodyRectangle(Vector2 pos, float width, float newBody->inverseInertia = ((newBody->inertia != 0.0f) ? 1.0f/newBody->inertia : 0.0f); newBody->staticFriction = 0.4f; newBody->dynamicFriction = 0.2f; - newBody->restitution = 0; + newBody->restitution = 0.0f; newBody->useGravity = true; newBody->isGrounded = false; newBody->freezeOrient = false; @@ -503,56 +475,34 @@ PHYSACDEF PhysicsBody CreatePhysicsBodyPolygon(Vector2 pos, float radius, int si PhysicsBody newBody = (PhysicsBody)PHYSAC_MALLOC(sizeof(PhysicsBodyData)); usedMemory += sizeof(PhysicsBodyData); - int newId = -1; - for (int i = 0; i < PHYSAC_MAX_BODIES; i++) - { - int currentId = i; - - // Check if current id already exist in other physics body - for (int k = 0; k < physicsBodiesCount; k++) - { - if (bodies[k]->id == currentId) - { - currentId++; - break; - } - } - - // If it is not used, use it as new physics body id - if (currentId == i) - { - newId = i; - break; - } - } - + int newId = FindAvailableBodyIndex(); if (newId != -1) { // Initialize new body with generic values newBody->id = newId; newBody->enabled = true; newBody->position = pos; - newBody->velocity = (Vector2){ 0 }; - newBody->force = (Vector2){ 0 }; - newBody->angularVelocity = 0; - newBody->torque = 0; - newBody->orient = 0; + newBody->velocity = PHYSAC_VECTOR_ZERO; + newBody->force = PHYSAC_VECTOR_ZERO; + newBody->angularVelocity = 0.0f; + newBody->torque = 0.0f; + newBody->orient = 0.0f; newBody->shape.type = PHYSICS_POLYGON; newBody->shape.body = newBody; + newBody->shape.transform = Mat2Radians(0.0f); newBody->shape.vertexData = CreateRandomPolygon(radius, sides); // Calculate centroid and moment of inertia - Vector2 center = { 0 }; - float area = 0; - float inertia = 0; - const float alpha = 1.0f/3.0f; + Vector2 center = { 0.0f, 0.0f }; + float area = 0.0f; + float inertia = 0.0f; for (int i = 0; i < newBody->shape.vertexData.vertexCount; i++) { // Triangle vertices, third vertex implied as (0, 0) - Vector2 position1 = newBody->shape.vertexData.vertices[i]; + Vector2 position1 = newBody->shape.vertexData.positions[i]; int nextIndex = (((i + 1) < newBody->shape.vertexData.vertexCount) ? (i + 1) : 0); - Vector2 position2 = newBody->shape.vertexData.vertices[nextIndex]; + Vector2 position2 = newBody->shape.vertexData.positions[nextIndex]; float cross = MathCrossVector2(position1, position2); float triangleArea = cross/2; @@ -560,12 +510,12 @@ PHYSACDEF PhysicsBody CreatePhysicsBodyPolygon(Vector2 pos, float radius, int si area += triangleArea; // Use area to weight the centroid average, not just vertex position - center.x += triangleArea*alpha*(position1.x + position2.x); - center.y += triangleArea*alpha*(position1.y + position2.y); + center.x += triangleArea*PHYSAC_K*(position1.x + position2.x); + center.y += triangleArea*PHYSAC_K*(position1.y + position2.y); float intx2 = position1.x*position1.x + position2.x*position1.x + position2.x*position2.x; float inty2 = position1.y*position1.y + position2.y*position1.y + position2.y*position2.y; - inertia += (0.25f*alpha*cross)*(intx2 + inty2); + inertia += (0.25f*PHYSAC_K*cross)*(intx2 + inty2); } center.x *= 1.0f/area; @@ -575,8 +525,8 @@ PHYSACDEF PhysicsBody CreatePhysicsBodyPolygon(Vector2 pos, float radius, int si // Note: this is not really necessary for (int i = 0; i < newBody->shape.vertexData.vertexCount; i++) { - newBody->shape.vertexData.vertices[i].x -= center.x; - newBody->shape.vertexData.vertices[i].y -= center.y; + newBody->shape.vertexData.positions[i].x -= center.x; + newBody->shape.vertexData.positions[i].y -= center.y; } newBody->mass = density*area; @@ -585,7 +535,7 @@ PHYSACDEF PhysicsBody CreatePhysicsBodyPolygon(Vector2 pos, float radius, int si newBody->inverseInertia = ((newBody->inertia != 0.0f) ? 1.0f/newBody->inertia : 0.0f); newBody->staticFriction = 0.4f; newBody->dynamicFriction = 0.2f; - newBody->restitution = 0; + newBody->restitution = 0.0f; newBody->useGravity = true; newBody->isGrounded = false; newBody->freezeOrient = false; @@ -630,9 +580,9 @@ PHYSACDEF void PhysicsShatter(PhysicsBody body, Vector2 position, float force) for (int i = 0; i < vertexData.vertexCount; i++) { Vector2 positionA = body->position; - Vector2 positionB = Mat2MultiplyVector2(vertexData.transform, Vector2Add(body->position, vertexData.vertices[i])); + Vector2 positionB = Mat2MultiplyVector2(body->shape.transform, Vector2Add(body->position, vertexData.positions[i])); int nextIndex = (((i + 1) < vertexData.vertexCount) ? (i + 1) : 0); - Vector2 positionC = Mat2MultiplyVector2(vertexData.transform, Vector2Add(body->position, vertexData.vertices[nextIndex])); + Vector2 positionC = Mat2MultiplyVector2(body->shape.transform, Vector2Add(body->position, vertexData.positions[nextIndex])); // Check collision between each triangle float alpha = ((positionB.y - positionC.y)*(position.x - positionC.x) + (positionC.x - positionB.x)*(position.y - positionC.y))/ @@ -643,7 +593,7 @@ PHYSACDEF void PhysicsShatter(PhysicsBody body, Vector2 position, float force) float gamma = 1.0f - alpha - beta; - if ((alpha > 0) && (beta > 0) & (gamma > 0)) + if ((alpha > 0.0f) && (beta > 0.0f) & (gamma > 0.0f)) { collision = true; break; @@ -655,8 +605,8 @@ PHYSACDEF void PhysicsShatter(PhysicsBody body, Vector2 position, float force) int count = vertexData.vertexCount; Vector2 bodyPos = body->position; Vector2 vertices[count]; - Mat2 trans = vertexData.transform; - for (int i = 0; i < count; i++) vertices[i] = vertexData.vertices[i]; + Mat2 trans = body->shape.transform; + for (int i = 0; i < count; i++) vertices[i] = vertexData.positions[i]; // Destroy shattered physics body DestroyPhysicsBody(body); @@ -664,7 +614,7 @@ PHYSACDEF void PhysicsShatter(PhysicsBody body, Vector2 position, float force) for (int i = 0; i < count; i++) { int nextIndex = (((i + 1) < count) ? (i + 1) : 0); - Vector2 center = TriangleBarycenter(vertices[i], vertices[nextIndex], (Vector2){ 0, 0 }); + Vector2 center = TriangleBarycenter(vertices[i], vertices[nextIndex], PHYSAC_VECTOR_ZERO); center = Vector2Add(bodyPos, center); Vector2 offset = Vector2Subtract(center, bodyPos); @@ -672,25 +622,24 @@ PHYSACDEF void PhysicsShatter(PhysicsBody body, Vector2 position, float force) PolygonData newData = { 0 }; newData.vertexCount = 3; - newData.transform = trans; - newData.vertices[0] = Vector2Subtract(vertices[i], offset); - newData.vertices[1] = Vector2Subtract(vertices[nextIndex], offset); - newData.vertices[2] = Vector2Subtract(position, center); + newData.positions[0] = Vector2Subtract(vertices[i], offset); + newData.positions[1] = Vector2Subtract(vertices[nextIndex], offset); + newData.positions[2] = Vector2Subtract(position, center); // Separate vertices to avoid unnecessary physics collisions - newData.vertices[0].x *= 0.95f; - newData.vertices[0].y *= 0.95f; - newData.vertices[1].x *= 0.95f; - newData.vertices[1].y *= 0.95f; - newData.vertices[2].x *= 0.95f; - newData.vertices[2].y *= 0.95f; + newData.positions[0].x *= 0.95f; + newData.positions[0].y *= 0.95f; + newData.positions[1].x *= 0.95f; + newData.positions[1].y *= 0.95f; + newData.positions[2].x *= 0.95f; + newData.positions[2].y *= 0.95f; // Calculate polygon faces normals for (int j = 0; j < newData.vertexCount; j++) { int nextVertex = (((j + 1) < newData.vertexCount) ? (j + 1) : 0); - Vector2 face = Vector2Subtract(newData.vertices[nextVertex], newData.vertices[j]); + Vector2 face = Vector2Subtract(newData.positions[nextVertex], newData.positions[j]); newData.normals[j] = (Vector2){ face.y, -face.x }; MathNormalize(&newData.normals[j]); @@ -698,19 +647,19 @@ PHYSACDEF void PhysicsShatter(PhysicsBody body, Vector2 position, float force) // Apply computed vertex data to new physics body shape newBody->shape.vertexData = newData; + newBody->shape.transform = trans; // Calculate centroid and moment of inertia - center = (Vector2){ 0 }; - float area = 0; - float inertia = 0; - const float k = 1.0f/3.0f; + center = PHYSAC_VECTOR_ZERO; + float area = 0.0f; + float inertia = 0.0f; for (int j = 0; j < newBody->shape.vertexData.vertexCount; j++) { // Triangle vertices, third vertex implied as (0, 0) - Vector2 p1 = newBody->shape.vertexData.vertices[j]; + Vector2 p1 = newBody->shape.vertexData.positions[j]; int nextVertex = (((j + 1) < newBody->shape.vertexData.vertexCount) ? (j + 1) : 0); - Vector2 p2 = newBody->shape.vertexData.vertices[nextVertex]; + Vector2 p2 = newBody->shape.vertexData.positions[nextVertex]; float D = MathCrossVector2(p1, p2); float triangleArea = D/2; @@ -718,12 +667,12 @@ PHYSACDEF void PhysicsShatter(PhysicsBody body, Vector2 position, float force) area += triangleArea; // Use area to weight the centroid average, not just vertex position - center.x += triangleArea*k*(p1.x + p2.x); - center.y += triangleArea*k*(p1.y + p2.y); + center.x += triangleArea*PHYSAC_K*(p1.x + p2.x); + center.y += triangleArea*PHYSAC_K*(p1.y + p2.y); float intx2 = p1.x*p1.x + p2.x*p1.x + p2.x*p2.x; float inty2 = p1.y*p1.y + p2.y*p1.y + p2.y*p2.y; - inertia += (0.25f*k*D)*(intx2 + inty2); + inertia += (0.25f*PHYSAC_K*D)*(intx2 + inty2); } center.x *= 1.0f/area; @@ -736,10 +685,10 @@ PHYSACDEF void PhysicsShatter(PhysicsBody body, Vector2 position, float force) // Calculate explosion force direction Vector2 pointA = newBody->position; - Vector2 pointB = Vector2Subtract(newData.vertices[1], newData.vertices[0]); - pointB.x /= 2; - pointB.y /= 2; - Vector2 forceDirection = Vector2Subtract(Vector2Add(pointA, Vector2Add(newData.vertices[0], pointB)), newBody->position); + Vector2 pointB = Vector2Subtract(newData.positions[1], newData.positions[0]); + pointB.x /= 2.0f; + pointB.y /= 2.0f; + Vector2 forceDirection = Vector2Subtract(Vector2Add(pointA, Vector2Add(newData.positions[0], pointB)), newBody->position); MathNormalize(&forceDirection); forceDirection.x *= force; forceDirection.y *= force; @@ -765,11 +714,11 @@ PHYSACDEF int GetPhysicsBodiesCount(void) PHYSACDEF PhysicsBody GetPhysicsBody(int index) { PhysicsBody body = NULL; - + if (index < physicsBodiesCount) { body = bodies[index]; - + if (body == NULL) { #if defined(PHYSAC_DEBUG) @@ -780,7 +729,7 @@ PHYSACDEF PhysicsBody GetPhysicsBody(int index) #if defined(PHYSAC_DEBUG) else printf("[PHYSAC] physics body index is out of bounds"); #endif - + return body; } @@ -788,11 +737,11 @@ PHYSACDEF PhysicsBody GetPhysicsBody(int index) PHYSACDEF int GetPhysicsShapeType(int index) { int result = -1; - + if (index < physicsBodiesCount) { PhysicsBody body = bodies[index]; - + if (body != NULL) result = body->shape.type; #if defined(PHYSAC_DEBUG) else printf("[PHYSAC] error when trying to get a null reference physics body"); @@ -801,7 +750,7 @@ PHYSACDEF int GetPhysicsShapeType(int index) #if defined(PHYSAC_DEBUG) else printf("[PHYSAC] physics body index is out of bounds"); #endif - + return result; } @@ -809,11 +758,11 @@ PHYSACDEF int GetPhysicsShapeType(int index) PHYSACDEF int GetPhysicsShapeVerticesCount(int index) { int result = 0; - + if (index < physicsBodiesCount) { PhysicsBody body = bodies[index]; - + if (body != NULL) { switch (body->shape.type) @@ -830,14 +779,14 @@ PHYSACDEF int GetPhysicsShapeVerticesCount(int index) #if defined(PHYSAC_DEBUG) else printf("[PHYSAC] physics body index is out of bounds"); #endif - + return result; } // Returns transformed position of a body shape (body position + vertex transformed position) PHYSACDEF Vector2 GetPhysicsShapeVertex(PhysicsBody body, int vertex) { - Vector2 position = { 0 }; + Vector2 position = { 0.0f, 0.0f }; if (body != NULL) { @@ -845,13 +794,13 @@ PHYSACDEF Vector2 GetPhysicsShapeVertex(PhysicsBody body, int vertex) { case PHYSICS_CIRCLE: { - position.x = body->position.x + cosf(360/PHYSAC_CIRCLE_VERTICES*vertex*PHYSAC_DEG2RAD)*body->shape.radius; - position.y = body->position.y + sinf(360/PHYSAC_CIRCLE_VERTICES*vertex*PHYSAC_DEG2RAD)*body->shape.radius; + position.x = body->position.x + cosf(360.0f/PHYSAC_CIRCLE_VERTICES*vertex*PHYSAC_DEG2RAD)*body->shape.radius; + position.y = body->position.y + sinf(360.0f/PHYSAC_CIRCLE_VERTICES*vertex*PHYSAC_DEG2RAD)*body->shape.radius; } break; case PHYSICS_POLYGON: { PolygonData vertexData = body->shape.vertexData; - position = Vector2Add(body->position, Mat2MultiplyVector2(vertexData.transform, vertexData.vertices[vertex])); + position = Vector2Add(body->position, Mat2MultiplyVector2(body->shape.transform, vertexData.positions[vertex])); } break; default: break; } @@ -870,7 +819,7 @@ PHYSACDEF void SetPhysicsBodyRotation(PhysicsBody body, float radians) { body->orient = radians; - if (body->shape.type == PHYSICS_POLYGON) body->shape.vertexData.transform = Mat2Radians(radians); + if (body->shape.type == PHYSICS_POLYGON) body->shape.transform = Mat2Radians(radians); } } @@ -892,11 +841,11 @@ PHYSACDEF void DestroyPhysicsBody(PhysicsBody body) } #if defined(PHYSAC_DEBUG) - if (index == -1) printf("[PHYSAC] cannot find body id %i in pointers array\n", id); + if (index == -1) printf("[PHYSAC] cannot find body id %i in pointers array\n", id); #endif // Free body allocated memory - PHYSAC_FREE(bodies[index]); + PHYSAC_FREE(body); usedMemory -= sizeof(PhysicsBodyData); bodies[index] = NULL; @@ -929,7 +878,7 @@ PHYSACDEF void ResetPhysics(void) if (body != NULL) { PHYSAC_FREE(body); - body = NULL; + bodies[i] = NULL; usedMemory -= sizeof(PhysicsBodyData); } } @@ -944,7 +893,7 @@ PHYSACDEF void ResetPhysics(void) if (manifold != NULL) { PHYSAC_FREE(manifold); - manifold = NULL; + contacts[i] = NULL; usedMemory -= sizeof(PhysicsManifoldData); } } @@ -970,27 +919,53 @@ PHYSACDEF void ClosePhysics(void) //---------------------------------------------------------------------------------- // Module Internal Functions Definition //---------------------------------------------------------------------------------- +// Finds a valid index for a new physics body initialization +static int FindAvailableBodyIndex() +{ + int index = -1; + for (int i = 0; i < PHYSAC_MAX_BODIES; i++) + { + int currentId = i; + + // Check if current id already exist in other physics body + for (int k = 0; k < physicsBodiesCount; k++) + { + if (bodies[k]->id == currentId) + { + currentId++; + break; + } + } + + // If it is not used, use it as new physics body id + if (currentId == i) + { + index = i; + break; + } + } + + return index; +} + // Creates a random polygon shape with max vertex distance from polygon pivot static PolygonData CreateRandomPolygon(float radius, int sides) { PolygonData data = { 0 }; data.vertexCount = sides; - float orient = GetRandomNumber(0, 360); - data.transform = Mat2Radians(orient*PHYSAC_DEG2RAD); - // Calculate polygon vertices positions for (int i = 0; i < data.vertexCount; i++) { - data.vertices[i].x = cosf(360/sides*i*PHYSAC_DEG2RAD)*radius; - data.vertices[i].y = sinf(360/sides*i*PHYSAC_DEG2RAD)*radius; + data.positions[i].x = cosf(360.0f/sides*i*PHYSAC_DEG2RAD)*radius; + data.positions[i].y = sinf(360.0f/sides*i*PHYSAC_DEG2RAD)*radius; } // Calculate polygon faces normals for (int i = 0; i < data.vertexCount; i++) { int nextIndex = (((i + 1) < sides) ? (i + 1) : 0); - Vector2 face = Vector2Subtract(data.vertices[nextIndex], data.vertices[i]); + Vector2 face = Vector2Subtract(data.positions[nextIndex], data.positions[i]); data.normals[i] = (Vector2){ face.y, -face.x }; MathNormalize(&data.normals[i]); @@ -1003,21 +978,19 @@ static PolygonData CreateRandomPolygon(float radius, int sides) static PolygonData CreateRectanglePolygon(Vector2 pos, Vector2 size) { PolygonData data = { 0 }; - data.vertexCount = 4; - data.transform = Mat2Radians(0); // Calculate polygon vertices positions - data.vertices[0] = (Vector2){ pos.x + size.x/2, pos.y - size.y/2 }; - data.vertices[1] = (Vector2){ pos.x + size.x/2, pos.y + size.y/2 }; - data.vertices[2] = (Vector2){ pos.x - size.x/2, pos.y + size.y/2 }; - data.vertices[3] = (Vector2){ pos.x - size.x/2, pos.y - size.y/2 }; + data.positions[0] = (Vector2){ pos.x + size.x/2, pos.y - size.y/2 }; + data.positions[1] = (Vector2){ pos.x + size.x/2, pos.y + size.y/2 }; + data.positions[2] = (Vector2){ pos.x - size.x/2, pos.y + size.y/2 }; + data.positions[3] = (Vector2){ pos.x - size.x/2, pos.y - size.y/2 }; // Calculate polygon faces normals for (int i = 0; i < data.vertexCount; i++) { int nextIndex = (((i + 1) < data.vertexCount) ? (i + 1) : 0); - Vector2 face = Vector2Subtract(data.vertices[nextIndex], data.vertices[i]); + Vector2 face = Vector2Subtract(data.positions[nextIndex], data.positions[i]); data.normals[i] = (Vector2){ face.y, -face.x }; MathNormalize(&data.normals[i]); @@ -1053,7 +1026,7 @@ static void *PhysicsLoop(void *arg) accumulator += deltaTime; // Clamp accumulator to max time step to avoid bad performance - MathClamp(&accumulator, 0, PHYSAC_MAX_TIMESTEP); + MathClamp(&accumulator, 0.0, PHYSAC_MAX_TIMESTEP); // Fixed time stepping loop while (accumulator >= PHYSAC_DESIRED_DELTATIME) @@ -1116,9 +1089,7 @@ static void PhysicsStep(void) { if ((bodyA->inverseMass == 0) && (bodyB->inverseMass == 0)) continue; - PhysicsManifold manifold = NULL; - if (bodyA->shape.type == PHYSICS_POLYGON && bodyB->shape.type == PHYSICS_CIRCLE) manifold = CreatePhysicsManifold(bodyB, bodyA); - else manifold = CreatePhysicsManifold(bodyA, bodyB); + PhysicsManifold manifold = CreatePhysicsManifold(bodyA, bodyB); SolvePhysicsManifold(manifold); if (manifold->contactsCount > 0) @@ -1183,19 +1154,16 @@ static void PhysicsStep(void) PhysicsBody body = bodies[i]; if (body != NULL) { - body->force = (Vector2){ 0 }; - body->torque = 0; + body->force = PHYSAC_VECTOR_ZERO; + body->torque = 0.0f; } } } -// Creates a new physics manifold to solve collision -static PhysicsManifold CreatePhysicsManifold(PhysicsBody a, PhysicsBody b) +// Finds a valid index for a new manifold initialization +static int FindAvailableManifoldIndex() { - PhysicsManifold newManifold = (PhysicsManifold)PHYSAC_MALLOC(sizeof(PhysicsManifoldData)); - usedMemory += sizeof(PhysicsManifoldData); - - int newId = -1; + int index = -1; for (int i = 0; i < PHYSAC_MAX_MANIFOLDS; i++) { int currentId = i; @@ -1213,11 +1181,21 @@ static PhysicsManifold CreatePhysicsManifold(PhysicsBody a, PhysicsBody b) // If it is not used, use it as new physics body id if (currentId == i) { - newId = i; + index = i; break; } } + return index; +} + +// Creates a new physics manifold to solve collision +static PhysicsManifold CreatePhysicsManifold(PhysicsBody a, PhysicsBody b) +{ + PhysicsManifold newManifold = (PhysicsManifold)PHYSAC_MALLOC(sizeof(PhysicsManifoldData)); + usedMemory += sizeof(PhysicsManifoldData); + + int newId = FindAvailableManifoldIndex(); if (newId != -1) { // Initialize new manifold with generic values @@ -1225,13 +1203,13 @@ static PhysicsManifold CreatePhysicsManifold(PhysicsBody a, PhysicsBody b) newManifold->bodyA = a; newManifold->bodyB = b; newManifold->penetration = 0; - newManifold->normal = (Vector2){ 0 }; - newManifold->contacts[0] = (Vector2){ 0 }; - newManifold->contacts[1] = (Vector2){ 0 }; + newManifold->normal = PHYSAC_VECTOR_ZERO; + newManifold->contacts[0] = PHYSAC_VECTOR_ZERO; + newManifold->contacts[1] = PHYSAC_VECTOR_ZERO; newManifold->contactsCount = 0; - newManifold->restitution = 0; - newManifold->dynamicFriction = 0; - newManifold->staticFriction = 0; + newManifold->restitution = 0.0f; + newManifold->dynamicFriction = 0.0f; + newManifold->staticFriction = 0.0f; // Add new body to bodies pointers array and update bodies count contacts[physicsManifoldsCount] = newManifold; @@ -1266,7 +1244,7 @@ static void DestroyPhysicsManifold(PhysicsManifold manifold) #endif // Free manifold allocated memory - PHYSAC_FREE(contacts[index]); + PHYSAC_FREE(manifold); usedMemory -= sizeof(PhysicsManifoldData); contacts[index] = NULL; @@ -1320,6 +1298,8 @@ static void SolveCircleToCircle(PhysicsManifold manifold) PhysicsBody bodyA = manifold->bodyA; PhysicsBody bodyB = manifold->bodyB; + if ((bodyA == NULL) || (bodyB == NULL)) return; + // Calculate translational vector, which is normal Vector2 normal = Vector2Subtract(bodyB->position, bodyA->position); @@ -1336,10 +1316,10 @@ static void SolveCircleToCircle(PhysicsManifold manifold) float distance = sqrtf(distSqr); manifold->contactsCount = 1; - if (distance == 0) + if (distance == 0.0f) { manifold->penetration = bodyA->shape.radius; - manifold->normal = (Vector2){ 1, 0 }; + manifold->normal = (Vector2){ 1.0f, 0.0f }; manifold->contacts[0] = bodyA->position; } else @@ -1359,11 +1339,13 @@ static void SolveCircleToPolygon(PhysicsManifold manifold) PhysicsBody bodyA = manifold->bodyA; PhysicsBody bodyB = manifold->bodyB; + if ((bodyA == NULL) || (bodyB == NULL)) return; + manifold->contactsCount = 0; // Transform circle center to polygon transform space Vector2 center = bodyA->position; - center = Mat2MultiplyVector2(Mat2Transpose(bodyB->shape.vertexData.transform), Vector2Subtract(center, bodyB->position)); + center = Mat2MultiplyVector2(Mat2Transpose(bodyB->shape.transform), Vector2Subtract(center, bodyB->position)); // Find edge with minimum penetration // It is the same concept as using support points in SolvePolygonToPolygon @@ -1373,7 +1355,7 @@ static void SolveCircleToPolygon(PhysicsManifold manifold) for (int i = 0; i < vertexData.vertexCount; i++) { - float currentSeparation = MathDot(vertexData.normals[i], Vector2Subtract(center, vertexData.vertices[i])); + float currentSeparation = MathDot(vertexData.normals[i], Vector2Subtract(center, vertexData.positions[i])); if (currentSeparation > bodyA->shape.radius) return; @@ -1385,15 +1367,15 @@ static void SolveCircleToPolygon(PhysicsManifold manifold) } // Grab face's vertices - Vector2 v1 = vertexData.vertices[faceNormal]; + Vector2 v1 = vertexData.positions[faceNormal]; int nextIndex = (((faceNormal + 1) < vertexData.vertexCount) ? (faceNormal + 1) : 0); - Vector2 v2 = vertexData.vertices[nextIndex]; + Vector2 v2 = vertexData.positions[nextIndex]; // Check to see if center is within polygon if (separation < PHYSAC_EPSILON) { manifold->contactsCount = 1; - Vector2 normal = Mat2MultiplyVector2(vertexData.transform, vertexData.normals[faceNormal]); + Vector2 normal = Mat2MultiplyVector2(bodyB->shape.transform, vertexData.normals[faceNormal]); manifold->normal = (Vector2){ -normal.x, -normal.y }; manifold->contacts[0] = (Vector2){ manifold->normal.x*bodyA->shape.radius + bodyA->position.x, manifold->normal.y*bodyA->shape.radius + bodyA->position.y }; manifold->penetration = bodyA->shape.radius; @@ -1405,29 +1387,29 @@ static void SolveCircleToPolygon(PhysicsManifold manifold) float dot2 = MathDot(Vector2Subtract(center, v2), Vector2Subtract(v1, v2)); manifold->penetration = bodyA->shape.radius - separation; - if (dot1 <= 0) // Closest to v1 + if (dot1 <= 0.0f) // Closest to v1 { if (DistSqr(center, v1) > bodyA->shape.radius*bodyA->shape.radius) return; manifold->contactsCount = 1; Vector2 normal = Vector2Subtract(v1, center); - normal = Mat2MultiplyVector2(vertexData.transform, normal); + normal = Mat2MultiplyVector2(bodyB->shape.transform, normal); MathNormalize(&normal); manifold->normal = normal; - v1 = Mat2MultiplyVector2(vertexData.transform, v1); + v1 = Mat2MultiplyVector2(bodyB->shape.transform, v1); v1 = Vector2Add(v1, bodyB->position); manifold->contacts[0] = v1; } - else if (dot2 <= 0) // Closest to v2 + else if (dot2 <= 0.0f) // Closest to v2 { if (DistSqr(center, v2) > bodyA->shape.radius*bodyA->shape.radius) return; manifold->contactsCount = 1; Vector2 normal = Vector2Subtract(v2, center); - v2 = Mat2MultiplyVector2(vertexData.transform, v2); + v2 = Mat2MultiplyVector2(bodyB->shape.transform, v2); v2 = Vector2Add(v2, bodyB->position); manifold->contacts[0] = v2; - normal = Mat2MultiplyVector2(vertexData.transform, normal); + normal = Mat2MultiplyVector2(bodyB->shape.transform, normal); MathNormalize(&normal); manifold->normal = normal; } @@ -1437,7 +1419,7 @@ static void SolveCircleToPolygon(PhysicsManifold manifold) if (MathDot(Vector2Subtract(center, v1), normal) > bodyA->shape.radius) return; - normal = Mat2MultiplyVector2(vertexData.transform, normal); + normal = Mat2MultiplyVector2(bodyB->shape.transform, normal); manifold->normal = (Vector2){ -normal.x, -normal.y }; manifold->contacts[0] = (Vector2){ manifold->normal.x*bodyA->shape.radius + bodyA->position.x, manifold->normal.y*bodyA->shape.radius + bodyA->position.y }; manifold->contactsCount = 1; @@ -1450,17 +1432,21 @@ static void SolvePolygonToCircle(PhysicsManifold manifold) PhysicsBody bodyA = manifold->bodyA; PhysicsBody bodyB = manifold->bodyB; + if ((bodyA == NULL) || (bodyB == NULL)) return; + manifold->bodyA = bodyB; manifold->bodyB = bodyA; SolveCircleToPolygon(manifold); - manifold->normal.x *= -1; - manifold->normal.y *= -1; + manifold->normal.x *= -1.0f; + manifold->normal.y *= -1.0f; } // Solves collision between two polygons shape physics bodies static void SolvePolygonToPolygon(PhysicsManifold manifold) { + if ((manifold->bodyA == NULL) || (manifold->bodyB == NULL)) return; + PhysicsShape bodyA = manifold->bodyA->shape; PhysicsShape bodyB = manifold->bodyB->shape; manifold->contactsCount = 0; @@ -1468,12 +1454,12 @@ static void SolvePolygonToPolygon(PhysicsManifold manifold) // Check for separating axis with A shape's face planes int faceA = 0; float penetrationA = FindAxisLeastPenetration(&faceA, bodyA, bodyB); - if (penetrationA >= 0) return; + if (penetrationA >= 0.0f) return; // Check for separating axis with B shape's face planes int faceB = 0; float penetrationB = FindAxisLeastPenetration(&faceB, bodyB, bodyA); - if (penetrationB >= 0) return; + if (penetrationB >= 0.0f) return; int referenceIndex = 0; bool flip = false; // Always point from A shape to B shape @@ -1502,14 +1488,14 @@ static void SolvePolygonToPolygon(PhysicsManifold manifold) // Setup reference face vertices PolygonData refData = refPoly.vertexData; - Vector2 v1 = refData.vertices[referenceIndex]; + Vector2 v1 = refData.positions[referenceIndex]; referenceIndex = (((referenceIndex + 1) < refData.vertexCount) ? (referenceIndex + 1) : 0); - Vector2 v2 = refData.vertices[referenceIndex]; + Vector2 v2 = refData.positions[referenceIndex]; // Transform vertices to world space - v1 = Mat2MultiplyVector2(refData.transform, v1); + v1 = Mat2MultiplyVector2(refPoly.transform, v1); v1 = Vector2Add(v1, refPoly.body->position); - v2 = Mat2MultiplyVector2(refData.transform, v2); + v2 = Mat2MultiplyVector2(refPoly.transform, v2); v2 = Vector2Add(v2, refPoly.body->position); // Calculate reference face side normal in world space @@ -1532,17 +1518,17 @@ static void SolvePolygonToPolygon(PhysicsManifold manifold) // Keep points behind reference face int currentPoint = 0; // Clipped points behind reference face float separation = MathDot(refFaceNormal, incidentFace[0]) - refC; - if (separation <= 0) + if (separation <= 0.0f) { manifold->contacts[currentPoint] = incidentFace[0]; manifold->penetration = -separation; currentPoint++; } - else manifold->penetration = 0; + else manifold->penetration = 0.0f; separation = MathDot(refFaceNormal, incidentFace[1]) - refC; - if (separation <= 0) + if (separation <= 0.0f) { manifold->contacts[currentPoint] = incidentFace[1]; manifold->penetration += -separation; @@ -1558,18 +1544,18 @@ static void SolvePolygonToPolygon(PhysicsManifold manifold) // Integrates physics forces into velocity static void IntegratePhysicsForces(PhysicsBody body) { - if (body->inverseMass == 0 || !body->enabled) return; + if ((body == NULL) || (body->inverseMass == 0.0f) || !body->enabled) return; - body->velocity.x += (body->force.x*body->inverseMass)*(deltaTime/2); - body->velocity.y += (body->force.y*body->inverseMass)*(deltaTime/2); + body->velocity.x += (body->force.x*body->inverseMass)*(deltaTime/2.0); + body->velocity.y += (body->force.y*body->inverseMass)*(deltaTime/2.0); if (body->useGravity) { - body->velocity.x += gravityForce.x*(deltaTime/2); - body->velocity.y += gravityForce.y*(deltaTime/2); + body->velocity.x += gravityForce.x*(deltaTime/2.0); + body->velocity.y += gravityForce.y*(deltaTime/2.0); } - if (!body->freezeOrient) body->angularVelocity += body->torque*body->inverseInertia*(deltaTime/2); + if (!body->freezeOrient) body->angularVelocity += body->torque*body->inverseInertia*(deltaTime/2.0); } // Initializes physics manifolds to solve collisions @@ -1578,12 +1564,14 @@ static void InitializePhysicsManifolds(PhysicsManifold manifold) PhysicsBody bodyA = manifold->bodyA; PhysicsBody bodyB = manifold->bodyB; + if ((bodyA == NULL) || (bodyB == NULL)) return; + // Calculate average restitution, static and dynamic friction manifold->restitution = sqrtf(bodyA->restitution*bodyB->restitution); manifold->staticFriction = sqrtf(bodyA->staticFriction*bodyB->staticFriction); manifold->dynamicFriction = sqrtf(bodyA->dynamicFriction*bodyB->dynamicFriction); - for (int i = 0; i < 2; i++) + for (int i = 0; i < manifold->contactsCount; i++) { // Caculate radius from center of mass to contact Vector2 radiusA = Vector2Subtract(manifold->contacts[i], bodyA->position); @@ -1592,7 +1580,7 @@ static void InitializePhysicsManifolds(PhysicsManifold manifold) Vector2 crossA = MathCross(bodyA->angularVelocity, radiusA); Vector2 crossB = MathCross(bodyB->angularVelocity, radiusB); - Vector2 radiusV = { 0 }; + Vector2 radiusV = { 0.0f, 0.0f }; radiusV.x = bodyB->velocity.x + crossB.x - bodyA->velocity.x - crossA.x; radiusV.y = bodyB->velocity.y + crossB.y - bodyA->velocity.y - crossA.y; @@ -1608,11 +1596,13 @@ static void IntegratePhysicsImpulses(PhysicsManifold manifold) PhysicsBody bodyA = manifold->bodyA; PhysicsBody bodyB = manifold->bodyB; + if ((bodyA == NULL) || (bodyB == NULL)) return; + // Early out and positional correct if both objects have infinite mass if (fabs(bodyA->inverseMass + bodyB->inverseMass) <= PHYSAC_EPSILON) { - bodyA->velocity = (Vector2){ 0 }; - bodyB->velocity = (Vector2){ 0 }; + bodyA->velocity = PHYSAC_VECTOR_ZERO; + bodyB->velocity = PHYSAC_VECTOR_ZERO; return; } @@ -1623,7 +1613,7 @@ static void IntegratePhysicsImpulses(PhysicsManifold manifold) Vector2 radiusB = Vector2Subtract(manifold->contacts[i], bodyB->position); // Calculate relative velocity - Vector2 radiusV = { 0 }; + Vector2 radiusV = { 0.0f, 0.0f }; radiusV.x = bodyB->velocity.x + MathCross(bodyB->angularVelocity, radiusB).x - bodyA->velocity.x - MathCross(bodyA->angularVelocity, radiusA).x; radiusV.y = bodyB->velocity.y + MathCross(bodyB->angularVelocity, radiusB).y - bodyA->velocity.y - MathCross(bodyA->angularVelocity, radiusA).y; @@ -1631,7 +1621,7 @@ static void IntegratePhysicsImpulses(PhysicsManifold manifold) float contactVelocity = MathDot(radiusV, manifold->normal); // Do not resolve if velocities are separating - if (contactVelocity > 0) return; + if (contactVelocity > 0.0f) return; float raCrossN = MathCrossVector2(radiusA, manifold->normal); float rbCrossN = MathCrossVector2(radiusB, manifold->normal); @@ -1678,7 +1668,7 @@ static void IntegratePhysicsImpulses(PhysicsManifold manifold) if (absImpulseTangent <= PHYSAC_EPSILON) return; // Apply coulumb's law - Vector2 tangentImpulse = { 0 }; + Vector2 tangentImpulse = { 0.0f, 0.0f }; if (absImpulseTangent < impulse*manifold->staticFriction) tangentImpulse = (Vector2){ tangent.x*impulseTangent, tangent.y*impulseTangent }; else tangentImpulse = (Vector2){ tangent.x*-impulse*manifold->dynamicFriction, tangent.y*-impulse*manifold->dynamicFriction }; @@ -1704,13 +1694,13 @@ static void IntegratePhysicsImpulses(PhysicsManifold manifold) // Integrates physics velocity into position and forces static void IntegratePhysicsVelocity(PhysicsBody body) { - if (!body->enabled) return; + if ((body == NULL) ||!body->enabled) return; body->position.x += body->velocity.x*deltaTime; body->position.y += body->velocity.y*deltaTime; if (!body->freezeOrient) body->orient += body->angularVelocity*deltaTime; - Mat2Set(&body->shape.vertexData.transform, body->orient); + Mat2Set(&body->shape.transform, body->orient); IntegratePhysicsForces(body); } @@ -1721,9 +1711,11 @@ static void CorrectPhysicsPositions(PhysicsManifold manifold) PhysicsBody bodyA = manifold->bodyA; PhysicsBody bodyB = manifold->bodyB; - Vector2 correction = { 0 }; - correction.x = (max(manifold->penetration - PHYSAC_PENETRATION_ALLOWANCE, 0)/(bodyA->inverseMass + bodyB->inverseMass))*manifold->normal.x*PHYSAC_PENETRATION_CORRECTION; - correction.y = (max(manifold->penetration - PHYSAC_PENETRATION_ALLOWANCE, 0)/(bodyA->inverseMass + bodyB->inverseMass))*manifold->normal.y*PHYSAC_PENETRATION_CORRECTION; + if ((bodyA == NULL) || (bodyB == NULL)) return; + + Vector2 correction = { 0.0f, 0.0f }; + correction.x = (max(manifold->penetration - PHYSAC_PENETRATION_ALLOWANCE, 0.0f)/(bodyA->inverseMass + bodyB->inverseMass))*manifold->normal.x*PHYSAC_PENETRATION_CORRECTION; + correction.y = (max(manifold->penetration - PHYSAC_PENETRATION_ALLOWANCE, 0.0f)/(bodyA->inverseMass + bodyB->inverseMass))*manifold->normal.y*PHYSAC_PENETRATION_CORRECTION; if (bodyA->enabled) { @@ -1742,12 +1734,12 @@ static void CorrectPhysicsPositions(PhysicsManifold manifold) static Vector2 GetSupport(PhysicsShape shape, Vector2 dir) { float bestProjection = -PHYSAC_FLT_MAX; - Vector2 bestVertex = { 0 }; + Vector2 bestVertex = { 0.0f, 0.0f }; PolygonData data = shape.vertexData; for (int i = 0; i < data.vertexCount; i++) { - Vector2 vertex = data.vertices[i]; + Vector2 vertex = data.positions[i]; float projection = MathDot(vertex, dir); if (projection > bestProjection) @@ -1773,18 +1765,18 @@ static float FindAxisLeastPenetration(int *faceIndex, PhysicsShape shapeA, Physi { // Retrieve a face normal from A shape Vector2 normal = dataA.normals[i]; - Vector2 transNormal = Mat2MultiplyVector2(dataA.transform, normal); + Vector2 transNormal = Mat2MultiplyVector2(shapeA.transform, normal); // Transform face normal into B shape's model space - Mat2 buT = Mat2Transpose(dataB.transform); + Mat2 buT = Mat2Transpose(shapeB.transform); normal = Mat2MultiplyVector2(buT, transNormal); // Retrieve support point from B shape along -n Vector2 support = GetSupport(shapeB, (Vector2){ -normal.x, -normal.y }); // Retrieve vertex on face from A shape, transform into B shape's model space - Vector2 vertex = dataA.vertices[i]; - vertex = Mat2MultiplyVector2(dataA.transform, vertex); + Vector2 vertex = dataA.positions[i]; + vertex = Mat2MultiplyVector2(shapeA.transform, vertex); vertex = Vector2Add(vertex, shapeA.body->position); vertex = Vector2Subtract(vertex, shapeB.body->position); vertex = Mat2MultiplyVector2(buT, vertex); @@ -1813,8 +1805,8 @@ static void FindIncidentFace(Vector2 *v0, Vector2 *v1, PhysicsShape ref, Physics Vector2 referenceNormal = refData.normals[index]; // Calculate normal in incident's frame of reference - referenceNormal = Mat2MultiplyVector2(refData.transform, referenceNormal); // To world space - referenceNormal = Mat2MultiplyVector2(Mat2Transpose(incData.transform), referenceNormal); // To incident's model space + referenceNormal = Mat2MultiplyVector2(ref.transform, referenceNormal); // To world space + referenceNormal = Mat2MultiplyVector2(Mat2Transpose(inc.transform), referenceNormal); // To incident's model space // Find most anti-normal face on polygon int incidentFace = 0; @@ -1832,10 +1824,10 @@ static void FindIncidentFace(Vector2 *v0, Vector2 *v1, PhysicsShape ref, Physics } // Assign face vertices for incident face - *v0 = Mat2MultiplyVector2(incData.transform, incData.vertices[incidentFace]); + *v0 = Mat2MultiplyVector2(inc.transform, incData.positions[incidentFace]); *v0 = Vector2Add(*v0, inc.body->position); incidentFace = (((incidentFace + 1) < incData.vertexCount) ? (incidentFace + 1) : 0); - *v1 = Mat2MultiplyVector2(incData.transform, incData.vertices[incidentFace]); + *v1 = Mat2MultiplyVector2(inc.transform, incData.positions[incidentFace]); *v1 = Vector2Add(*v1, inc.body->position); } @@ -1850,11 +1842,11 @@ static int Clip(Vector2 normal, float clip, Vector2 *faceA, Vector2 *faceB) float distanceB = MathDot(normal, *faceB) - clip; // If negative (behind plane) - if (distanceA <= 0) out[sp++] = *faceA; - if (distanceB <= 0) out[sp++] = *faceB; + if (distanceA <= 0.0f) out[sp++] = *faceA; + if (distanceB <= 0.0f) out[sp++] = *faceB; // If the points are on different sides of the plane - if ((distanceA*distanceB) < 0) + if ((distanceA*distanceB) < 0.0f) { // Push intersection point float alpha = distanceA/(distanceA - distanceB); @@ -1882,7 +1874,7 @@ static bool BiasGreaterThan(float valueA, float valueB) // Returns the barycenter of a triangle given by 3 points static Vector2 TriangleBarycenter(Vector2 v1, Vector2 v2, Vector2 v3) { - Vector2 result = { 0 }; + Vector2 result = { 0.0f, 0.0f }; result.x = (v1.x + v2.x + v3.x)/3; result.y = (v1.y + v2.y + v3.y)/3; @@ -2024,7 +2016,7 @@ static inline Vector2 Vector2Subtract(Vector2 v1, Vector2 v2) #endif // Creates a matrix 2x2 from a given radians value -static inline Mat2 Mat2Radians(float radians) +static Mat2 Mat2Radians(float radians) { float c = cosf(radians); float s = sinf(radians); @@ -2056,4 +2048,4 @@ static inline Vector2 Mat2MultiplyVector2(Mat2 matrix, Vector2 vector) return (Vector2){ matrix.m00*vector.x + matrix.m01*vector.y, matrix.m10*vector.x + matrix.m11*vector.y }; } -#endif // PHYSAC_IMPLEMENTATION +#endif // PHYSAC_IMPLEMENTATION
\ No newline at end of file diff --git a/src/raylib.h b/src/raylib.h index c1d383fd..acca46bd 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1,6 +1,6 @@ /********************************************************************************************** * -* raylib v1.9.4-dev +* raylib v1.9.6-dev * * A simple and easy-to-use library to learn videogames programming (www.raylib.com) * @@ -398,12 +398,19 @@ typedef struct SpriteFont { CharInfo *chars; // Characters info data } SpriteFont; +// Camera projection modes +typedef enum { + CAMERA_PERSPECTIVE = 0, + CAMERA_ORTHOGRAPHIC +} CameraType; + // Camera type, defines a camera position/orientation in 3d space typedef struct Camera { Vector3 position; // Camera position Vector3 target; // Camera target it looks-at Vector3 up; // Camera up vector (rotation over its axis) - float fovy; // Camera field-of-view apperture in Y (degrees) + float fovy; // Camera field-of-view apperture in Y (degrees) in perspective, used as near plane width in orthographic + CameraType type; // Camera type, controlling projection type, either CAMERA_PERSPECTIVE or CAMERA_ORTHOGRAPHIC. } Camera; // Camera2D type, defines a 2d camera @@ -561,7 +568,7 @@ typedef enum { LOC_MAP_METALNESS, // LOC_MAP_SPECULAR LOC_MAP_NORMAL, LOC_MAP_ROUGHNESS, - LOC_MAP_OCCUSION, + LOC_MAP_OCCLUSION, LOC_MAP_EMISSION, LOC_MAP_HEIGHT, LOC_MAP_CUBEMAP, @@ -692,7 +699,7 @@ extern "C" { // Prevents name mangling of functions //------------------------------------------------------------------------------------ // Window-related functions -RLAPI void InitWindow(int width, int height, void *data); // Initialize window and OpenGL context +RLAPI void InitWindow(int width, int height, const char *title); // Initialize window and OpenGL context RLAPI void CloseWindow(void); // Close window and unload OpenGL context RLAPI bool IsWindowReady(void); // Check if window has been initialized successfully RLAPI bool WindowShouldClose(void); // Check if KEY_ESCAPE pressed or Close icon pressed @@ -703,6 +710,7 @@ RLAPI void SetWindowTitle(const char *title); // Set title f RLAPI void SetWindowPosition(int x, int y); // Set window position on screen (only PLATFORM_DESKTOP) RLAPI void SetWindowMonitor(int monitor); // Set monitor for the current window (fullscreen mode) RLAPI void SetWindowMinSize(int width, int height); // Set window minimum dimensions (for FLAG_WINDOW_RESIZABLE) +RLAPI void SetWindowSize(int width, int height); // Set window dimensions RLAPI int GetScreenWidth(void); // Get current screen width RLAPI int GetScreenHeight(void); // Get current screen height @@ -725,7 +733,7 @@ RLAPI void BeginTextureMode(RenderTexture2D target); // Initializes RLAPI void EndTextureMode(void); // Ends drawing to render texture // Screen-space-related functions -RLAPI Ray GetMouseRay(Vector2 mousePosition, Camera camera); // Returns a ray trace from mouse position +RLAPI Ray GetMouseRay(Vector2 mousePosition, Camera camera); // Returns a ray trace from mouse position RLAPI Vector2 GetWorldToScreen(Vector3 position, Camera camera); // Returns the screen space position for a 3d world space position RLAPI Matrix GetCameraMatrix(Camera camera); // Returns camera transform matrix (view matrix) @@ -742,13 +750,6 @@ RLAPI Vector3 ColorToHSV(Color color); // Returns HSV RLAPI Color GetColor(int hexValue); // Returns a Color struct from hexadecimal value RLAPI Color Fade(Color color, float alpha); // Color fade-in or fade-out, alpha goes from 0.0f to 1.0f -// Math useful functions (available from raymath.h) -RLAPI float *Vector3ToFloat(Vector3 vec); // Returns Vector3 as float array -RLAPI float *MatrixToFloat(Matrix mat); // Returns Matrix as float array -RLAPI Vector3 Vector3Zero(void); // Vector with components value 0.0f -RLAPI Vector3 Vector3One(void); // Vector with components value 1.0f -RLAPI Matrix MatrixIdentity(void); // Returns identity matrix - // Misc. functions RLAPI void ShowLogo(void); // Activate raylib logo at startup (can be done with flags) RLAPI void SetConfigFlags(unsigned char flags); // Setup window configuration flags (view FLAGS) @@ -805,6 +806,7 @@ RLAPI int GetMouseX(void); // Returns mouse p RLAPI int GetMouseY(void); // Returns mouse position Y RLAPI Vector2 GetMousePosition(void); // Returns mouse position XY RLAPI void SetMousePosition(Vector2 position); // Set mouse position XY +RLAPI void SetMouseScale(float scale); // Set mouse scaling RLAPI int GetMouseWheelMove(void); // Returns mouse wheel movement Y // Input-related functions: touch diff --git a/src/raymath.h b/src/raymath.h index c29c6b95..22adfe52 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -1,6 +1,6 @@ /********************************************************************************************** * -* raymath v1.1 - Math functions to work with Vector3, Matrix and Quaternions +* raymath v1.2 - Math functions to work with Vector3, Matrix and Quaternions * * CONFIGURATION: * @@ -9,8 +9,9 @@ * If not defined, the library is in header only mode and can be included in other headers * or source files without problems. But only ONE file should hold the implementation. * -* #define RAYMATH_EXTERN_INLINE -* Inlines all functions code, so it runs faster. This requires lots of memory on system. +* #define RAYMATH_HEADER_ONLY +* Define static inline functions code, so #include header suffices for use. +* This may use up lots of memory. * * #define RAYMATH_STANDALONE * Avoid raylib.h header inclusion in this file. @@ -41,8 +42,8 @@ #ifndef RAYMATH_H #define RAYMATH_H -//#define RAYMATH_STANDALONE // NOTE: To use raymath as standalone lib, just uncomment this line -//#define RAYMATH_EXTERN_INLINE // NOTE: To compile functions as static inline, uncomment this line +//#define RAYMATH_STANDALONE // NOTE: To use raymath as standalone lib, just uncomment this line +//#define RAYMATH_HEADER_ONLY // NOTE: To compile functions as static inline, uncomment this line #ifndef RAYMATH_STANDALONE #include "raylib.h" // Required for structs: Vector3, Matrix @@ -51,15 +52,22 @@ #ifdef __cplusplus #define RMEXTERN extern "C" // Functions visible from other files (no name mangling of functions in C++) #else - #define RMEXTERN extern // Functions visible from other files + #define RMEXTERN // Functions visible from other files #endif -#if defined(RAYMATH_EXTERN_INLINE) - #define RMDEF RMEXTERN inline // Functions are embeded inline (compiler generated code) +#if defined RAYMATH_IMPLEMENTATION && defined RAYMATH_HEADER_ONLY + #error "Specifying both RAYMATH_IMPLEMENTATION and RAYMATH_HEADER_ONLY is contradictory" +#endif + +#ifdef RAYMATH_IMPLEMENTATION + #define RMDEF extern inline // Provide external definition +#elif defined RAYMATH_HEADER_ONLY + #define RMDEF static inline // Functions may be inlined, no external out-of-line definition #else - #define RMDEF RMEXTERN + #define RMDEF inline // Functions may be inlined or external definition used #endif + //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- @@ -75,6 +83,16 @@ #define RAD2DEG (180.0f/PI) #endif +// Return float vector for Matrix +#ifndef MatrixToFloat + #define MatrixToFloat(mat) (MatrixToFloatV(mat).v) +#endif + +// Return float vector for Vector3 +#ifndef Vector3ToFloat + #define Vector3ToFloat(vec) (Vector3ToFloatV(vec).v) +#endif + //---------------------------------------------------------------------------------- // Types and Structures Definition //---------------------------------------------------------------------------------- @@ -102,6 +120,10 @@ } Matrix; #endif +// NOTE: Helper types to be used instead of array return types for *ToFloat functions +typedef struct float3 { float v[3]; } float3; +typedef struct float16 { float v[16]; } float16; + // Quaternion type typedef struct Quaternion { float x; @@ -110,105 +132,6 @@ typedef struct Quaternion { float w; } Quaternion; -#ifndef RAYMATH_EXTERN_INLINE - -//------------------------------------------------------------------------------------ -// Functions Declaration - math utils -//------------------------------------------------------------------------------------ -RMDEF float Clamp(float value, float min, float max); // Clamp float value - -//------------------------------------------------------------------------------------ -// Functions Declaration to work with Vector2 -//------------------------------------------------------------------------------------ -RMDEF Vector2 Vector2Zero(void); // Vector with components value 0.0f -RMDEF Vector2 Vector2One(void); // Vector with components value 1.0f -RMDEF Vector2 Vector2Add(Vector2 v1, Vector2 v2); // Add two vectors (v1 + v2) -RMDEF Vector2 Vector2Subtract(Vector2 v1, Vector2 v2); // Subtract two vectors (v1 - v2) -RMDEF float Vector2Length(Vector2 v); // Calculate vector length -RMDEF float Vector2DotProduct(Vector2 v1, Vector2 v2); // Calculate two vectors dot product -RMDEF float Vector2Distance(Vector2 v1, Vector2 v2); // Calculate distance between two vectors -RMDEF float Vector2Angle(Vector2 v1, Vector2 v2); // Calculate angle between two vectors in X-axis -RMDEF void Vector2Scale(Vector2 *v, float scale); // Scale vector (multiply by value) -RMDEF void Vector2Negate(Vector2 *v); // Negate vector -RMDEF void Vector2Divide(Vector2 *v, float div); // Divide vector by a float value -RMDEF void Vector2Normalize(Vector2 *v); // Normalize provided vector - -//------------------------------------------------------------------------------------ -// Functions Declaration to work with Vector3 -//------------------------------------------------------------------------------------ -RMDEF Vector3 Vector3Zero(void); // Vector with components value 0.0f -RMDEF Vector3 Vector3One(void); // Vector with components value 1.0f -RMDEF Vector3 Vector3Add(Vector3 v1, Vector3 v2); // Add two vectors -RMDEF Vector3 Vector3Multiply(Vector3 v, float scalar); // Multiply vector by scalar -RMDEF Vector3 Vector3MultiplyV(Vector3 v1, Vector3 v2); // Multiply vector by vector -RMDEF Vector3 Vector3Subtract(Vector3 v1, Vector3 v2); // Substract two vectors -RMDEF Vector3 Vector3CrossProduct(Vector3 v1, Vector3 v2); // Calculate two vectors cross product -RMDEF Vector3 Vector3Perpendicular(Vector3 v); // Calculate one vector perpendicular vector -RMDEF float Vector3Length(const Vector3 v); // Calculate vector length -RMDEF float Vector3DotProduct(Vector3 v1, Vector3 v2); // Calculate two vectors dot product -RMDEF float Vector3Distance(Vector3 v1, Vector3 v2); // Calculate distance between two points -RMDEF void Vector3Scale(Vector3 *v, float scale); // Scale provided vector -RMDEF void Vector3Negate(Vector3 *v); // Negate provided vector (invert direction) -RMDEF void Vector3Normalize(Vector3 *v); // Normalize provided vector -RMDEF void Vector3Transform(Vector3 *v, Matrix mat); // Transforms a Vector3 by a given Matrix -RMDEF Vector3 Vector3Lerp(Vector3 v1, Vector3 v2, float amount); // Calculate linear interpolation between two vectors -RMDEF Vector3 Vector3Reflect(Vector3 vector, Vector3 normal); // Calculate reflected vector to normal -RMDEF Vector3 Vector3Min(Vector3 vec1, Vector3 vec2); // Return min value for each pair of components -RMDEF Vector3 Vector3Max(Vector3 vec1, Vector3 vec2); // Return max value for each pair of components -RMDEF Vector3 Vector3Barycenter(Vector3 p, Vector3 a, Vector3 b, Vector3 c); // Barycenter coords for p in triangle abc -RMDEF float *Vector3ToFloat(Vector3 vec); // Returns Vector3 as float array - -//------------------------------------------------------------------------------------ -// Functions Declaration to work with Matrix -//------------------------------------------------------------------------------------ -RMDEF float MatrixDeterminant(Matrix mat); // Compute matrix determinant -RMDEF float MatrixTrace(Matrix mat); // Returns the trace of the matrix (sum of the values along the diagonal) -RMDEF void MatrixTranspose(Matrix *mat); // Transposes provided matrix -RMDEF void MatrixInvert(Matrix *mat); // Invert provided matrix -RMDEF void MatrixNormalize(Matrix *mat); // Normalize provided matrix -RMDEF Matrix MatrixIdentity(void); // Returns identity matrix -RMDEF Matrix MatrixAdd(Matrix left, Matrix right); // Add two matrices -RMDEF Matrix MatrixSubstract(Matrix left, Matrix right); // Substract two matrices (left - right) -RMDEF Matrix MatrixTranslate(float x, float y, float z); // Returns translation matrix -RMDEF Matrix MatrixRotate(Vector3 axis, float angle); // Returns rotation matrix for an angle around an specified axis (angle in radians) -RMDEF Matrix MatrixRotateX(float angle); // Returns x-rotation matrix (angle in radians) -RMDEF Matrix MatrixRotateY(float angle); // Returns y-rotation matrix (angle in radians) -RMDEF Matrix MatrixRotateZ(float angle); // Returns z-rotation matrix (angle in radians) -RMDEF Matrix MatrixScale(float x, float y, float z); // Returns scaling matrix -RMDEF Matrix MatrixMultiply(Matrix left, Matrix right); // Returns two matrix multiplication -RMDEF Matrix MatrixFrustum(double left, double right, double bottom, double top, double near, double far); // Returns perspective projection matrix -RMDEF Matrix MatrixPerspective(double fovy, double aspect, double near, double far); // Returns perspective projection matrix -RMDEF Matrix MatrixOrtho(double left, double right, double bottom, double top, double near, double far); // Returns orthographic projection matrix -RMDEF Matrix MatrixLookAt(Vector3 position, Vector3 target, Vector3 up); // Returns camera look-at matrix (view matrix) -RMDEF float *MatrixToFloat(Matrix mat); // Returns float array of Matrix data - -//------------------------------------------------------------------------------------ -// Functions Declaration to work with Quaternions -//------------------------------------------------------------------------------------ -RMDEF Quaternion QuaternionIdentity(void); // Returns identity quaternion -RMDEF float QuaternionLength(Quaternion quat); // Compute the length of a quaternion -RMDEF void QuaternionNormalize(Quaternion *q); // Normalize provided quaternion -RMDEF void QuaternionInvert(Quaternion *quat); // Invert provided quaternion -RMDEF Quaternion QuaternionMultiply(Quaternion q1, Quaternion q2); // Calculate two quaternion multiplication -RMDEF Quaternion QuaternionLerp(Quaternion q1, Quaternion q2, float amount); // Calculate linear interpolation between two quaternions -RMDEF Quaternion QuaternionNlerp(Quaternion q1, Quaternion q2, float amount); // Calculate slerp-optimized interpolation between two quaternions -RMDEF Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount); // Calculates spherical linear interpolation between two quaternions -RMDEF Quaternion QuaternionFromVector3ToVector3(Vector3 from, Vector3 to); // Calculate quaternion based on the rotation from one vector to another -RMDEF Quaternion QuaternionFromMatrix(Matrix matrix); // Returns a quaternion for a given rotation matrix -RMDEF Matrix QuaternionToMatrix(Quaternion q); // Returns a matrix for a given quaternion -RMDEF Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle); // Returns rotation quaternion for an angle and axis -RMDEF void QuaternionToAxisAngle(Quaternion q, Vector3 *outAxis, float *outAngle); // Returns the rotation angle and axis for a given quaternion -RMDEF Quaternion QuaternionFromEuler(float roll, float pitch, float yaw); // Returns he quaternion equivalent to Euler angles -RMDEF Vector3 QuaternionToEuler(Quaternion q); // Return the Euler angles equivalent to quaternion (roll, pitch, yaw) -RMDEF void QuaternionTransform(Quaternion *q, Matrix mat); // Transform a quaternion given a transformation matrix - -#endif // notdef RAYMATH_EXTERN_INLINE - -#endif // RAYMATH_H -//////////////////////////////////////////////////////////////////// end of header file - -#if defined(RAYMATH_IMPLEMENTATION) || defined(RAYMATH_EXTERN_INLINE) - #include <math.h> // Required for: sinf(), cosf(), tan(), fabs() //---------------------------------------------------------------------------------- @@ -229,84 +152,86 @@ RMDEF float Clamp(float value, float min, float max) // Vector with components value 0.0f RMDEF Vector2 Vector2Zero(void) { - Vector2 tmp = {0.0f, 0.0f}; - return tmp; + Vector2 result = { 0.0f, 0.0f }; + return result; } // Vector with components value 1.0f RMDEF Vector2 Vector2One(void) { - Vector2 tmp = {1.0f, 1.0f}; - return tmp; + Vector2 result = { 1.0f, 1.0f }; + return result; } // Add two vectors (v1 + v2) RMDEF Vector2 Vector2Add(Vector2 v1, Vector2 v2) { - Vector2 tmp = { v1.x + v2.x, v1.y + v2.y }; - return tmp; + Vector2 result = { v1.x + v2.x, v1.y + v2.y }; + return result; } // Subtract two vectors (v1 - v2) RMDEF Vector2 Vector2Subtract(Vector2 v1, Vector2 v2) { - Vector2 tmp = { v1.x - v2.x, v1.y - v2.y }; - return tmp; + Vector2 result = { v1.x - v2.x, v1.y - v2.y }; + return result; } // Calculate vector length RMDEF float Vector2Length(Vector2 v) { - return sqrtf((v.x*v.x) + (v.y*v.y)); + float result = sqrtf((v.x*v.x) + (v.y*v.y)); + return result; } // Calculate two vectors dot product RMDEF float Vector2DotProduct(Vector2 v1, Vector2 v2) { - return (v1.x*v2.x + v1.y*v2.y); + float result = (v1.x*v2.x + v1.y*v2.y); + return result; } // Calculate distance between two vectors RMDEF float Vector2Distance(Vector2 v1, Vector2 v2) { - return sqrtf((v1.x - v2.x)*(v1.x - v2.x) + (v1.y - v2.y)*(v1.y - v2.y)); + float result = sqrtf((v1.x - v2.x)*(v1.x - v2.x) + (v1.y - v2.y)*(v1.y - v2.y)); + return result; } // Calculate angle from two vectors in X-axis RMDEF float Vector2Angle(Vector2 v1, Vector2 v2) { - float angle = atan2f(v2.y - v1.y, v2.x - v1.x)*(180.0f/PI); - - if (angle < 0) angle += 360.0f; - - return angle; + float result = atan2f(v2.y - v1.y, v2.x - v1.x)*(180.0f/PI); + if (result < 0) result += 360.0f; + return result; } // Scale vector (multiply by value) -RMDEF void Vector2Scale(Vector2 *v, float scale) +RMDEF Vector2 Vector2Scale(Vector2 v, float scale) { - v->x *= scale; - v->y *= scale; + Vector2 result = { v.x*scale, v.y*scale }; + return result; } // Negate vector -RMDEF void Vector2Negate(Vector2 *v) +RMDEF Vector2 Vector2Negate(Vector2 v) { - v->x = -v->x; - v->y = -v->y; + Vector2 result = { -v.x, -v.y }; + return result; } // Divide vector by a float value -RMDEF void Vector2Divide(Vector2 *v, float div) +RMDEF Vector2 Vector2Divide(Vector2 v, float div) { - Vector2 tmp = {v->x/div, v->y/div}; - *v = tmp; + Vector2 result = { v.x/div, v.y/div }; + return result; } // Normalize provided vector -RMDEF void Vector2Normalize(Vector2 *v) +RMDEF Vector2 Vector2Normalize(Vector2 v) { - Vector2Divide(v, Vector2Length(*v)); + Vector2 result = Vector2Divide(v, Vector2Length(v)); + return result; } //---------------------------------------------------------------------------------- @@ -316,69 +241,56 @@ RMDEF void Vector2Normalize(Vector2 *v) // Vector with components value 0.0f RMDEF Vector3 Vector3Zero(void) { - Vector3 tmp = { 0.0f, 0.0f, 0.0f }; - return tmp; + Vector3 result = { 0.0f, 0.0f, 0.0f }; + return result; } // Vector with components value 1.0f RMDEF Vector3 Vector3One(void) { - Vector3 tmp = { 1.0f, 1.0f, 1.0f }; - return tmp; + Vector3 result = { 1.0f, 1.0f, 1.0f }; + return result; } // Add two vectors RMDEF Vector3 Vector3Add(Vector3 v1, Vector3 v2) { - Vector3 tmp = { v1.x + v2.x, v1.y + v2.y, v1.z + v2.z }; - return tmp; + Vector3 result = { v1.x + v2.x, v1.y + v2.y, v1.z + v2.z }; + return result; } // Substract two vectors RMDEF Vector3 Vector3Subtract(Vector3 v1, Vector3 v2) { - Vector3 tmp = { v1.x - v2.x, v1.y - v2.y, v1.z - v2.z }; - return tmp; + Vector3 result = { v1.x - v2.x, v1.y - v2.y, v1.z - v2.z }; + return result; } // Multiply vector by scalar RMDEF Vector3 Vector3Multiply(Vector3 v, float scalar) -{ - v.x *= scalar; - v.y *= scalar; - v.z *= scalar; - - return v; +{ + Vector3 result = { v.x*scalar, v.y*scalar, v.z*scalar }; + return result; } // Multiply vector by vector RMDEF Vector3 Vector3MultiplyV(Vector3 v1, Vector3 v2) { - Vector3 result; - - result.x = v1.x * v2.x; - result.y = v1.y * v2.y; - result.z = v1.z * v2.z; - + Vector3 result = { v1.x*v2.x, v1.y*v2.y, v1.z*v2.z }; return result; } // Calculate two vectors cross product RMDEF Vector3 Vector3CrossProduct(Vector3 v1, Vector3 v2) { - Vector3 result; - - result.x = v1.y*v2.z - v1.z*v2.y; - result.y = v1.z*v2.x - v1.x*v2.z; - result.z = v1.x*v2.y - v1.y*v2.x; - + Vector3 result = { v1.y*v2.z - v1.z*v2.y, v1.z*v2.x - v1.x*v2.z, v1.x*v2.y - v1.y*v2.x }; return result; } // Calculate one vector perpendicular vector RMDEF Vector3 Vector3Perpendicular(Vector3 v) { - Vector3 result; + Vector3 result = { 0 }; float min = fabsf(v.x); Vector3 cardinalAxis = {1.0f, 0.0f, 0.0f}; @@ -404,13 +316,15 @@ RMDEF Vector3 Vector3Perpendicular(Vector3 v) // Calculate vector length RMDEF float Vector3Length(const Vector3 v) { - return sqrtf(v.x*v.x + v.y*v.y + v.z*v.z); + float result = sqrtf(v.x*v.x + v.y*v.y + v.z*v.z); + return result; } // Calculate two vectors dot product RMDEF float Vector3DotProduct(Vector3 v1, Vector3 v2) { - return (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z); + float result = (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z); + return result; } // Calculate distance between two vectors @@ -419,58 +333,60 @@ RMDEF float Vector3Distance(Vector3 v1, Vector3 v2) float dx = v2.x - v1.x; float dy = v2.y - v1.y; float dz = v2.z - v1.z; - - return sqrtf(dx*dx + dy*dy + dz*dz); + float result = sqrtf(dx*dx + dy*dy + dz*dz); + return result; } // Scale provided vector -RMDEF void Vector3Scale(Vector3 *v, float scale) +RMDEF Vector3 Vector3Scale(Vector3 v, float scale) { - v->x *= scale; - v->y *= scale; - v->z *= scale; + Vector3 result = { v.x*scale, v.y*scale, v.z*scale }; + return result; } // Negate provided vector (invert direction) -RMDEF void Vector3Negate(Vector3 *v) +RMDEF Vector3 Vector3Negate(Vector3 v) { - v->x = -v->x; - v->y = -v->y; - v->z = -v->z; + Vector3 result = { -v.x, -v.y, -v.z }; + return result; } // Normalize provided vector -RMDEF void Vector3Normalize(Vector3 *v) +RMDEF Vector3 Vector3Normalize(Vector3 v) { + Vector3 result = v; + float length, ilength; - - length = Vector3Length(*v); - + length = Vector3Length(v); if (length == 0.0f) length = 1.0f; - ilength = 1.0f/length; - v->x *= ilength; - v->y *= ilength; - v->z *= ilength; + result.x *= ilength; + result.y *= ilength; + result.z *= ilength; + + return result; } // Transforms a Vector3 by a given Matrix -RMDEF void Vector3Transform(Vector3 *v, Matrix mat) +RMDEF Vector3 Vector3Transform(Vector3 v, Matrix mat) { - float x = v->x; - float y = v->y; - float z = v->z; + Vector3 result = { 0 }; + float x = v.x; + float y = v.y; + float z = v.z; - v->x = mat.m0*x + mat.m4*y + mat.m8*z + mat.m12; - v->y = mat.m1*x + mat.m5*y + mat.m9*z + mat.m13; - v->z = mat.m2*x + mat.m6*y + mat.m10*z + mat.m14; + result.x = mat.m0*x + mat.m4*y + mat.m8*z + mat.m12; + result.y = mat.m1*x + mat.m5*y + mat.m9*z + mat.m13; + result.z = mat.m2*x + mat.m6*y + mat.m10*z + mat.m14; + + return result; }; // Calculate linear interpolation between two vectors RMDEF Vector3 Vector3Lerp(Vector3 v1, Vector3 v2, float amount) { - Vector3 result; + Vector3 result = { 0 }; result.x = v1.x + amount*(v2.x - v1.x); result.y = v1.y + amount*(v2.y - v1.y); @@ -480,43 +396,43 @@ RMDEF Vector3 Vector3Lerp(Vector3 v1, Vector3 v2, float amount) } // Calculate reflected vector to normal -RMDEF Vector3 Vector3Reflect(Vector3 vector, Vector3 normal) +RMDEF Vector3 Vector3Reflect(Vector3 v, Vector3 normal) { // I is the original vector // N is the normal of the incident plane // R = I - (2*N*( DotProduct[ I,N] )) - Vector3 result; + Vector3 result = { 0 }; - float dotProduct = Vector3DotProduct(vector, normal); + float dotProduct = Vector3DotProduct(v, normal); - result.x = vector.x - (2.0f*normal.x)*dotProduct; - result.y = vector.y - (2.0f*normal.y)*dotProduct; - result.z = vector.z - (2.0f*normal.z)*dotProduct; + result.x = v.x - (2.0f*normal.x)*dotProduct; + result.y = v.y - (2.0f*normal.y)*dotProduct; + result.z = v.z - (2.0f*normal.z)*dotProduct; return result; } // Return min value for each pair of components -RMDEF Vector3 Vector3Min(Vector3 vec1, Vector3 vec2) +RMDEF Vector3 Vector3Min(Vector3 v1, Vector3 v2) { - Vector3 result; + Vector3 result = { 0 }; - result.x = fminf(vec1.x, vec2.x); - result.y = fminf(vec1.y, vec2.y); - result.z = fminf(vec1.z, vec2.z); + result.x = fminf(v1.x, v2.x); + result.y = fminf(v1.y, v2.y); + result.z = fminf(v1.z, v2.z); return result; } // Return max value for each pair of components -RMDEF Vector3 Vector3Max(Vector3 vec1, Vector3 vec2) +RMDEF Vector3 Vector3Max(Vector3 v1, Vector3 v2) { - Vector3 result; + Vector3 result = { 0 }; - result.x = fmaxf(vec1.x, vec2.x); - result.y = fmaxf(vec1.y, vec2.y); - result.z = fmaxf(vec1.z, vec2.z); + result.x = fmaxf(v1.x, v2.x); + result.y = fmaxf(v1.y, v2.y); + result.z = fmaxf(v1.z, v2.z); return result; } @@ -538,7 +454,7 @@ RMDEF Vector3 Vector3Barycenter(Vector3 p, Vector3 a, Vector3 b, Vector3 c) float denom = d00*d11 - d01*d01; - Vector3 result; + Vector3 result = { 0 }; result.y = (d11*d20 - d01*d21)/denom; result.z = (d00*d21 - d01*d20)/denom; @@ -548,13 +464,13 @@ RMDEF Vector3 Vector3Barycenter(Vector3 p, Vector3 a, Vector3 b, Vector3 c) } // Returns Vector3 as float array -RMDEF float *Vector3ToFloat(Vector3 vec) +RMDEF float3 Vector3ToFloatV(Vector3 v) { - static float buffer[3]; + float3 buffer = { 0 }; - buffer[0] = vec.x; - buffer[1] = vec.y; - buffer[2] = vec.z; + buffer.v[0] = v.x; + buffer.v[1] = v.y; + buffer.v[2] = v.z; return buffer; } @@ -566,7 +482,7 @@ RMDEF float *Vector3ToFloat(Vector3 vec) // Compute matrix determinant RMDEF float MatrixDeterminant(Matrix mat) { - float result; + float result = { 0 }; // Cache the matrix values (speed optimization) float a00 = mat.m0, a01 = mat.m1, a02 = mat.m2, a03 = mat.m3; @@ -587,44 +503,45 @@ RMDEF float MatrixDeterminant(Matrix mat) // Returns the trace of the matrix (sum of the values along the diagonal) RMDEF float MatrixTrace(Matrix mat) { - return (mat.m0 + mat.m5 + mat.m10 + mat.m15); + float result = (mat.m0 + mat.m5 + mat.m10 + mat.m15); + return result; } // Transposes provided matrix -RMDEF void MatrixTranspose(Matrix *mat) -{ - Matrix temp; - - temp.m0 = mat->m0; - temp.m1 = mat->m4; - temp.m2 = mat->m8; - temp.m3 = mat->m12; - temp.m4 = mat->m1; - temp.m5 = mat->m5; - temp.m6 = mat->m9; - temp.m7 = mat->m13; - temp.m8 = mat->m2; - temp.m9 = mat->m6; - temp.m10 = mat->m10; - temp.m11 = mat->m14; - temp.m12 = mat->m3; - temp.m13 = mat->m7; - temp.m14 = mat->m11; - temp.m15 = mat->m15; - - *mat = temp; +RMDEF Matrix MatrixTranspose(Matrix mat) +{ + Matrix result = { 0 }; + + result.m0 = mat.m0; + result.m1 = mat.m4; + result.m2 = mat.m8; + result.m3 = mat.m12; + result.m4 = mat.m1; + result.m5 = mat.m5; + result.m6 = mat.m9; + result.m7 = mat.m13; + result.m8 = mat.m2; + result.m9 = mat.m6; + result.m10 = mat.m10; + result.m11 = mat.m14; + result.m12 = mat.m3; + result.m13 = mat.m7; + result.m14 = mat.m11; + result.m15 = mat.m15; + + return result; } // Invert provided matrix -RMDEF void MatrixInvert(Matrix *mat) +RMDEF Matrix MatrixInvert(Matrix mat) { - Matrix temp; + Matrix result = { 0 }; // Cache the matrix values (speed optimization) - float a00 = mat->m0, a01 = mat->m1, a02 = mat->m2, a03 = mat->m3; - float a10 = mat->m4, a11 = mat->m5, a12 = mat->m6, a13 = mat->m7; - float a20 = mat->m8, a21 = mat->m9, a22 = mat->m10, a23 = mat->m11; - float a30 = mat->m12, a31 = mat->m13, a32 = mat->m14, a33 = mat->m15; + float a00 = mat.m0, a01 = mat.m1, a02 = mat.m2, a03 = mat.m3; + float a10 = mat.m4, a11 = mat.m5, a12 = mat.m6, a13 = mat.m7; + float a20 = mat.m8, a21 = mat.m9, a22 = mat.m10, a23 = mat.m11; + float a30 = mat.m12, a31 = mat.m13, a32 = mat.m14, a33 = mat.m15; float b00 = a00*a11 - a01*a10; float b01 = a00*a12 - a02*a10; @@ -642,47 +559,51 @@ RMDEF void MatrixInvert(Matrix *mat) // Calculate the invert determinant (inlined to avoid double-caching) float invDet = 1.0f/(b00*b11 - b01*b10 + b02*b09 + b03*b08 - b04*b07 + b05*b06); - temp.m0 = (a11*b11 - a12*b10 + a13*b09)*invDet; - temp.m1 = (-a01*b11 + a02*b10 - a03*b09)*invDet; - temp.m2 = (a31*b05 - a32*b04 + a33*b03)*invDet; - temp.m3 = (-a21*b05 + a22*b04 - a23*b03)*invDet; - temp.m4 = (-a10*b11 + a12*b08 - a13*b07)*invDet; - temp.m5 = (a00*b11 - a02*b08 + a03*b07)*invDet; - temp.m6 = (-a30*b05 + a32*b02 - a33*b01)*invDet; - temp.m7 = (a20*b05 - a22*b02 + a23*b01)*invDet; - temp.m8 = (a10*b10 - a11*b08 + a13*b06)*invDet; - temp.m9 = (-a00*b10 + a01*b08 - a03*b06)*invDet; - temp.m10 = (a30*b04 - a31*b02 + a33*b00)*invDet; - temp.m11 = (-a20*b04 + a21*b02 - a23*b00)*invDet; - temp.m12 = (-a10*b09 + a11*b07 - a12*b06)*invDet; - temp.m13 = (a00*b09 - a01*b07 + a02*b06)*invDet; - temp.m14 = (-a30*b03 + a31*b01 - a32*b00)*invDet; - temp.m15 = (a20*b03 - a21*b01 + a22*b00)*invDet; - - *mat = temp; + result.m0 = (a11*b11 - a12*b10 + a13*b09)*invDet; + result.m1 = (-a01*b11 + a02*b10 - a03*b09)*invDet; + result.m2 = (a31*b05 - a32*b04 + a33*b03)*invDet; + result.m3 = (-a21*b05 + a22*b04 - a23*b03)*invDet; + result.m4 = (-a10*b11 + a12*b08 - a13*b07)*invDet; + result.m5 = (a00*b11 - a02*b08 + a03*b07)*invDet; + result.m6 = (-a30*b05 + a32*b02 - a33*b01)*invDet; + result.m7 = (a20*b05 - a22*b02 + a23*b01)*invDet; + result.m8 = (a10*b10 - a11*b08 + a13*b06)*invDet; + result.m9 = (-a00*b10 + a01*b08 - a03*b06)*invDet; + result.m10 = (a30*b04 - a31*b02 + a33*b00)*invDet; + result.m11 = (-a20*b04 + a21*b02 - a23*b00)*invDet; + result.m12 = (-a10*b09 + a11*b07 - a12*b06)*invDet; + result.m13 = (a00*b09 - a01*b07 + a02*b06)*invDet; + result.m14 = (-a30*b03 + a31*b01 - a32*b00)*invDet; + result.m15 = (a20*b03 - a21*b01 + a22*b00)*invDet; + + return result; } // Normalize provided matrix -RMDEF void MatrixNormalize(Matrix *mat) -{ - float det = MatrixDeterminant(*mat); - - mat->m0 /= det; - mat->m1 /= det; - mat->m2 /= det; - mat->m3 /= det; - mat->m4 /= det; - mat->m5 /= det; - mat->m6 /= det; - mat->m7 /= det; - mat->m8 /= det; - mat->m9 /= det; - mat->m10 /= det; - mat->m11 /= det; - mat->m12 /= det; - mat->m13 /= det; - mat->m14 /= det; - mat->m15 /= det; +RMDEF Matrix MatrixNormalize(Matrix mat) +{ + Matrix result = { 0 }; + + float det = MatrixDeterminant(mat); + + result.m0 = mat.m0/det; + result.m1 = mat.m1/det; + result.m2 = mat.m2/det; + result.m3 = mat.m3/det; + result.m4 = mat.m4/det; + result.m5 = mat.m5/det; + result.m6 = mat.m6/det; + result.m7 = mat.m7/det; + result.m8 = mat.m8/det; + result.m9 = mat.m9/det; + result.m10 = mat.m10/det; + result.m11 = mat.m11/det; + result.m12 = mat.m12/det; + result.m13 = mat.m13/det; + result.m14 = mat.m14/det; + result.m15 = mat.m15/det; + + return result; } // Returns identity matrix @@ -761,7 +682,7 @@ RMDEF Matrix MatrixTranslate(float x, float y, float z) // NOTE: Angle should be provided in radians RMDEF Matrix MatrixRotate(Vector3 axis, float angle) { - Matrix result; + Matrix result = { 0 }; float x = axis.x, y = axis.y, z = axis.z; @@ -865,7 +786,7 @@ RMDEF Matrix MatrixScale(float x, float y, float z) // NOTE: When multiplying matrices... the order matters! RMDEF Matrix MatrixMultiply(Matrix left, Matrix right) { - Matrix result; + Matrix result = { 0 }; result.m0 = left.m0*right.m0 + left.m1*right.m4 + left.m2*right.m8 + left.m3*right.m12; result.m1 = left.m0*right.m1 + left.m1*right.m5 + left.m2*right.m9 + left.m3*right.m13; @@ -890,7 +811,7 @@ RMDEF Matrix MatrixMultiply(Matrix left, Matrix right) // Returns perspective projection matrix RMDEF Matrix MatrixFrustum(double left, double right, double bottom, double top, double near, double far) { - Matrix result; + Matrix result = { 0 }; float rl = (right - left); float tb = (top - bottom); @@ -925,14 +846,15 @@ RMDEF Matrix MatrixPerspective(double fovy, double aspect, double near, double f { double top = near*tan(fovy*0.5); double right = top*aspect; + Matrix result = MatrixFrustum(-right, right, -top, top, near, far); - return MatrixFrustum(-right, right, -top, top, near, far); + return result; } // Returns orthographic projection matrix RMDEF Matrix MatrixOrtho(double left, double right, double bottom, double top, double near, double far) { - Matrix result; + Matrix result = { 0 }; float rl = (right - left); float tb = (top - bottom); @@ -961,14 +883,14 @@ RMDEF Matrix MatrixOrtho(double left, double right, double bottom, double top, d // Returns camera look-at matrix (view matrix) RMDEF Matrix MatrixLookAt(Vector3 eye, Vector3 target, Vector3 up) { - Matrix result; + Matrix result = { 0 }; Vector3 z = Vector3Subtract(eye, target); - Vector3Normalize(&z); + z = Vector3Normalize(z); Vector3 x = Vector3CrossProduct(up, z); - Vector3Normalize(&x); + x = Vector3Normalize(x); Vector3 y = Vector3CrossProduct(z, x); - Vector3Normalize(&y); + y = Vector3Normalize(y); result.m0 = x.x; result.m1 = x.y; @@ -987,32 +909,32 @@ RMDEF Matrix MatrixLookAt(Vector3 eye, Vector3 target, Vector3 up) result.m14 = eye.z; result.m15 = 1.0f; - MatrixInvert(&result); + result = MatrixInvert(result); return result; } // Returns float array of matrix data -RMDEF float *MatrixToFloat(Matrix mat) -{ - static float buffer[16]; - - buffer[0] = mat.m0; - buffer[1] = mat.m1; - buffer[2] = mat.m2; - buffer[3] = mat.m3; - buffer[4] = mat.m4; - buffer[5] = mat.m5; - buffer[6] = mat.m6; - buffer[7] = mat.m7; - buffer[8] = mat.m8; - buffer[9] = mat.m9; - buffer[10] = mat.m10; - buffer[11] = mat.m11; - buffer[12] = mat.m12; - buffer[13] = mat.m13; - buffer[14] = mat.m14; - buffer[15] = mat.m15; +RMDEF float16 MatrixToFloatV(Matrix mat) +{ + float16 buffer = { 0 }; + + buffer.v[0] = mat.m0; + buffer.v[1] = mat.m1; + buffer.v[2] = mat.m2; + buffer.v[3] = mat.m3; + buffer.v[4] = mat.m4; + buffer.v[5] = mat.m5; + buffer.v[6] = mat.m6; + buffer.v[7] = mat.m7; + buffer.v[8] = mat.m8; + buffer.v[9] = mat.m9; + buffer.v[10] = mat.m10; + buffer.v[11] = mat.m11; + buffer.v[12] = mat.m12; + buffer.v[13] = mat.m13; + buffer.v[14] = mat.m14; + buffer.v[15] = mat.m15; return buffer; } @@ -1024,54 +946,59 @@ RMDEF float *MatrixToFloat(Matrix mat) // Returns identity quaternion RMDEF Quaternion QuaternionIdentity(void) { - Quaternion q = { 0.0f, 0.0f, 0.0f, 1.0f }; - return q; + Quaternion result = { 0.0f, 0.0f, 0.0f, 1.0f }; + return result; } // Computes the length of a quaternion -RMDEF float QuaternionLength(Quaternion quat) +RMDEF float QuaternionLength(Quaternion q) { - return sqrt(quat.x*quat.x + quat.y*quat.y + quat.z*quat.z + quat.w*quat.w); + float result = sqrt(q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w); + return result; } // Normalize provided quaternion -RMDEF void QuaternionNormalize(Quaternion *q) +RMDEF Quaternion QuaternionNormalize(Quaternion q) { + Quaternion result = { 0 }; + float length, ilength; - - length = QuaternionLength(*q); - + length = QuaternionLength(q); if (length == 0.0f) length = 1.0f; - ilength = 1.0f/length; - q->x *= ilength; - q->y *= ilength; - q->z *= ilength; - q->w *= ilength; + result.x = q.x*ilength; + result.y = q.y*ilength; + result.z = q.z*ilength; + result.w = q.w*ilength; + + return result; } // Invert provided quaternion -RMDEF void QuaternionInvert(Quaternion *quat) +RMDEF Quaternion QuaternionInvert(Quaternion q) { - float length = QuaternionLength(*quat); + Quaternion result = q; + float length = QuaternionLength(q); float lengthSq = length*length; if (lengthSq != 0.0) { float i = 1.0f/lengthSq; - quat->x *= -i; - quat->y *= -i; - quat->z *= -i; - quat->w *= i; + result.x *= -i; + result.y *= -i; + result.z *= -i; + result.w *= i; } + + return result; } // Calculate two quaternion multiplication RMDEF Quaternion QuaternionMultiply(Quaternion q1, Quaternion q2) { - Quaternion result; + Quaternion result = { 0 }; float qax = q1.x, qay = q1.y, qaz = q1.z, qaw = q1.w; float qbx = q2.x, qby = q2.y, qbz = q2.z, qbw = q2.w; @@ -1087,7 +1014,7 @@ RMDEF Quaternion QuaternionMultiply(Quaternion q1, Quaternion q2) // Calculate linear interpolation between two quaternions RMDEF Quaternion QuaternionLerp(Quaternion q1, Quaternion q2, float amount) { - Quaternion result; + Quaternion result = { 0 }; result.x = q1.x + amount*(q2.x - q1.x); result.y = q1.y + amount*(q2.y - q1.y); @@ -1101,7 +1028,7 @@ RMDEF Quaternion QuaternionLerp(Quaternion q1, Quaternion q2, float amount) RMDEF Quaternion QuaternionNlerp(Quaternion q1, Quaternion q2, float amount) { Quaternion result = QuaternionLerp(q1, q2, amount); - QuaternionNormalize(&result); + result = QuaternionNormalize(result); return result; } @@ -1109,7 +1036,7 @@ RMDEF Quaternion QuaternionNlerp(Quaternion q1, Quaternion q2, float amount) // Calculates spherical linear interpolation between two quaternions RMDEF Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount) { - Quaternion result; + Quaternion result = { 0 }; float cosHalfTheta = q1.x*q2.x + q1.y*q2.y + q1.z*q2.z + q1.w*q2.w; @@ -1145,31 +1072,31 @@ RMDEF Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount) // Calculate quaternion based on the rotation from one vector to another RMDEF Quaternion QuaternionFromVector3ToVector3(Vector3 from, Vector3 to) { - Quaternion q = { 0 }; + Quaternion result = { 0 }; float cos2Theta = Vector3DotProduct(from, to); Vector3 cross = Vector3CrossProduct(from, to); - q.x = cross.x; - q.y = cross.y; - q.z = cross.y; - q.w = 1.0f + cos2Theta; // NOTE: Added QuaternioIdentity() + result.x = cross.x; + result.y = cross.y; + result.z = cross.y; + result.w = 1.0f + cos2Theta; // NOTE: Added QuaternioIdentity() // Normalize to essentially nlerp the original and identity to 0.5 - QuaternionNormalize(&q); + result = QuaternionNormalize(result); // Above lines are equivalent to: //Quaternion result = QuaternionNlerp(q, QuaternionIdentity(), 0.5f); - return q; + return result; } // Returns a quaternion for a given rotation matrix -RMDEF Quaternion QuaternionFromMatrix(Matrix matrix) +RMDEF Quaternion QuaternionFromMatrix(Matrix mat) { - Quaternion result; + Quaternion result = { 0 }; - float trace = MatrixTrace(matrix); + float trace = MatrixTrace(mat); if (trace > 0.0f) { @@ -1177,42 +1104,42 @@ RMDEF Quaternion QuaternionFromMatrix(Matrix matrix) float invS = 1.0f/s; result.w = s*0.25f; - result.x = (matrix.m6 - matrix.m9)*invS; - result.y = (matrix.m8 - matrix.m2)*invS; - result.z = (matrix.m1 - matrix.m4)*invS; + result.x = (mat.m6 - mat.m9)*invS; + result.y = (mat.m8 - mat.m2)*invS; + result.z = (mat.m1 - mat.m4)*invS; } else { - float m00 = matrix.m0, m11 = matrix.m5, m22 = matrix.m10; + float m00 = mat.m0, m11 = mat.m5, m22 = mat.m10; if (m00 > m11 && m00 > m22) { float s = (float)sqrt(1.0f + m00 - m11 - m22)*2.0f; float invS = 1.0f/s; - result.w = (matrix.m6 - matrix.m9)*invS; + result.w = (mat.m6 - mat.m9)*invS; result.x = s*0.25f; - result.y = (matrix.m4 + matrix.m1)*invS; - result.z = (matrix.m8 + matrix.m2)*invS; + result.y = (mat.m4 + mat.m1)*invS; + result.z = (mat.m8 + mat.m2)*invS; } else if (m11 > m22) { float s = (float)sqrt(1.0f + m11 - m00 - m22)*2.0f; float invS = 1.0f/s; - result.w = (matrix.m8 - matrix.m2)*invS; - result.x = (matrix.m4 + matrix.m1)*invS; + result.w = (mat.m8 - mat.m2)*invS; + result.x = (mat.m4 + mat.m1)*invS; result.y = s*0.25f; - result.z = (matrix.m9 + matrix.m6)*invS; + result.z = (mat.m9 + mat.m6)*invS; } else { float s = (float)sqrt(1.0f + m22 - m00 - m11)*2.0f; float invS = 1.0f/s; - result.w = (matrix.m1 - matrix.m4)*invS; - result.x = (matrix.m8 + matrix.m2)*invS; - result.y = (matrix.m9 + matrix.m6)*invS; + result.w = (mat.m1 - mat.m4)*invS; + result.x = (mat.m8 + mat.m2)*invS; + result.y = (mat.m9 + mat.m6)*invS; result.z = s*0.25f; } } @@ -1223,7 +1150,7 @@ RMDEF Quaternion QuaternionFromMatrix(Matrix matrix) // Returns a matrix for a given quaternion RMDEF Matrix QuaternionToMatrix(Quaternion q) { - Matrix result; + Matrix result = { 0 }; float x = q.x, y = q.y, z = q.z, w = q.w; @@ -1276,7 +1203,7 @@ RMDEF Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle) angle *= 0.5f; - Vector3Normalize(&axis); + axis = Vector3Normalize(axis); float sinres = sinf(angle); float cosres = cosf(angle); @@ -1286,7 +1213,7 @@ RMDEF Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle) result.z = axis.z*sinres; result.w = cosres; - QuaternionNormalize(&result); + result = QuaternionNormalize(result); return result; } @@ -1294,7 +1221,7 @@ RMDEF Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle) // Returns the rotation angle and axis for a given quaternion RMDEF void QuaternionToAxisAngle(Quaternion q, Vector3 *outAxis, float *outAngle) { - if (fabs(q.w) > 1.0f) QuaternionNormalize(&q); + if (fabs(q.w) > 1.0f) q = QuaternionNormalize(q); Vector3 resAxis = { 0.0f, 0.0f, 0.0f }; float resAngle = 0.0f; @@ -1343,39 +1270,38 @@ RMDEF Quaternion QuaternionFromEuler(float roll, float pitch, float yaw) // NOTE: Angles are returned in a Vector3 struct in degrees RMDEF Vector3 QuaternionToEuler(Quaternion q) { - Vector3 v = { 0 }; + Vector3 result = { 0 }; // roll (x-axis rotation) float x0 = 2.0f*(q.w*q.x + q.y*q.z); float x1 = 1.0f - 2.0f*(q.x*q.x + q.y*q.y); - v.x = atan2f(x0, x1)*RAD2DEG; + result.x = atan2f(x0, x1)*RAD2DEG; // pitch (y-axis rotation) float y0 = 2.0f*(q.w*q.y - q.z*q.x); y0 = y0 > 1.0f ? 1.0f : y0; y0 = y0 < -1.0f ? -1.0f : y0; - v.y = asinf(y0)*RAD2DEG; + result.y = asinf(y0)*RAD2DEG; // yaw (z-axis rotation) float z0 = 2.0f*(q.w*q.z + q.x*q.y); float z1 = 1.0f - 2.0f*(q.y*q.y + q.z*q.z); - v.z = atan2f(z0, z1)*RAD2DEG; + result.z = atan2f(z0, z1)*RAD2DEG; - return v; + return result; } // Transform a quaternion given a transformation matrix -RMDEF void QuaternionTransform(Quaternion *q, Matrix mat) +RMDEF Quaternion QuaternionTransform(Quaternion q, Matrix mat) { - float x = q->x; - float y = q->y; - float z = q->z; - float w = q->w; + Quaternion result = { 0 }; - q->x = mat.m0*x + mat.m4*y + mat.m8*z + mat.m12*w; - q->y = mat.m1*x + mat.m5*y + mat.m9*z + mat.m13*w; - q->z = mat.m2*x + mat.m6*y + mat.m10*z + mat.m14*w; - q->w = mat.m3*x + mat.m7*y + mat.m11*z + mat.m15*w; + result.x = mat.m0*q.x + mat.m4*q.y + mat.m8*q.z + mat.m12*q.w; + result.y = mat.m1*q.x + mat.m5*q.y + mat.m9*q.z + mat.m13*q.w; + result.z = mat.m2*q.x + mat.m6*q.y + mat.m10*q.z + mat.m14*q.w; + result.w = mat.m3*q.x + mat.m7*q.y + mat.m11*q.z + mat.m15*q.w; + + return result; } -#endif // RAYMATH_IMPLEMENTATION +#endif // RAYMATH_H @@ -470,8 +470,7 @@ void rlRotatef(float angleDeg, float x, float y, float z) Matrix matRotation = MatrixIdentity(); Vector3 axis = (Vector3){ x, y, z }; - Vector3Normalize(&axis); - matRotation = MatrixRotate(axis, angleDeg*DEG2RAD); + matRotation = MatrixRotate(Vector3Normalize(axis), angleDeg*DEG2RAD); // NOTE: We transpose matrix with multiplication order *currentMatrix = MatrixMultiply(matRotation, *currentMatrix); @@ -570,7 +569,7 @@ void rlEnd(void) // This way, rlTranslatef(), rlRotatef()... behaviour is the same than OpenGL 1.1 // Apply transformation matrix to all temp vertices - for (int i = 0; i < tempBufferCount; i++) Vector3Transform(&tempBuffer[i], *currentMatrix); + for (int i = 0; i < tempBufferCount; i++) tempBuffer[i] = Vector3Transform(tempBuffer[i], *currentMatrix); // Deactivate tempBuffer usage to allow rlVertex3f do its job useTempBuffer = false; @@ -1356,13 +1355,13 @@ Vector3 rlUnproject(Vector3 source, Matrix proj, Matrix view) // Calculate unproject matrix (multiply view patrix by projection matrix) and invert it Matrix matViewProj = MatrixMultiply(view, proj); - MatrixInvert(&matViewProj); + matViewProj = MatrixInvert(matViewProj); // Create quaternion from source point Quaternion quat = { source.x, source.y, source.z, 1.0f }; // Multiply quat point by unproject matrix - QuaternionTransform(&quat, matViewProj); + quat = QuaternionTransform(quat, matViewProj); // Normalized world points in vectors result.x = quat.x/quat.w; @@ -321,7 +321,7 @@ typedef unsigned char byte; LOC_MAP_METALNESS, // LOC_MAP_SPECULAR LOC_MAP_NORMAL, LOC_MAP_ROUGHNESS, - LOC_MAP_OCCUSION, + LOC_MAP_OCCLUSION, LOC_MAP_EMISSION, LOC_MAP_HEIGHT, LOC_MAP_CUBEMAP, diff --git a/templates/advance_game/advance_game.c b/templates/advance_game/advance_game.c index 5499b2d8..768b2f94 100644 --- a/templates/advance_game/advance_game.c +++ b/templates/advance_game/advance_game.c @@ -15,10 +15,6 @@ #include "raylib.h" #include "screens/screens.h" // NOTE: Defines global variable: currentScreen -#if defined(PLATFORM_ANDROID) - #include "android_native_app_glue.h" -#endif - #if defined(PLATFORM_WEB) #include <emscripten/emscripten.h> #endif @@ -53,19 +49,11 @@ static void UpdateDrawFrame(void); // Update and Draw one frame //---------------------------------------------------------------------------------- // Main entry point //---------------------------------------------------------------------------------- -#if defined(PLATFORM_ANDROID) -void android_main(struct android_app *app) -#else int main(void) -#endif { - // Initialization + // Initialization (Note windowTitle is unused on Android) //--------------------------------------------------------- -#if defined(PLATFORM_ANDROID) - InitWindow(screenWidth, screenHeight, app); -#else InitWindow(screenWidth, screenHeight, "raylib template - advance game"); -#endif // Global data loading (assets that must be available in all screens, i.e. fonts) InitAudioDevice(); @@ -116,9 +104,8 @@ int main(void) CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- -#if !defined(PLATFORM_ANDROID) + return 0; -#endif } //---------------------------------------------------------------------------------- @@ -299,4 +286,4 @@ static void UpdateDrawFrame(void) EndDrawing(); //---------------------------------------------------------------------------------- -}
\ No newline at end of file +} diff --git a/templates/simple_game/simple_game.c b/templates/simple_game/simple_game.c index 50859221..028b1da8 100644 --- a/templates/simple_game/simple_game.c +++ b/templates/simple_game/simple_game.c @@ -14,10 +14,6 @@ #include "raylib.h" -#if defined(PLATFORM_ANDROID) - #include "android_native_app_glue.h" -#endif - //---------------------------------------------------------------------------------- // Types and Structures Definition //---------------------------------------------------------------------------------- @@ -26,22 +22,14 @@ typedef enum GameScreen { LOGO = 0, TITLE, GAMEPLAY, ENDING } GameScreen; //---------------------------------------------------------------------------------- // Main entry point //---------------------------------------------------------------------------------- -#if defined(PLATFORM_ANDROID) -void android_main(struct android_app *app) -#else int main(void) -#endif { - // Initialization + // Initialization (Note windowTitle is unused on Android) //-------------------------------------------------------------------------------------- const int screenWidth = 800; const int screenHeight = 450; -#if defined(PLATFORM_ANDROID) - InitWindow(screenWidth, screenHeight, app); -#else InitWindow(screenWidth, screenHeight, "raylib template - simple game"); -#endif GameScreen currentScreen = LOGO; @@ -158,7 +146,6 @@ int main(void) CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- -#if !defined(PLATFORM_ANDROID) + return 0; -#endif } diff --git a/templates/standard_game/standard_game.c b/templates/standard_game/standard_game.c index cf059451..8871484e 100644 --- a/templates/standard_game/standard_game.c +++ b/templates/standard_game/standard_game.c @@ -15,29 +15,17 @@ #include "raylib.h" #include "screens/screens.h" // NOTE: Defines global variable: currentScreen -#if defined(PLATFORM_ANDROID) - #include "android_native_app_glue.h" -#endif - //---------------------------------------------------------------------------------- // Main entry point //---------------------------------------------------------------------------------- -#if defined(PLATFORM_ANDROID) -void android_main(struct android_app *app) -#else int main(void) -#endif { - // Initialization + // Initialization (Note windowTitle is unused on Android) //--------------------------------------------------------- const int screenWidth = 800; const int screenHeight = 450; -#if defined(PLATFORM_ANDROID) - InitWindow(screenWidth, screenHeight, app); -#else InitWindow(screenWidth, screenHeight, "raylib template - standard game"); -#endif // TODO: Load global data here (assets that must be available in all screens, i.e. fonts) @@ -150,7 +138,6 @@ int main(void) CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- -#if !defined(PLATFORM_ANDROID) + return 0; -#endif -}
\ No newline at end of file +} |
