diff options
| author | David Reid <mackron@gmail.com> | 2018-07-01 20:52:50 +1000 |
|---|---|---|
| committer | David Reid <mackron@gmail.com> | 2018-07-01 20:52:50 +1000 |
| commit | fec0a4f2e37e63cdbc531f6914a55442d520a104 (patch) | |
| tree | 546a30f60fbe76abb24a2514ba824ec210674c36 /src | |
| parent | bce7a7b5765defcfb5692dc73e7251c8dd3e9fe2 (diff) | |
| parent | 7dedb84fd07f81cbe3f7c299b7e6e3f4e9959391 (diff) | |
| download | raylib-fec0a4f2e37e63cdbc531f6914a55442d520a104.tar.gz raylib-fec0a4f2e37e63cdbc531f6914a55442d520a104.zip | |
Merge branch 'master' of https://github.com/raysan5/raylib into dr/mini_al
Diffstat (limited to 'src')
| -rwxr-xr-x | src/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/Makefile | 32 | ||||
| -rw-r--r-- | src/audio.c | 27 | ||||
| -rw-r--r-- | src/camera.h | 4 | ||||
| -rw-r--r-- | src/core.c | 45 | ||||
| -rw-r--r-- | src/external/glfw/CMake/modules/FindVulkan.cmake | 5 | ||||
| -rw-r--r-- | src/external/glfw/README.md | 2 | ||||
| -rw-r--r-- | src/external/glfw/include/GLFW/glfw3.h | 20 | ||||
| -rw-r--r-- | src/external/glfw/src/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/external/glfw/src/input.c | 5 | ||||
| -rw-r--r-- | src/external/glfw/src/internal.h | 2 | ||||
| -rw-r--r-- | src/external/glfw/src/win32_platform.h | 4 | ||||
| -rw-r--r-- | src/external/glfw/src/window.c | 13 | ||||
| -rw-r--r-- | src/external/glfw/src/x11_window.c | 5 | ||||
| -rw-r--r-- | src/external/jar_xm.h | 2 | ||||
| -rw-r--r-- | src/models.c | 8 | ||||
| -rw-r--r-- | src/physac.h | 2 | ||||
| -rw-r--r-- | src/raylib.h | 73 | ||||
| -rw-r--r-- | src/raylib.rc.o (renamed from src/raylib_icon) | bin | 107340 -> 107260 bytes | |||
| -rw-r--r-- | src/raymath.h | 156 | ||||
| -rw-r--r-- | src/rglfw.c | 4 | ||||
| -rw-r--r-- | src/rlgl.c | 196 | ||||
| -rw-r--r-- | src/rlgl.h | 58 | ||||
| -rw-r--r-- | src/shapes.c | 12 | ||||
| -rw-r--r-- | src/text.c | 355 | ||||
| -rw-r--r-- | src/textures.c | 463 |
26 files changed, 936 insertions, 560 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7e94d97d..c19cebaf 100755 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -17,7 +17,7 @@ include_directories(SYSTEM .) file(GLOB raylib_sources *.c) list(REMOVE_ITEM raylib_sources ${CMAKE_CURRENT_SOURCE_DIR}/rglfw.c) -if(NOT glfw3_FOUND AND "${PLATFORM}" MATCHES "Desktop") +if(NOT glfw3_FOUND AND NOT USE_EXTERNAL_GLFW AND "${PLATFORM}" MATCHES "Desktop") set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE) set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE) set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) diff --git a/src/Makefile b/src/Makefile index f8219044..6f71874f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -6,7 +6,7 @@ # PLATFORM_DESKTOP: Windows (Win32, Win64) # PLATFORM_DESKTOP: Linux (32 and 64 bit) # PLATFORM_DESKTOP: OSX/macOS -# PLATFORM_DESKTOP: FreeBSD +# PLATFORM_DESKTOP: FreeBSD, OpenBSD, NetBSD, DragonFly # PLATFORM_ANDROID: Android (ARM, ARM64) # PLATFORM_RPI: Raspberry Pi (Raspbian) # PLATFORM_WEB: HTML5 (Chrome, Firefox) @@ -111,7 +111,16 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) PLATFORM_OS=LINUX endif ifeq ($(UNAMEOS),FreeBSD) - PLATFORM_OS=FREEBSD + PLATFORM_OS=BSD + endif + ifeq ($(UNAMEOS),OpenBSD) + PLATFORM_OS=BSD + endif + ifeq ($(UNAMEOS),NetBSD) + PLATFORM_OS=BSD + endif + ifeq ($(UNAMEOS),DragonFly) + PLATFORM_OS=BSD endif ifeq ($(UNAMEOS),Darwin) PLATFORM_OS=OSX @@ -185,8 +194,8 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),OSX) RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/osx endif - ifeq ($(PLATFORM_OS),FREEBSD) - RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/freebsd + ifeq ($(PLATFORM_OS),BSD) + RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/bsd endif endif ifeq ($(PLATFORM),PLATFORM_RPI) @@ -231,8 +240,8 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) CC = clang GLFW_CFLAGS = -x objective-c endif - ifeq ($(PLATFORM_OS),FREEBSD) - # FreeBSD default compiler + ifeq ($(PLATFORM_OS),BSD) + # FreeBSD, OpenBSD, NetBSD, DragonFly default compiler CC = clang endif endif @@ -309,13 +318,14 @@ endif ifeq ($(PLATFORM),PLATFORM_ANDROID) # Compiler flags for arquitecture (only ARM, not ARM64) #CFLAGS += -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 + CFLAGS += -target aarch64 -mfix-cortex-a53-835769 # Compilation functions attributes options CFLAGS += -ffunction-sections -funwind-tables -fstack-protector-strong -fPIE -fPIC # Compiler options for the linker # -Werror=format-security CFLAGS += -Wa,--noexecstack -Wformat -no-canonical-prefixes # Preprocessor macro definitions - CFLAGS += -DANDROID -DPLATFORM_ANDROID -D__ANDROID_API__=21 + CFLAGS += -DANDROID -DPLATFORM_ANDROID -D__ANDROID_API__=21 -DMAL_NO_OSS endif # Define required compilation flags for raylib SHARED lib @@ -345,7 +355,7 @@ endif INCLUDE_PATHS = -I. -Iexternal -Iexternal/glfw/include ifeq ($(PLATFORM),PLATFORM_DESKTOP) - ifeq ($(PLATFORM_OS),FREEBSD) + ifeq ($(PLATFORM_OS),BSD) INCLUDE_PATHS += -I/usr/local/include LDFLAGS += -L. -Lsrc -L/usr/local/lib -L$(RAYLIB_RELEASE_PATH) endif @@ -415,6 +425,10 @@ ifeq ($(INCLUDE_AUDIO_MODULE),TRUE) endif endif +ifeq ($(PLATFORM),PLATFORM_ANDROID) + OBJS += external/android/native_app_glue/android_native_app_glue.o +endif + # Default target entry all: raylib @@ -454,7 +468,7 @@ else cd $(RAYLIB_RELEASE_PATH) && ln -fs libraylib.$(RAYLIB_VERSION).dylib libraylib.$(RAYLIB_API_VERSION).dylib cd $(RAYLIB_RELEASE_PATH) && ln -fs libraylib.$(RAYLIB_VERSION).dylib libraylib.dylib endif - ifeq ($(PLATFORM_OS),FREEBSD) + ifeq ($(PLATFORM_OS),BSD) # 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)!" diff --git a/src/audio.c b/src/audio.c index abab48bc..ce857771 100644 --- a/src/audio.c +++ b/src/audio.c @@ -17,7 +17,7 @@ * Required types and functions are defined in the same module. * * #define USE_OPENAL_BACKEND -* Use OpenAL Soft audio backend usage +* Use OpenAL Soft audio backend * * #define SUPPORT_FILEFORMAT_WAV * #define SUPPORT_FILEFORMAT_OGG @@ -73,11 +73,6 @@ * **********************************************************************************************/ -#include "config.h" -#if !defined(USE_OPENAL_BACKEND) - #define USE_MINI_AL 1 // Set to 1 to use mini_al; 0 to use OpenAL. -#endif - #if defined(AUDIO_STANDALONE) #include "audio.h" #include <stdarg.h> // Required for: va_list, va_start(), vfprintf(), va_end() @@ -87,6 +82,10 @@ #include "utils.h" // Required for: fopen() Android mapping #endif +#if !defined(USE_OPENAL_BACKEND) + #define USE_MINI_AL 1 // Set to 1 to use mini_al; 0 to use OpenAL. +#endif + #include "external/mini_al.h" // Implemented in mini_al.c. Cannot implement this here because it conflicts with Win32 APIs such as CloseWindow(), etc. #if !defined(USE_MINI_AL) || (USE_MINI_AL == 0) @@ -668,7 +667,7 @@ AudioBuffer *CreateAudioBuffer(mal_format format, mal_uint32 channels, mal_uint3 mal_result resultMAL = mal_dsp_init(&dspConfig, &audioBuffer->dsp); if (resultMAL != MAL_SUCCESS) { - TraceLog(LOG_ERROR, "LoadSoundFromWave() : Failed to create data conversion pipeline"); + TraceLog(LOG_ERROR, "CreateAudioBuffer() : Failed to create data conversion pipeline"); free(audioBuffer); return NULL; } @@ -696,7 +695,7 @@ void DeleteAudioBuffer(AudioBuffer *audioBuffer) { if (audioBuffer == NULL) { - TraceLog(LOG_ERROR, "PlayAudioBuffer() : No audio buffer"); + TraceLog(LOG_ERROR, "DeleteAudioBuffer() : No audio buffer"); return; } @@ -709,7 +708,7 @@ bool IsAudioBufferPlaying(AudioBuffer *audioBuffer) { if (audioBuffer == NULL) { - TraceLog(LOG_ERROR, "PlayAudioBuffer() : No audio buffer"); + TraceLog(LOG_ERROR, "IsAudioBufferPlaying() : No audio buffer"); return false; } @@ -737,7 +736,7 @@ void StopAudioBuffer(AudioBuffer *audioBuffer) { if (audioBuffer == NULL) { - TraceLog(LOG_ERROR, "PlayAudioBuffer() : No audio buffer"); + TraceLog(LOG_ERROR, "StopAudioBuffer() : No audio buffer"); return; } @@ -756,7 +755,7 @@ void PauseAudioBuffer(AudioBuffer *audioBuffer) { if (audioBuffer == NULL) { - TraceLog(LOG_ERROR, "PlayAudioBuffer() : No audio buffer"); + TraceLog(LOG_ERROR, "PauseAudioBuffer() : No audio buffer"); return; } @@ -768,7 +767,7 @@ void ResumeAudioBuffer(AudioBuffer *audioBuffer) { if (audioBuffer == NULL) { - TraceLog(LOG_ERROR, "PlayAudioBuffer() : No audio buffer"); + TraceLog(LOG_ERROR, "ResumeAudioBuffer() : No audio buffer"); return; } @@ -780,7 +779,7 @@ void SetAudioBufferVolume(AudioBuffer *audioBuffer, float volume) { if (audioBuffer == NULL) { - TraceLog(LOG_ERROR, "PlayAudioBuffer() : No audio buffer"); + TraceLog(LOG_ERROR, "SetAudioBufferVolume() : No audio buffer"); return; } @@ -792,7 +791,7 @@ void SetAudioBufferPitch(AudioBuffer *audioBuffer, float pitch) { if (audioBuffer == NULL) { - TraceLog(LOG_ERROR, "PlayAudioBuffer() : No audio buffer"); + TraceLog(LOG_ERROR, "SetAudioBufferPitch() : No audio buffer"); return; } diff --git a/src/camera.h b/src/camera.h index 8067e7bf..6bada666 100644 --- a/src/camera.h +++ b/src/camera.h @@ -244,8 +244,8 @@ void SetCameraMode(Camera camera, int mode) distance.y = sqrtf(dx*dx + dy*dy); // Camera angle calculation - cameraAngle.x = asinf(fabsf(dx)/distance.x); // Camera angle in plane XZ (0 aligned with Z, move positive CCW) - cameraAngle.y = -asinf(fabsf(dy)/distance.y); // Camera angle in plane XY (0 aligned with X, move positive CW) + cameraAngle.x = asinf(fabs(dx)/distance.x); // Camera angle in plane XZ (0 aligned with Z, move positive CCW) + cameraAngle.y = -asinf(fabs(dy)/distance.y); // Camera angle in plane XY (0 aligned with X, move positive CW) // NOTE: Just testing what cameraAngle means //cameraAngle.x = 0.0f*DEG2RAD; // Camera angle in plane XZ (0 aligned with Z, move positive CCW) @@ -5,7 +5,7 @@ * PLATFORMS SUPPORTED: * - PLATFORM_DESKTOP: Windows (Win32, Win64) * - PLATFORM_DESKTOP: Linux (X11 desktop mode) -* - PLATFORM_DESKTOP: FreeBSD (X11 desktop) +* - PLATFORM_DESKTOP: FreeBSD, OpenBSD, NetBSD, DragonFly (X11 desktop) * - PLATFORM_DESKTOP: OSX/macOS * - PLATFORM_ANDROID: Android 4.0 (ARM, ARM64) * - PLATFORM_RPI: Raspberry Pi 0,1,2,3 (Raspbian) @@ -15,7 +15,7 @@ * CONFIGURATION: * * #define PLATFORM_DESKTOP -* Windowing and input system configured for desktop platforms: Windows, Linux, OSX, FreeBSD +* Windowing and input system configured for desktop platforms: Windows, Linux, OSX, FreeBSD, OpenBSD, NetBSD, DragonFly * NOTE: Oculus Rift CV1 requires PLATFORM_DESKTOP for mirror rendering - View [rlgl] module to enable it * * #define PLATFORM_ANDROID @@ -57,7 +57,7 @@ * Allow automatic gif recording of current screen pressing CTRL+F12, defined in KeyCallback() * * DEPENDENCIES: -* rglfw - Manage graphic device, OpenGL context and inputs on PLATFORM_DESKTOP (Windows, Linux, OSX. FreeBSD) +* rglfw - Manage graphic device, OpenGL context and inputs on PLATFORM_DESKTOP (Windows, Linux, OSX. FreeBSD, OpenBSD, NetBSD, DragonFly) * raymath - 3D math functionality (Vector2, Vector3, Matrix, Quaternion) * camera - Multiple 3D camera modes (free, orbital, 1st person, 3rd person) * gestures - Gestures system for touch-ready devices (or simulated from mouse inputs) @@ -1884,31 +1884,30 @@ static bool InitGraphicsDevice(int width, int height) displayHeight = screenHeight; #endif // defined(PLATFORM_WEB) - glfwDefaultWindowHints(); // Set default windows hints + glfwDefaultWindowHints(); // Set default windows hints: + //glfwWindowHint(GLFW_RED_BITS, 8); // Framebuffer red color component bits + //glfwWindowHint(GLFW_GREEN_BITS, 8); // Framebuffer green color component bits + //glfwWindowHint(GLFW_BLUE_BITS, 8); // Framebuffer blue color component bits + //glfwWindowHint(GLFW_ALPHA_BITS, 8); // Framebuffer alpha color component bits + //glfwWindowHint(GLFW_DEPTH_BITS, 24); // Depthbuffer bits + //glfwWindowHint(GLFW_REFRESH_RATE, 0); // Refresh rate for fullscreen window + //glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API); // OpenGL API to use. Alternative: GLFW_OPENGL_ES_API + //glfwWindowHint(GLFW_AUX_BUFFERS, 0); // Number of auxiliar buffers // Check some Window creation flags - if (configFlags & FLAG_WINDOW_RESIZABLE) glfwWindowHint(GLFW_RESIZABLE, GL_TRUE); // Resizable window + if (configFlags & FLAG_WINDOW_RESIZABLE) glfwWindowHint(GLFW_RESIZABLE, GL_TRUE); // Resizable window else glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); // Avoid window being resizable - if (configFlags & FLAG_WINDOW_DECORATED) glfwWindowHint(GLFW_DECORATED, GL_TRUE); // Border and buttons on Window + if (configFlags & FLAG_WINDOW_UNDECORATED) glfwWindowHint(GLFW_DECORATED, GL_FALSE); // Border and buttons on Window + else glfwWindowHint(GLFW_DECORATED, GL_TRUE); // Decorated window - if (configFlags & FLAG_WINDOW_TRANSPARENT) - { - // TODO: Enable transparent window (not ready yet on GLFW 3.2) - } +#if !defined(PLATFORM_WEB) // FLAG_WINDOW_TRANSPARENT not supported on HTML5 + if (configFlags & FLAG_WINDOW_TRANSPARENT) glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE); // Transparent framebuffer + else glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_FALSE); // Opaque framebuffer +#endif - if (configFlags & FLAG_MSAA_4X_HINT) - { - glfwWindowHint(GLFW_SAMPLES, 4); // Enables multisampling x4 (MSAA), default is 0 - TraceLog(LOG_INFO, "Trying to enable MSAA x4"); - } + if (configFlags & FLAG_MSAA_4X_HINT) glfwWindowHint(GLFW_SAMPLES, 4); // Tries to enable multisampling x4 (MSAA), default is 0 - //glfwWindowHint(GLFW_RED_BITS, 8); // Framebuffer red color component bits - //glfwWindowHint(GLFW_DEPTH_BITS, 16); // Depthbuffer bits (24 by default) - //glfwWindowHint(GLFW_REFRESH_RATE, 0); // Refresh rate for fullscreen window - //glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API); // Default OpenGL API to use. Alternative: GLFW_OPENGL_ES_API - //glfwWindowHint(GLFW_AUX_BUFFERS, 0); // Number of auxiliar buffers - // NOTE: When asking for an OpenGL context version, most drivers provide highest supported version // with forward compatibility to older OpenGL versions. // For example, if using OpenGL 1.1, driver can provide a 4.3 context forward compatible. @@ -1926,11 +1925,11 @@ static bool InitGraphicsDevice(int width, int height) glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // Profiles Hint: Only 3.3 and above! // Other values: GLFW_OPENGL_ANY_PROFILE, GLFW_OPENGL_COMPAT_PROFILE #if defined(__APPLE__) - glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // OSX Requires + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // OSX Requires fordward compatibility #else glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_FALSE); // Fordward Compatibility Hint: Only 3.3 and above! #endif - //glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE); + //glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE); // Request OpenGL DEBUG context } if (fullscreen) diff --git a/src/external/glfw/CMake/modules/FindVulkan.cmake b/src/external/glfw/CMake/modules/FindVulkan.cmake index 103554bb..5004356b 100644 --- a/src/external/glfw/CMake/modules/FindVulkan.cmake +++ b/src/external/glfw/CMake/modules/FindVulkan.cmake @@ -27,11 +27,6 @@ if (WIN32) "$ENV{VULKAN_SDK}/Bin32" "$ENV{VK_SDK_PATH}/Bin32") endif() -elseif (APPLE) - find_library(VULKAN_LIBRARY vulkan.1 HINTS - "$ENV{VULKAN_SDK}/macOS/lib") - find_path(VULKAN_INCLUDE_DIR NAMES vulkan/vulkan.h HINTS - "$ENV{VULKAN_SDK}/macOS/include") else() find_path(VULKAN_INCLUDE_DIR NAMES vulkan/vulkan.h HINTS "$ENV{VULKAN_SDK}/include") diff --git a/src/external/glfw/README.md b/src/external/glfw/README.md index 0573dcd9..82d4806a 100644 --- a/src/external/glfw/README.md +++ b/src/external/glfw/README.md @@ -165,6 +165,8 @@ information on what to include when reporting a bug. - Added `GLFW_HOVERED` window attribute for polling cursor hover state (#1166) - Added `GLFW_CENTER_CURSOR` window hint for controlling cursor centering (#749,#842) +- Added `GLFW_FOCUS_ON_SHOW` window hint and attribute to control input focus + on calling show window (#1189) - Added `GLFW_JOYSTICK_HAT_BUTTONS` init hint (#889) - Added `GLFW_LOCK_KEY_MODS` input mode and `GLFW_MOD_*_LOCK` mod bits (#946) - Added macOS specific `GLFW_COCOA_RETINA_FRAMEBUFFER` window hint diff --git a/src/external/glfw/include/GLFW/glfw3.h b/src/external/glfw/include/GLFW/glfw3.h index 00256d4d..990fe3f7 100644 --- a/src/external/glfw/include/GLFW/glfw3.h +++ b/src/external/glfw/include/GLFW/glfw3.h @@ -819,6 +819,12 @@ extern "C" { * Mouse cursor hover [window attribute](@ref GLFW_HOVERED_attrib). */ #define GLFW_HOVERED 0x0002000B +/*! @brief Input focus on calling show window hint and attribute + * + * Input focus [window hint](@ref GLFW_FOCUS_ON_SHOW_hint) or + * [window attribute](@ref GLFW_FOCUS_ON_SHOW_attrib). + */ +#define GLFW_FOCUS_ON_SHOW 0x0002000C /*! @brief Framebuffer bit depth hint. * @@ -3085,6 +3091,11 @@ GLFWAPI void glfwMaximizeWindow(GLFWwindow* window); * hidden. If the window is already visible or is in full screen mode, this * function does nothing. * + * By default, windowed mode windows are focused when shown + * Set the [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_hint) window hint + * to change this behavior for all newly created windows, or change the + * behavior for an existing window with @ref glfwSetWindowAttrib. + * * @param[in] window The window to make visible. * * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref @@ -3132,6 +3143,10 @@ GLFWAPI void glfwHideWindow(GLFWwindow* window); * initially created. Set the [GLFW_FOCUSED](@ref GLFW_FOCUSED_hint) to * disable this behavior. * + * Also by default, windowed mode windows are focused when shown + * with @ref glfwShowWindow. Set the + * [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_hint) to disable this behavior. + * * __Do not use this function__ to steal focus from other applications unless * you are certain that is what the user wants. Focus stealing can be * extremely disruptive. @@ -3306,8 +3321,9 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* window, int attrib); * * The supported attributes are [GLFW_DECORATED](@ref GLFW_DECORATED_attrib), * [GLFW_RESIZABLE](@ref GLFW_RESIZABLE_attrib), - * [GLFW_FLOATING](@ref GLFW_FLOATING_attrib) and - * [GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_attrib). + * [GLFW_FLOATING](@ref GLFW_FLOATING_attrib), + * [GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_attrib) and + * [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_attrib). * * Some of these attributes are ignored for full screen windows. The new * value will take effect if the window is later made windowed. diff --git a/src/external/glfw/src/CMakeLists.txt b/src/external/glfw/src/CMakeLists.txt index 6d3e33a5..fe060844 100644 --- a/src/external/glfw/src/CMakeLists.txt +++ b/src/external/glfw/src/CMakeLists.txt @@ -163,4 +163,3 @@ if (GLFW_INSTALL) ARCHIVE DESTINATION "lib${LIB_SUFFIX}" LIBRARY DESTINATION "lib${LIB_SUFFIX}") endif() - diff --git a/src/external/glfw/src/input.c b/src/external/glfw/src/input.c index 42975452..b0bb3de4 100644 --- a/src/external/glfw/src/input.c +++ b/src/external/glfw/src/input.c @@ -32,7 +32,6 @@ #include <math.h> #include <stdlib.h> #include <string.h> -#include <ctype.h> // Internal key state used for sticky keys #define _GLFW_STICK 3 @@ -1086,7 +1085,9 @@ GLFWAPI int glfwUpdateGamepadMappings(const char* string) while (*c) { - if (isxdigit(*c)) + if ((*c >= '0' && *c <= '9') || + (*c >= 'a' && *c <= 'f') || + (*c >= 'A' && *c <= 'F')) { char line[1024]; diff --git a/src/external/glfw/src/internal.h b/src/external/glfw/src/internal.h index 92bbfcce..9fc626dd 100644 --- a/src/external/glfw/src/internal.h +++ b/src/external/glfw/src/internal.h @@ -267,6 +267,7 @@ struct _GLFWwndconfig GLFWbool floating; GLFWbool maximized; GLFWbool centerCursor; + GLFWbool focusOnShow; struct { GLFWbool retina; char frameName[256]; @@ -372,6 +373,7 @@ struct _GLFWwindow GLFWbool decorated; GLFWbool autoIconify; GLFWbool floating; + GLFWbool focusOnShow; GLFWbool shouldClose; void* userPointer; GLFWvidmode videoMode; diff --git a/src/external/glfw/src/win32_platform.h b/src/external/glfw/src/win32_platform.h index 9a669215..59815146 100644 --- a/src/external/glfw/src/win32_platform.h +++ b/src/external/glfw/src/win32_platform.h @@ -242,7 +242,9 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)( #include "egl_context.h" #include "osmesa_context.h" -#define _GLFW_WNDCLASSNAME L"GLFW30" +#if !defined(_GLFW_WNDCLASSNAME) + #define _GLFW_WNDCLASSNAME L"GLFW30" +#endif #define _glfw_dlopen(name) LoadLibraryA(name) #define _glfw_dlclose(handle) FreeLibrary((HMODULE) handle) diff --git a/src/external/glfw/src/window.c b/src/external/glfw/src/window.c index 38a8982b..4ed415ca 100644 --- a/src/external/glfw/src/window.c +++ b/src/external/glfw/src/window.c @@ -201,6 +201,7 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, window->decorated = wndconfig.decorated; window->autoIconify = wndconfig.autoIconify; window->floating = wndconfig.floating; + window->focusOnShow = wndconfig.focusOnShow; window->cursorMode = GLFW_CURSOR_NORMAL; window->minwidth = GLFW_DONT_CARE; @@ -267,6 +268,7 @@ void glfwDefaultWindowHints(void) _glfw.hints.window.focused = GLFW_TRUE; _glfw.hints.window.autoIconify = GLFW_TRUE; _glfw.hints.window.centerCursor = GLFW_TRUE; + _glfw.hints.window.focusOnShow = GLFW_TRUE; // The default is 24 bits of color, 24 bits of depth and 8 bits of stencil, // double buffered @@ -370,6 +372,9 @@ GLFWAPI void glfwWindowHint(int hint, int value) case GLFW_CENTER_CURSOR: _glfw.hints.window.centerCursor = value ? GLFW_TRUE : GLFW_FALSE; return; + case GLFW_FOCUS_ON_SHOW: + _glfw.hints.window.focusOnShow = value ? GLFW_TRUE : GLFW_FALSE; + return; case GLFW_CLIENT_API: _glfw.hints.context.client = value; return; @@ -755,7 +760,9 @@ GLFWAPI void glfwShowWindow(GLFWwindow* handle) return; _glfwPlatformShowWindow(window); - _glfwPlatformFocusWindow(window); + + if (window->focusOnShow) + _glfwPlatformFocusWindow(window); } GLFWAPI void glfwRequestWindowAttention(GLFWwindow* handle) @@ -810,6 +817,8 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib) return _glfwPlatformWindowMaximized(window); case GLFW_HOVERED: return _glfwPlatformWindowHovered(window); + case GLFW_FOCUS_ON_SHOW: + return window->focusOnShow; case GLFW_TRANSPARENT_FRAMEBUFFER: return _glfwPlatformFramebufferTransparent(window); case GLFW_RESIZABLE: @@ -886,6 +895,8 @@ GLFWAPI void glfwSetWindowAttrib(GLFWwindow* handle, int attrib, int value) if (!window->monitor) _glfwPlatformSetWindowFloating(window, value); } + else if (attrib == GLFW_FOCUS_ON_SHOW) + window->focusOnShow = value; else _glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib); } diff --git a/src/external/glfw/src/x11_window.c b/src/external/glfw/src/x11_window.c index fc24f285..1c4e9c3c 100644 --- a/src/external/glfw/src/x11_window.c +++ b/src/external/glfw/src/x11_window.c @@ -2672,8 +2672,9 @@ void _glfwPlatformPollEvents(void) #if defined(__linux__) _glfwDetectJoystickConnectionLinux(); #endif - int count = XPending(_glfw.x11.display); - while (count--) + XPending(_glfw.x11.display); + + while (XQLength(_glfw.x11.display)) { XEvent event; XNextEvent(_glfw.x11.display, &event); diff --git a/src/external/jar_xm.h b/src/external/jar_xm.h index 9d4f5b5b..c8c9e3c9 100644 --- a/src/external/jar_xm.h +++ b/src/external/jar_xm.h @@ -2365,7 +2365,7 @@ static void jar_xm_tick(jar_xm_context_t* ctx) { float panning, volume; panning = ch->panning + - (ch->panning_envelope_panning - .5f) * (.5f - fabsf(ch->panning - .5f)) * 2.0f; + (ch->panning_envelope_panning - .5f) * (.5f - fabs(ch->panning - .5f)) * 2.0f; if(ch->tremor_on) { volume = .0f; diff --git a/src/models.c b/src/models.c index afeee0fc..b389333b 100644 --- a/src/models.c +++ b/src/models.c @@ -1837,9 +1837,9 @@ void DrawBoundingBox(BoundingBox box, Color color) { Vector3 size; - size.x = fabsf(box.max.x - box.min.x); - size.y = fabsf(box.max.y - box.min.y); - size.z = fabsf(box.max.z - box.min.z); + size.x = fabs(box.max.x - box.min.x); + size.y = fabs(box.max.y - box.min.y); + size.z = fabs(box.max.z - box.min.z); Vector3 center = { box.min.x + size.x/2.0f, box.min.y + size.y/2.0f, box.min.z + size.z/2.0f }; @@ -2074,7 +2074,7 @@ RayHitInfo GetCollisionRayGround(Ray ray, float groundHeight) RayHitInfo result = { 0 }; - if (fabsf(ray.direction.y) > EPSILON) + if (fabs(ray.direction.y) > EPSILON) { float distance = (ray.position.y - groundHeight)/-ray.direction.y; diff --git a/src/physac.h b/src/physac.h index 7fa62545..6b78fcc6 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 $(RAYLIB_DIR)\raylib\raylib_icon -static -lraylib -lpthread -lopengl32 -lgdi32 -std=c99 +* gcc -o $(NAME_PART).exe $(FILE_NAME) -s -static -lraylib -lpthread -lopengl32 -lgdi32 -std=c99 * * VERY THANKS TO: * Ramon Santamaria (github: @raysan5) diff --git a/src/raylib.h b/src/raylib.h index e83650e6..de78b8c3 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -3,6 +3,8 @@ * raylib - A simple and easy-to-use library to learn videogames programming (www.raylib.com) * * FEATURES: +* - NO external dependencies, all required libraries included with raylib +* - Multiple platforms support: Windows, Linux, FreeBSD, OpenBSD, NetBSD, DragonFly, MacOS, UWP, Android, Raspberry Pi, HTML5. * - Written in plain C code (C99) in PascalCase/camelCase notation * - Hardware accelerated with OpenGL (1.1, 2.1, 3.3 or ES2 - choose at compile) * - Unique OpenGL abstraction layer (usable as standalone module): [rlgl] @@ -12,10 +14,8 @@ * - Flexible Materials system, supporting classic maps and PBR maps * - Shaders support, including Model shaders and Postprocessing shaders * - Powerful math module for Vector, Matrix and Quaternion operations: [raymath] -* - Audio loading and playing with streaming support (WAV, OGG, FLAC, XM, MOD) -* - Multiple platforms support: Windows, Linux, FreeBSD, MacOS, UWP, Android, Raspberry Pi, HTML5. +* - Audio loading and playing with streaming support (WAV, OGG, MP3, FLAC, XM, MOD) * - VR stereo rendering with configurable HMD device parameters -* - NO external dependencies, all required libraries included with raylib * - Complete bindings to LUA (raylib-lua) and Go (raylib-go) * * NOTES: @@ -33,14 +33,15 @@ * stb_image_resize (Sean Barret) for image resizing algorythms [textures] * stb_image_write (Sean Barret) for image writting (PNG) [utils] * stb_truetype (Sean Barret) for ttf fonts loading [text] +* stb_rect_pack (Sean Barret) for rectangles packing [text] * stb_vorbis (Sean Barret) for OGG audio loading [audio] * stb_perlin (Sean Barret) for Perlin noise image generation [textures] * par_shapes (Philip Rideout) for parametric 3d shapes generation [models] * jar_xm (Joshua Reisenauer) for XM audio module loading [audio] * jar_mod (Joshua Reisenauer) for MOD audio module loading [audio] * dr_flac (David Reid) for FLAC audio file loading [audio] +* dr_mp3 (David Reid) for MP3 audio file loading [audio] * rgif (Charlie Tangora, Ramon Santamaria) for GIF recording [core] -* tinfl for data decompression (DEFLATE algorithm) [rres] * * * LICENSE: zlib/libpng @@ -92,7 +93,7 @@ #define FLAG_SHOW_LOGO 1 // Set to show raylib logo at startup #define FLAG_FULLSCREEN_MODE 2 // Set to run program in fullscreen #define FLAG_WINDOW_RESIZABLE 4 // Set to allow resizable window -#define FLAG_WINDOW_DECORATED 8 // Set to show window decoration (frame and buttons) +#define FLAG_WINDOW_UNDECORATED 8 // Set to disable window decoration (frame and buttons) #define FLAG_WINDOW_TRANSPARENT 16 // Set to allow transparent window #define FLAG_MSAA_4X_HINT 32 // Set to try enabling MSAA 4X #define FLAG_VSYNC_HINT 64 // Set to try enabling V-Sync on GPU @@ -389,6 +390,7 @@ typedef struct CharInfo { int offsetX; // Character offset X when drawing int offsetY; // Character offset Y when drawing int advanceX; // Character advance position X + unsigned char *data; // Character pixel data (grayscale) } CharInfo; // Font type, includes texture and charSet array data @@ -539,12 +541,12 @@ typedef struct VrDeviceInfo { // Enumerators Definition //---------------------------------------------------------------------------------- // Trace log type -typedef enum { +typedef enum { LOG_INFO = 1, - LOG_WARNING = 2, - LOG_ERROR = 4, - LOG_DEBUG = 8, - LOG_OTHER = 16 + LOG_WARNING = 2, + LOG_ERROR = 4, + LOG_DEBUG = 8, + LOG_OTHER = 16 } LogType; // Shader location point type @@ -636,16 +638,16 @@ typedef enum { } TextureFilterMode; // Texture parameters: wrap mode -typedef enum { - WRAP_REPEAT = 0, - WRAP_CLAMP, - WRAP_MIRROR +typedef enum { + WRAP_REPEAT = 0, + WRAP_CLAMP, + WRAP_MIRROR } TextureWrapMode; // Color blending modes (pre-defined) -typedef enum { - BLEND_ALPHA = 0, - BLEND_ADDITIVE, +typedef enum { + BLEND_ALPHA = 0, + BLEND_ADDITIVE, BLEND_MULTIPLIED } BlendMode; @@ -899,6 +901,7 @@ RLAPI void UnloadImage(Image image); RLAPI void UnloadTexture(Texture2D texture); // Unload texture from GPU memory (VRAM) RLAPI void UnloadRenderTexture(RenderTexture2D target); // Unload render texture from GPU memory (VRAM) RLAPI Color *GetImageData(Image image); // Get pixel data from image as a Color struct array +RLAPI Vector4 *GetImageDataNormalized(Image image); // Get pixel data from image as Vector4 array (float normalized) RLAPI int GetPixelDataSize(int width, int height, int format); // Get pixel data size in bytes (image or texture) RLAPI Image GetTextureData(Texture2D texture); // Get pixel data from GPU texture and return an Image RLAPI void UpdateTexture(Texture2D texture, const void *pixels); // Update GPU texture with new data @@ -912,8 +915,9 @@ RLAPI void ImageAlphaClear(Image *image, Color color, float threshold); RLAPI void ImageAlphaCrop(Image *image, float threshold); // Crop image depending on alpha value RLAPI void ImageAlphaPremultiply(Image *image); // Premultiply alpha channel 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 ImageResize(Image *image, int newWidth, int newHeight); // Resize image (bilinear filtering) +RLAPI void ImageResizeNN(Image *image, int newWidth,int newHeight); // Resize image (Nearest-Neighbor scaling algorithm) +RLAPI void ImageResizeCanvas(Image *image, int newWidth, int newHeight, int offsetX, int offsetY, Color color); // Resize canvas and fill with color 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) @@ -924,6 +928,8 @@ RLAPI void ImageDrawText(Image *dst, Vector2 position, const char *text, int fon RLAPI void ImageDrawTextEx(Image *dst, Vector2 position, Font font, const char *text, float fontSize, float spacing, Color color); // Draw text (custom sprite font) within an image (destination) RLAPI void ImageFlipVertical(Image *image); // Flip image vertically RLAPI void ImageFlipHorizontal(Image *image); // Flip image horizontally +RLAPI void ImageRotateCW(Image *image); // Rotate image clockwise 90deg +RLAPI void ImageRotateCCW(Image *image); // Rotate image counter-clockwise 90deg RLAPI void ImageColorTint(Image *image, Color color); // Modify image color: tint RLAPI void ImageColorInvert(Image *image); // Modify image color: invert RLAPI void ImageColorGrayscale(Image *image); // Modify image color: grayscale @@ -951,29 +957,30 @@ RLAPI void DrawTextureV(Texture2D texture, Vector2 position, Color tint); RLAPI void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, float scale, Color tint); // Draw a Texture2D with extended parameters RLAPI void DrawTextureRec(Texture2D texture, Rectangle sourceRec, Vector2 position, Color tint); // Draw a part of a texture defined by a rectangle RLAPI void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle destRec, Vector2 origin, float rotation, Color tint); // Draw a part of a texture defined by a rectangle with 'pro' parameters - //------------------------------------------------------------------------------------ // Font Loading and Text Drawing Functions (Module: text) //------------------------------------------------------------------------------------ // Font loading/unloading functions -RLAPI Font GetDefaultFont(void); // Get the default Font -RLAPI Font LoadFont(const char *fileName); // Load Font from file into GPU memory (VRAM) -RLAPI Font LoadFontEx(const char *fileName, int fontSize, int charsCount, int *fontChars); // Load Font from file with extended parameters -RLAPI void UnloadFont(Font font); // Unload Font from GPU memory (VRAM) +RLAPI Font GetDefaultFont(void); // Get the default Font +RLAPI Font LoadFont(const char *fileName); // Load font from file into GPU memory (VRAM) +RLAPI Font LoadFontEx(const char *fileName, int fontSize, int charsCount, int *fontChars); // Load font from file with extended parameters +RLAPI CharInfo *LoadFontData(const char *fileName, int fontSize, int *fontChars, int charsCount, bool sdf); // Load font data for further use +RLAPI Image GenImageFontAtlas(CharInfo *chars, int fontSize, int charsCount, int padding, int packMethod); // Generate image font atlas using chars info +RLAPI void UnloadFont(Font font); // Unload Font 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(Font font, const char* text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text using Font and additional parameters +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(Font font, const char* text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text using font and additional parameters // Text misc. functions -RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font -RLAPI Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing); // Measure string size for Font -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(Font font, int character); // Returns index position for a unicode character on sprite font +RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font +RLAPI Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing); // Measure string size for Font +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(Font font, int character); // Get index position for a unicode character on sprite font //------------------------------------------------------------------------------------ // Basic 3d Shapes Drawing Functions (Module: models) @@ -1013,7 +1020,7 @@ RLAPI void ExportMesh(const char *fileName, Mesh mesh); // Mesh manipulation functions RLAPI BoundingBox MeshBoundingBox(Mesh mesh); // Compute mesh bounding box limits -RLAPI void MeshTangents(Mesh *mesh); // Compute mesh tangents +RLAPI void MeshTangents(Mesh *mesh); // Compute mesh tangents RLAPI void MeshBinormals(Mesh *mesh); // Compute mesh binormals // Mesh generation functions diff --git a/src/raylib_icon b/src/raylib.rc.o Binary files differindex f6e32f37..28005c73 100644 --- a/src/raylib_icon +++ b/src/raylib.rc.o diff --git a/src/raymath.h b/src/raymath.h index b0046522..a574dd0d 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -12,9 +12,9 @@ * #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. +* Avoid raylib.h header inclusion in this file. * Vector3 and Matrix data types are defined internally in raymath module. * * @@ -94,7 +94,7 @@ // Return float vector for Vector3 #ifndef Vector3ToFloat - #define Vector3ToFloat(vec) (Vector3ToFloatV(vec).v) + #define Vector3ToFloat(vec) (Vector3ToFloatV(vec).v) #endif //---------------------------------------------------------------------------------- @@ -122,20 +122,20 @@ float m2, m6, m10, m14; float m3, m7, m11, m15; } Matrix; + + // Quaternion type + typedef struct Quaternion { + float x; + float y; + float z; + float w; + } Quaternion; #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; - float y; - float z; - float w; -} Quaternion; - #include <math.h> // Required for: sinf(), cosf(), tan(), fabs() //---------------------------------------------------------------------------------- @@ -143,7 +143,7 @@ typedef struct Quaternion { //---------------------------------------------------------------------------------- // Clamp float value -RMDEF float Clamp(float value, float min, float max) +RMDEF float Clamp(float value, float min, float max) { const float res = value < min ? min : value; return res > max ? max : res; @@ -154,15 +154,15 @@ RMDEF float Clamp(float value, float min, float max) //---------------------------------------------------------------------------------- // Vector with components value 0.0f -RMDEF Vector2 Vector2Zero(void) -{ +RMDEF Vector2 Vector2Zero(void) +{ Vector2 result = { 0.0f, 0.0f }; return result; } // Vector with components value 1.0f -RMDEF Vector2 Vector2One(void) -{ +RMDEF Vector2 Vector2One(void) +{ Vector2 result = { 1.0f, 1.0f }; return result; } @@ -243,31 +243,31 @@ RMDEF Vector2 Vector2Normalize(Vector2 v) //---------------------------------------------------------------------------------- // Vector with components value 0.0f -RMDEF Vector3 Vector3Zero(void) -{ +RMDEF Vector3 Vector3Zero(void) +{ Vector3 result = { 0.0f, 0.0f, 0.0f }; - return result; + return result; } // Vector with components value 1.0f -RMDEF Vector3 Vector3One(void) -{ +RMDEF Vector3 Vector3One(void) +{ Vector3 result = { 1.0f, 1.0f, 1.0f }; - return result; + return result; } // Add two vectors RMDEF Vector3 Vector3Add(Vector3 v1, Vector3 v2) { Vector3 result = { v1.x + v2.x, v1.y + v2.y, v1.z + v2.z }; - return result; + return result; } // Substract two vectors RMDEF Vector3 Vector3Subtract(Vector3 v1, Vector3 v2) { Vector3 result = { v1.x - v2.x, v1.y - v2.y, v1.z - v2.z }; - return result; + return result; } // Multiply vector by scalar @@ -279,7 +279,7 @@ RMDEF Vector3 Vector3Multiply(Vector3 v, float scalar) // Multiply vector by vector RMDEF Vector3 Vector3MultiplyV(Vector3 v1, Vector3 v2) -{ +{ Vector3 result = { v1.x*v2.x, v1.y*v2.y, v1.z*v2.z }; return result; } @@ -296,17 +296,17 @@ RMDEF Vector3 Vector3Perpendicular(Vector3 v) { Vector3 result = { 0 }; - float min = fabsf(v.x); + float min = fabs(v.x); Vector3 cardinalAxis = {1.0f, 0.0f, 0.0f}; - if (fabsf(v.y) < min) + if (fabs(v.y) < min) { - min = fabsf(v.y); + min = fabs(v.y); Vector3 tmp = {0.0f, 1.0f, 0.0f}; cardinalAxis = tmp; } - if (fabsf(v.z) < min) + if (fabs(v.z) < min) { Vector3 tmp = {0.0f, 0.0f, 1.0f}; cardinalAxis = tmp; @@ -359,7 +359,7 @@ RMDEF Vector3 Vector3Negate(Vector3 v) RMDEF Vector3 Vector3Normalize(Vector3 v) { Vector3 result = v; - + float length, ilength; length = Vector3Length(v); if (length == 0.0f) length = 1.0f; @@ -394,10 +394,22 @@ RMDEF Vector3 Vector3Transform(Vector3 v, Matrix mat) 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; }; +// Transform a vector by quaternion rotation +RMDEF Vector3 Vector3RotateByQuaternion(Vector3 v, Quaternion q) +{ + Vector3 result = { 0 }; + + result.x = v.x*(q.x*q.x + q.w*q.w - q.y*q.y - q.z*q.z) + v.y*(2*q.x*q.y - 2*q.w*q.z) + v.z*(2*q.x*q.z + 2*q.w*q.y); + result.y = v.x*(2*q.w*q.z + 2*q.x*q.y) + v.y*(q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z) + v.z*(-2*q.w*q.x + 2*q.y*q.z); + result.z = v.x*(-2*q.w*q.y + 2*q.x*q.z) + v.y*(2*q.w*q.x + 2*q.y*q.z)+ v.z*(q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z); + + return result; +} + // Calculate linear interpolation between two vectors RMDEF Vector3 Vector3Lerp(Vector3 v1, Vector3 v2, float amount) { @@ -432,11 +444,11 @@ RMDEF Vector3 Vector3Reflect(Vector3 v, Vector3 normal) RMDEF Vector3 Vector3Min(Vector3 v1, Vector3 v2) { Vector3 result = { 0 }; - + result.x = fminf(v1.x, v2.x); result.y = fminf(v1.y, v2.y); result.z = fminf(v1.z, v2.z); - + return result; } @@ -444,11 +456,11 @@ RMDEF Vector3 Vector3Min(Vector3 v1, Vector3 v2) RMDEF Vector3 Vector3Max(Vector3 v1, Vector3 v2) { Vector3 result = { 0 }; - + result.x = fmaxf(v1.x, v2.x); result.y = fmaxf(v1.y, v2.y); result.z = fmaxf(v1.z, v2.z); - + return result; } @@ -457,7 +469,7 @@ RMDEF Vector3 Vector3Max(Vector3 v1, Vector3 v2) RMDEF Vector3 Vector3Barycenter(Vector3 p, Vector3 a, Vector3 b, Vector3 c) { //Vector v0 = b - a, v1 = c - a, v2 = p - a; - + Vector3 v0 = Vector3Subtract(b, a); Vector3 v1 = Vector3Subtract(c, a); Vector3 v2 = Vector3Subtract(p, a); @@ -466,15 +478,15 @@ RMDEF Vector3 Vector3Barycenter(Vector3 p, Vector3 a, Vector3 b, Vector3 c) float d11 = Vector3DotProduct(v1, v1); float d20 = Vector3DotProduct(v2, v0); float d21 = Vector3DotProduct(v2, v1); - + float denom = d00*d11 - d01*d01; - + Vector3 result = { 0 }; - + result.y = (d11*d20 - d01*d21)/denom; result.z = (d00*d21 - d01*d20)/denom; result.x = 1.0f - (result.z + result.y); - + return result; } @@ -598,7 +610,7 @@ RMDEF Matrix MatrixInvert(Matrix mat) RMDEF Matrix MatrixNormalize(Matrix mat) { Matrix result = { 0 }; - + float det = MatrixDeterminant(mat); result.m0 = mat.m0/det; @@ -617,15 +629,15 @@ RMDEF Matrix MatrixNormalize(Matrix mat) result.m13 = mat.m13/det; result.m14 = mat.m14/det; result.m15 = mat.m15/det; - + return result; } // Returns identity matrix RMDEF Matrix MatrixIdentity(void) { - Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, + Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }; @@ -685,9 +697,9 @@ RMDEF Matrix MatrixSubstract(Matrix left, Matrix right) // Returns translation matrix RMDEF Matrix MatrixTranslate(float x, float y, float z) { - Matrix result = { 1.0f, 0.0f, 0.0f, x, - 0.0f, 1.0f, 0.0f, y, - 0.0f, 0.0f, 1.0f, z, + Matrix result = { 1.0f, 0.0f, 0.0f, x, + 0.0f, 1.0f, 0.0f, y, + 0.0f, 0.0f, 1.0f, z, 0.0f, 0.0f, 0.0f, 1.0f }; return result; @@ -724,12 +736,12 @@ RMDEF Matrix MatrixRotate(Vector3 axis, float angle) result.m5 = y*y*t + cosres; result.m6 = z*y*t + x*sinres; result.m7 = 0.0f; - + result.m8 = x*z*t + y*sinres; result.m9 = y*z*t - x*sinres; result.m10 = z*z*t + cosres; result.m11 = 0.0f; - + result.m12 = 0.0f; result.m13 = 0.0f; result.m14 = 0.0f; @@ -789,9 +801,9 @@ RMDEF Matrix MatrixRotateZ(float angle) // Returns scaling matrix RMDEF Matrix MatrixScale(float x, float y, float z) { - Matrix result = { x, 0.0f, 0.0f, 0.0f, - 0.0f, y, 0.0f, 0.0f, - 0.0f, 0.0f, z, 0.0f, + Matrix result = { x, 0.0f, 0.0f, 0.0f, + 0.0f, y, 0.0f, 0.0f, + 0.0f, 0.0f, z, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }; return result; @@ -859,11 +871,11 @@ RMDEF Matrix MatrixFrustum(double left, double right, double bottom, double top, // NOTE: Angle should be provided in radians RMDEF Matrix MatrixPerspective(double fovy, double aspect, double near, double far) { - double top = near*tan(fovy*0.5); + double top = near*tan(fovy*0.5); double right = top*aspect; Matrix result = MatrixFrustum(-right, right, -top, top, near, far); - return result; + return result; } // Returns orthographic projection matrix @@ -906,7 +918,7 @@ RMDEF Matrix MatrixLookAt(Vector3 eye, Vector3 target, Vector3 up) x = Vector3Normalize(x); Vector3 y = Vector3CrossProduct(z, x); y = Vector3Normalize(y); - + result.m0 = x.x; result.m1 = x.y; result.m2 = x.z; @@ -976,7 +988,7 @@ RMDEF float QuaternionLength(Quaternion q) RMDEF Quaternion QuaternionNormalize(Quaternion q) { Quaternion result = { 0 }; - + float length, ilength; length = QuaternionLength(q); if (length == 0.0f) length = 1.0f; @@ -986,7 +998,7 @@ RMDEF Quaternion QuaternionNormalize(Quaternion q) result.y = q.y*ilength; result.z = q.z*ilength; result.w = q.w*ilength; - + return result; } @@ -996,17 +1008,17 @@ RMDEF Quaternion QuaternionInvert(Quaternion q) Quaternion result = q; float length = QuaternionLength(q); float lengthSq = length*length; - + if (lengthSq != 0.0) { float i = 1.0f/lengthSq; - + result.x *= -i; result.y *= -i; result.z *= -i; result.w *= i; } - + return result; } @@ -1044,7 +1056,7 @@ RMDEF Quaternion QuaternionNlerp(Quaternion q1, Quaternion q2, float amount) { Quaternion result = QuaternionLerp(q1, q2, amount); result = QuaternionNormalize(result); - + return result; } @@ -1096,13 +1108,13 @@ RMDEF Quaternion QuaternionFromVector3ToVector3(Vector3 from, Vector3 to) 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 - result = QuaternionNormalize(result); - + result = QuaternionNormalize(result); + // Above lines are equivalent to: //Quaternion result = QuaternionNlerp(q, QuaternionIdentity(), 0.5f); - + return result; } @@ -1172,7 +1184,7 @@ RMDEF Matrix QuaternionToMatrix(Quaternion q) float x2 = x + x; float y2 = y + y; float z2 = z + z; - + float length = QuaternionLength(q); float lengthSquared = length*length; @@ -1204,7 +1216,7 @@ RMDEF Matrix QuaternionToMatrix(Quaternion q) result.m13 = 0.0f; result.m14 = 0.0f; result.m15 = 1.0f; - + return result; } @@ -1219,7 +1231,7 @@ RMDEF Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle) angle *= 0.5f; axis = Vector3Normalize(axis); - + float sinres = sinf(angle); float cosres = cosf(angle); @@ -1277,7 +1289,7 @@ RMDEF Quaternion QuaternionFromEuler(float roll, float pitch, float yaw) q.y = x0*y1*z0 + x1*y0*z1; q.z = x0*y0*z1 - x1*y1*z0; q.w = x0*y0*z0 + x1*y1*z1; - + return q; } @@ -1300,9 +1312,9 @@ RMDEF Vector3 QuaternionToEuler(Quaternion q) // 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); + float z1 = 1.0f - 2.0f*(q.y*q.y + q.z*q.z); result.z = atan2f(z0, z1)*RAD2DEG; - + return result; } @@ -1315,7 +1327,7 @@ RMDEF Quaternion QuaternionTransform(Quaternion q, Matrix mat) 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; } diff --git a/src/rglfw.c b/src/rglfw.c index e1b5392e..50d606d4 100644 --- a/src/rglfw.c +++ b/src/rglfw.c @@ -37,7 +37,7 @@ #define _GLFW_X11 #endif #endif -#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__) +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) #define _GLFW_X11 #endif #if defined(__APPLE__) @@ -91,7 +91,7 @@ #include "external/glfw/src/osmesa_context.c" #endif -#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__) +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__) || defined(__DragonFly__) #include "external/glfw/src/x11_init.c" #include "external/glfw/src/x11_monitor.c" #include "external/glfw/src/x11_window.c" @@ -2,8 +2,8 @@ * * rlgl - raylib OpenGL abstraction layer * -* rlgl is a wrapper for multiple OpenGL versions (1.1, 2.1, 3.3 Core, ES 2.0) to -* pseudo-OpenGL 1.1 style functions (rlVertex, rlTranslate, rlRotate...). +* rlgl is a wrapper for multiple OpenGL versions (1.1, 2.1, 3.3 Core, ES 2.0) to +* pseudo-OpenGL 1.1 style functions (rlVertex, rlTranslate, rlRotate...). * * When chosing an OpenGL version greater than OpenGL 1.1, rlgl stores vertex data on internal * VBO buffers (and VAOs if available). It requires calling 3 functions: @@ -657,7 +657,7 @@ void rlEnd(void) // as well as depth buffer bit-depth (16bit or 24bit or 32bit) // Correct increment formula would be: depthInc = (zfar - znear)/pow(2, bits) currentDepth += (1.0f/20000.0f); - + // Verify internal buffers limits // NOTE: This check is combined with usage of rlCheckBufferLimit() if ((lines.vCounter/2 >= MAX_LINES_BATCH - 2) || @@ -829,7 +829,7 @@ void rlEnableTexture(unsigned int id) if (draws[drawsCounter - 1].textureId != id) { if (draws[drawsCounter - 1].vertexCount > 0) drawsCounter++; - + if (drawsCounter >= MAX_DRAWS_BY_TEXTURE) { rlglDraw(); @@ -1126,7 +1126,7 @@ void rlglInit(int width, int height) // Check NPOT textures support // NOTE: Only check on OpenGL ES, OpenGL 3.3 has NPOT textures full support as core feature if (strcmp(extList[i], (const char *)"GL_OES_texture_npot") == 0) texNPOTSupported = true; - + // Check texture float support if (strcmp(extList[i], (const char *)"GL_OES_texture_float") == 0) texFloatSupported = true; #endif @@ -1158,7 +1158,7 @@ void rlglInit(int width, int height) // Clamp mirror wrap mode supported if (strcmp(extList[i], (const char *)"GL_EXT_texture_mirror_clamp") == 0) texClampMirrorSupported = true; - + // Debug marker support if(strcmp(extList[i], (const char *)"GL_EXT_debug_marker") == 0) debugMarkerSupported = true; } @@ -1271,9 +1271,9 @@ void rlglClose(void) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) UnloadShaderDefault(); // Unload default shader - UnloadBuffersDefault(); // Unload default buffers (lines, triangles, quads) + UnloadBuffersDefault(); // Unload default buffers (lines, triangles, quads) glDeleteTextures(1, &whiteTexture); // Unload default texture - + TraceLog(LOG_INFO, "[TEX ID %i] Unloaded texture data (base white texture) from VRAM", whiteTexture); free(draws); @@ -1438,30 +1438,30 @@ unsigned int rlLoadTexture(void *data, int width, int height, int format, int mi #endif glBindTexture(GL_TEXTURE_2D, id); - + int mipWidth = width; int mipHeight = height; int mipOffset = 0; // Mipmap data offset - + TraceLog(LOG_DEBUG, "Load texture from data memory address: 0x%x", data); - + // Load the different mipmap levels for (int i = 0; i < mipmapCount; i++) { unsigned int mipSize = GetPixelDataSize(mipWidth, mipHeight, format); - + int glInternalFormat, glFormat, glType; GetGlFormats(format, &glInternalFormat, &glFormat, &glType); - + TraceLog(LOG_DEBUG, "Load mipmap level %i (%i x %i), size: %i, offset: %i", i, mipWidth, mipHeight, mipSize, mipOffset); - + if (glInternalFormat != -1) { if (format < COMPRESSED_DXT1_RGB) glTexImage2D(GL_TEXTURE_2D, i, glInternalFormat, mipWidth, mipHeight, 0, glFormat, glType, (unsigned char *)data + mipOffset); - #if !defined(GRAPHICS_API_OPENGL_11) + #if !defined(GRAPHICS_API_OPENGL_11) else glCompressedTexImage2D(GL_TEXTURE_2D, i, glInternalFormat, mipWidth, mipHeight, 0, mipSize, (unsigned char *)data + mipOffset); #endif - + #if defined(GRAPHICS_API_OPENGL_33) if (format == UNCOMPRESSED_GRAYSCALE) { @@ -1479,11 +1479,11 @@ unsigned int rlLoadTexture(void *data, int width, int height, int format, int mi } #endif } - + mipWidth /= 2; mipHeight /= 2; mipOffset += mipSize; - + // Security check for NPOT textures if (mipWidth < 1) mipWidth = 1; if (mipHeight < 1) mipHeight = 1; @@ -1539,7 +1539,7 @@ unsigned int rlLoadTexture(void *data, int width, int height, int format, int mi void rlUpdateTexture(unsigned int id, int width, int height, int format, const void *data) { glBindTexture(GL_TEXTURE_2D, id); - + int glInternalFormat, glFormat, glType; GetGlFormats(format, &glInternalFormat, &glFormat, &glType); @@ -1671,7 +1671,7 @@ void rlGenerateMipmaps(Texture2D *texture) { // Retrieve texture data from VRAM void *data = rlReadTexturePixels(*texture); - + // NOTE: data size is reallocated to fit mipmaps data // NOTE: CPU mipmap generation only supports RGBA 32bit data int mipmapCount = GenerateMipmaps(data, texture->width, texture->height); @@ -1696,7 +1696,7 @@ void rlGenerateMipmaps(Texture2D *texture) texture->mipmaps = mipmapCount + 1; free(data); // Once mipmaps have been generated and data has been uploaded to GPU VRAM, we can discard RAM data - + TraceLog(LOG_WARNING, "[TEX ID %i] Mipmaps [%i] generated manually on CPU side", texture->id, texture->mipmaps); } else TraceLog(LOG_WARNING, "[TEX ID %i] Mipmaps could not be generated for texture format", texture->id); @@ -1943,27 +1943,27 @@ void rlDrawMesh(Mesh mesh, Material material, Matrix transform) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) // Bind shader program - glUseProgram(material.shader.id); + glUseProgram(material.shader.id); // Matrices and other values required by shader //----------------------------------------------------- // Calculate and send to shader model matrix (used by PBR shader) if (material.shader.locs[LOC_MATRIX_MODEL] != -1) SetShaderValueMatrix(material.shader, material.shader.locs[LOC_MATRIX_MODEL], transform); - + // Upload to shader material.colDiffuse if (material.shader.locs[LOC_COLOR_DIFFUSE] != -1) - glUniform4f(material.shader.locs[LOC_COLOR_DIFFUSE], (float)material.maps[MAP_DIFFUSE].color.r/255.0f, - (float)material.maps[MAP_DIFFUSE].color.g/255.0f, - (float)material.maps[MAP_DIFFUSE].color.b/255.0f, + glUniform4f(material.shader.locs[LOC_COLOR_DIFFUSE], (float)material.maps[MAP_DIFFUSE].color.r/255.0f, + (float)material.maps[MAP_DIFFUSE].color.g/255.0f, + (float)material.maps[MAP_DIFFUSE].color.b/255.0f, (float)material.maps[MAP_DIFFUSE].color.a/255.0f); // Upload to shader material.colSpecular (if available) - if (material.shader.locs[LOC_COLOR_SPECULAR] != -1) - glUniform4f(material.shader.locs[LOC_COLOR_SPECULAR], (float)material.maps[MAP_SPECULAR].color.r/255.0f, - (float)material.maps[MAP_SPECULAR].color.g/255.0f, - (float)material.maps[MAP_SPECULAR].color.b/255.0f, + if (material.shader.locs[LOC_COLOR_SPECULAR] != -1) + glUniform4f(material.shader.locs[LOC_COLOR_SPECULAR], (float)material.maps[MAP_SPECULAR].color.r/255.0f, + (float)material.maps[MAP_SPECULAR].color.g/255.0f, + (float)material.maps[MAP_SPECULAR].color.b/255.0f, (float)material.maps[MAP_SPECULAR].color.a/255.0f); - + if (material.shader.locs[LOC_MATRIX_VIEW] != -1) SetShaderValueMatrix(material.shader, material.shader.locs[LOC_MATRIX_VIEW], modelview); if (material.shader.locs[LOC_MATRIX_PROJECTION] != -1) SetShaderValueMatrix(material.shader, material.shader.locs[LOC_MATRIX_PROJECTION], projection); @@ -2054,7 +2054,7 @@ void rlDrawMesh(Mesh mesh, Material material, Matrix transform) #if defined(SUPPORT_VR_SIMULATOR) if (vrStereoRender) eyesCount = 2; #endif - + for (int eye = 0; eye < eyesCount; eye++) { if (eyesCount == 1) modelview = matModelView; @@ -2072,7 +2072,7 @@ void rlDrawMesh(Mesh mesh, Material material, Matrix transform) if (mesh.indices != NULL) glDrawElements(GL_TRIANGLES, mesh.triangleCount*3, GL_UNSIGNED_SHORT, 0); // Indexed vertices draw else glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount); } - + // Unbind all binded texture maps for (int i = 0; i < MAX_MATERIAL_MAPS; i++) { @@ -2168,7 +2168,7 @@ void *rlReadTexturePixels(Texture2D texture) glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &format); // Other texture info: GL_TEXTURE_RED_SIZE, GL_TEXTURE_GREEN_SIZE, GL_TEXTURE_BLUE_SIZE, GL_TEXTURE_ALPHA_SIZE */ - + // NOTE: Each row written to or read from by OpenGL pixel operations like glGetTexImage are aligned to a 4 byte boundary by default, which may add some padding. // Use glPixelStorei to modify padding with the GL_[UN]PACK_ALIGNMENT setting. // GL_PACK_ALIGNMENT affects operations that read from OpenGL memory (glReadPixels, glGetTexImage, etc.) @@ -2178,7 +2178,7 @@ void *rlReadTexturePixels(Texture2D texture) int glInternalFormat, glFormat, glType; GetGlFormats(texture.format, &glInternalFormat, &glFormat, &glType); unsigned int size = GetPixelDataSize(texture.width, texture.height, texture.format); - + if ((glInternalFormat != -1) && (texture.format < COMPRESSED_DXT1_RGB)) { pixels = (unsigned char *)malloc(size); @@ -2224,7 +2224,7 @@ void *rlReadTexturePixels(Texture2D texture) //glDisable(GL_TEXTURE_2D); glEnable(GL_DEPTH_TEST); //glDisable(GL_BLEND); - + glViewport(0, 0, texture.width, texture.height); rlOrtho(0.0, texture.width, texture.height, 0.0, 0.0, 1.0); @@ -2234,17 +2234,17 @@ void *rlReadTexturePixels(Texture2D texture) GenDrawQuad(); glBindTexture(GL_TEXTURE_2D, 0); glUseProgram(0); - + pixels = (unsigned char *)malloc(texture.width*texture.height*4*sizeof(unsigned char)); glReadPixels(0, 0, texture.width, texture.height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); // Bind framebuffer 0, which means render to back buffer glBindFramebuffer(GL_FRAMEBUFFER, 0); - + // Reset viewport dimensions to default glViewport(0, 0, screenWidth, screenHeight); - + #endif // GET_TEXTURE_FBO_OPTION // Clean up temporal fbo @@ -2349,9 +2349,9 @@ Shader LoadShader(const char *vsFileName, const char *fsFileName) if (vsFileName != NULL) vShaderStr = LoadText(vsFileName); if (fsFileName != NULL) fShaderStr = LoadText(fsFileName); - + shader = LoadShaderCode(vShaderStr, fShaderStr); - + if (vShaderStr != NULL) free(vShaderStr); if (fShaderStr != NULL) free(fShaderStr); @@ -2366,16 +2366,16 @@ Shader LoadShaderCode(char *vsCode, char *fsCode) // NOTE: All locations must be reseted to -1 (no location) for (int i = 0; i < MAX_SHADER_LOCATIONS; i++) shader.locs[i] = -1; - + #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) unsigned int vertexShaderId = defaultVShaderId; unsigned int fragmentShaderId = defaultFShaderId; - + if (vsCode != NULL) vertexShaderId = CompileShader(vsCode, GL_VERTEX_SHADER); if (fsCode != NULL) fragmentShaderId = CompileShader(fsCode, GL_FRAGMENT_SHADER); - + if ((vertexShaderId == defaultVShaderId) && (fragmentShaderId == defaultFShaderId)) shader = defaultShader; - else + else { shader.id = LoadShaderProgram(vertexShaderId, fragmentShaderId); @@ -2387,17 +2387,17 @@ Shader LoadShaderCode(char *vsCode, char *fsCode) TraceLog(LOG_WARNING, "Custom shader could not be loaded"); shader = defaultShader; } - + // After shader loading, we TRY to set default location names if (shader.id > 0) SetShaderDefaultLocations(&shader); } - + // Get available shader uniforms // NOTE: This information is useful for debug... int uniformCount = -1; - + glGetProgramiv(shader.id, GL_ACTIVE_UNIFORMS, &uniformCount); - + for(int i = 0; i < uniformCount; i++) { int namelen = -1; @@ -2407,16 +2407,16 @@ Shader LoadShaderCode(char *vsCode, char *fsCode) // Get the name of the uniforms glGetActiveUniform(shader.id, i,sizeof(name) - 1, &namelen, &num, &type, name); - + name[namelen] = 0; // Get the location of the named uniform GLuint location = glGetUniformLocation(shader.id, name); - + TraceLog(LOG_DEBUG, "[SHDR ID %i] Active uniform [%s] set at location: %i", shader.id, name, location); } #endif - + return shader; } @@ -2524,7 +2524,7 @@ void SetMatrixModelview(Matrix view) } // Return internal modelview matrix -Matrix GetMatrixModelview() +Matrix GetMatrixModelview() { Matrix matrix = MatrixIdentity(); #if defined(GRAPHICS_API_OPENGL_11) @@ -2541,16 +2541,16 @@ Matrix GetMatrixModelview() Texture2D GenTextureCubemap(Shader shader, Texture2D skyHDR, int size) { Texture2D cubemap = { 0 }; -#if defined(GRAPHICS_API_OPENGL_33) // || defined(GRAPHICS_API_OPENGL_ES2) +#if defined(GRAPHICS_API_OPENGL_33) // || defined(GRAPHICS_API_OPENGL_ES2) // NOTE: SetShaderDefaultLocations() already setups locations for projection and view Matrix in shader // Other locations should be setup externally in shader before calling the function - + // Set up depth face culling and cubemap seamless glDisable(GL_CULL_FACE); #if defined(GRAPHICS_API_OPENGL_33) glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); // Flag not supported on OpenGL ES 2.0 #endif - + // Setup framebuffer unsigned int fbo, rbo; @@ -2565,7 +2565,7 @@ Texture2D GenTextureCubemap(Shader shader, Texture2D skyHDR, int size) // NOTE: faces are stored with 16 bit floating point values glGenTextures(1, &cubemap.id); glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap.id); - for (unsigned int i = 0; i < 6; i++) + for (unsigned int i = 0; i < 6; i++) glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, size, size, 0, GL_RGB, GL_FLOAT, NULL); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); @@ -2607,7 +2607,7 @@ Texture2D GenTextureCubemap(Shader shader, Texture2D skyHDR, int size) // Unbind framebuffer and textures glBindFramebuffer(GL_FRAMEBUFFER, 0); - + // Reset viewport dimensions to default glViewport(0, 0, screenWidth, screenHeight); //glEnable(GL_CULL_FACE); @@ -2623,11 +2623,11 @@ Texture2D GenTextureCubemap(Shader shader, Texture2D skyHDR, int size) Texture2D GenTextureIrradiance(Shader shader, Texture2D cubemap, int size) { Texture2D irradiance = { 0 }; - + #if defined(GRAPHICS_API_OPENGL_33) // || defined(GRAPHICS_API_OPENGL_ES2) // NOTE: SetShaderDefaultLocations() already setups locations for projection and view Matrix in shader // Other locations should be setup externally in shader before calling the function - + // Setup framebuffer unsigned int fbo, rbo; glGenFramebuffers(1, &fbo); @@ -2636,18 +2636,18 @@ Texture2D GenTextureIrradiance(Shader shader, Texture2D cubemap, int size) glBindRenderbuffer(GL_RENDERBUFFER, rbo); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, size, size); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo); - + // Create an irradiance cubemap, and re-scale capture FBO to irradiance scale glGenTextures(1, &irradiance.id); glBindTexture(GL_TEXTURE_CUBE_MAP, irradiance.id); - for (unsigned int i = 0; i < 6; i++) + for (unsigned int i = 0; i < 6; i++) glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, size, size, 0, GL_RGB, GL_FLOAT, NULL); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - + // Create projection (transposed) and different views for each face Matrix fboProjection = MatrixPerspective(90.0*DEG2RAD, 1.0, 0.01, 1000.0); //MatrixTranspose(&fboProjection); @@ -2680,7 +2680,7 @@ Texture2D GenTextureIrradiance(Shader shader, Texture2D cubemap, int size) // Unbind framebuffer and textures glBindFramebuffer(GL_FRAMEBUFFER, 0); - + // Reset viewport dimensions to default glViewport(0, 0, screenWidth, screenHeight); @@ -2695,13 +2695,13 @@ Texture2D GenTextureIrradiance(Shader shader, Texture2D cubemap, int size) Texture2D GenTexturePrefilter(Shader shader, Texture2D cubemap, int size) { Texture2D prefilter = { 0 }; - + #if defined(GRAPHICS_API_OPENGL_33) // || defined(GRAPHICS_API_OPENGL_ES2) // NOTE: SetShaderDefaultLocations() already setups locations for projection and view Matrix in shader // Other locations should be setup externally in shader before calling the function // TODO: Locations should be taken out of this function... too shader dependant... int roughnessLoc = GetShaderLocation(shader, "roughness"); - + // Setup framebuffer unsigned int fbo, rbo; glGenFramebuffers(1, &fbo); @@ -2710,11 +2710,11 @@ Texture2D GenTexturePrefilter(Shader shader, Texture2D cubemap, int size) glBindRenderbuffer(GL_RENDERBUFFER, rbo); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, size, size); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo); - + // Create a prefiltered HDR environment map glGenTextures(1, &prefilter.id); glBindTexture(GL_TEXTURE_CUBE_MAP, prefilter.id); - for (unsigned int i = 0; i < 6; i++) + for (unsigned int i = 0; i < 6; i++) glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, size, size, 0, GL_RGB, GL_FLOAT, NULL); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); @@ -2724,7 +2724,7 @@ Texture2D GenTexturePrefilter(Shader shader, Texture2D cubemap, int size) // Generate mipmaps for the prefiltered HDR texture glGenerateMipmap(GL_TEXTURE_CUBE_MAP); - + // Create projection (transposed) and different views for each face Matrix fboProjection = MatrixPerspective(90.0*DEG2RAD, 1.0, 0.01, 1000.0); //MatrixTranspose(&fboProjection); @@ -2744,7 +2744,7 @@ Texture2D GenTexturePrefilter(Shader shader, Texture2D cubemap, int size) SetShaderValueMatrix(shader, shader.locs[LOC_MATRIX_PROJECTION], fboProjection); glBindFramebuffer(GL_FRAMEBUFFER, fbo); - + #define MAX_MIPMAP_LEVELS 5 // Max number of prefilter texture mipmaps for (unsigned int mip = 0; mip < MAX_MIPMAP_LEVELS; mip++) @@ -2752,7 +2752,7 @@ Texture2D GenTexturePrefilter(Shader shader, Texture2D cubemap, int size) // Resize framebuffer according to mip-level size. unsigned int mipWidth = size*powf(0.5f, mip); unsigned int mipHeight = size*powf(0.5f, mip); - + glBindRenderbuffer(GL_RENDERBUFFER, rbo); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, mipWidth, mipHeight); glViewport(0, 0, mipWidth, mipHeight); @@ -2771,7 +2771,7 @@ Texture2D GenTexturePrefilter(Shader shader, Texture2D cubemap, int size) // Unbind framebuffer and textures glBindFramebuffer(GL_FRAMEBUFFER, 0); - + // Reset viewport dimensions to default glViewport(0, 0, screenWidth, screenHeight); @@ -2804,7 +2804,7 @@ Texture2D GenTextureBRDF(Shader shader, Texture2D cubemap, int size) glBindRenderbuffer(GL_RENDERBUFFER, rbo); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, size, size); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, brdf.id, 0); - + glViewport(0, 0, size, size); glUseProgram(shader.id); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -2812,10 +2812,10 @@ Texture2D GenTextureBRDF(Shader shader, Texture2D cubemap, int size) // Unbind framebuffer and textures glBindFramebuffer(GL_FRAMEBUFFER, 0); - + // Reset viewport dimensions to default glViewport(0, 0, screenWidth, screenHeight); - + brdf.width = size; brdf.height = size; #endif @@ -2853,7 +2853,7 @@ void EndBlendMode(void) VrDeviceInfo GetVrDeviceInfo(int vrDeviceType) { VrDeviceInfo hmd = { 0 }; // Current VR device info - + switch (vrDeviceType) { case HMD_DEFAULT_DEVICE: @@ -2881,7 +2881,7 @@ VrDeviceInfo GetVrDeviceInfo(int vrDeviceType) hmd.chromaAbCorrection[1] = -0.004f; // HMD chromatic aberration correction parameter 1 hmd.chromaAbCorrection[2] = 1.014f; // HMD chromatic aberration correction parameter 2 hmd.chromaAbCorrection[3] = 0.0f; // HMD chromatic aberration correction parameter 3 - + TraceLog(LOG_INFO, "Initializing VR Simulator (Oculus Rift CV1)"); } break; case HMD_OCULUS_RIFT_DK2: @@ -2903,9 +2903,9 @@ VrDeviceInfo GetVrDeviceInfo(int vrDeviceType) hmd.chromaAbCorrection[1] = -0.004f; // HMD chromatic aberration correction parameter 1 hmd.chromaAbCorrection[2] = 1.014f; // HMD chromatic aberration correction parameter 2 hmd.chromaAbCorrection[3] = 0.0f; // HMD chromatic aberration correction parameter 3 - + TraceLog(LOG_INFO, "Initializing VR Simulator (Oculus Rift DK2)"); - } break; + } break; case HMD_OCULUS_GO: { // TODO: Provide device display and lens parameters @@ -2920,7 +2920,7 @@ VrDeviceInfo GetVrDeviceInfo(int vrDeviceType) } default: break; } - + return hmd; } @@ -2932,12 +2932,12 @@ void InitVrSimulator(VrDeviceInfo info) // Initialize framebuffer and textures for stereo rendering // NOTE: Screen size should match HMD aspect ratio vrConfig.stereoFbo = rlLoadRenderTexture(screenWidth, screenHeight); - + #if defined(SUPPORT_DISTORTION_SHADER) // Load distortion shader unsigned int vertexShaderId = CompileShader(distortionVShaderStr, GL_VERTEX_SHADER); unsigned int fragmentShaderId = CompileShader(distortionFShaderStr, GL_FRAGMENT_SHADER); - + vrConfig.distortionShader.id = LoadShaderProgram(vertexShaderId, fragmentShaderId); if (vrConfig.distortionShader.id > 0) SetShaderDefaultLocations(&vrConfig.distortionShader); #endif @@ -2997,7 +2997,7 @@ void ToggleVrMode(void) if (!vrSimulatorReady) { vrStereoRender = false; - + // Reset viewport and default projection-modelview matrices rlViewport(0, 0, screenWidth, screenHeight); projection = MatrixOrtho(0.0, screenWidth, screenHeight, 0.0, 0.0, 1.0); @@ -3031,7 +3031,7 @@ void BeginVrDrawing(void) //glViewport(0, 0, buffer.width, buffer.height); // Useful if rendering to separate framebuffers (every eye) rlClearScreenBuffers(); // Clear current framebuffer(s) - + vrStereoRender = true; } #endif @@ -3044,7 +3044,7 @@ void EndVrDrawing(void) if (vrSimulatorReady) { vrStereoRender = false; // Disable stereo render - + rlDisableRenderTexture(); // Unbind current framebuffer rlClearScreenBuffers(); // Clear current framebuffer @@ -3096,7 +3096,7 @@ void EndVrDrawing(void) // Update and draw render texture fbo with distortion to backbuffer UpdateBuffersDefault(); DrawBuffersDefault(); - + // Restore defaultShader currentShader = defaultShader; @@ -3104,7 +3104,7 @@ void EndVrDrawing(void) rlViewport(0, 0, screenWidth, screenHeight); projection = MatrixOrtho(0.0, screenWidth, screenHeight, 0.0, 0.0, 1.0); modelview = MatrixIdentity(); - + rlDisableDepthTest(); } #endif @@ -3216,7 +3216,7 @@ static unsigned int LoadShaderProgram(unsigned int vShaderId, unsigned int fShad static Shader LoadShaderDefault(void) { Shader shader = { 0 }; - + // NOTE: All locations must be reseted to -1 (no location) for (int i = 0; i < MAX_SHADER_LOCATIONS; i++) shader.locs[i] = -1; @@ -3282,10 +3282,10 @@ static Shader LoadShaderDefault(void) // NOTE: Compiled vertex/fragment shaders are kept for re-use defaultVShaderId = CompileShader(defaultVShaderStr, GL_VERTEX_SHADER); // Compile default vertex shader defaultFShaderId = CompileShader(defaultFShaderStr, GL_FRAGMENT_SHADER); // Compile default fragment shader - + shader.id = LoadShaderProgram(defaultVShaderId, defaultFShaderId); - if (shader.id > 0) + if (shader.id > 0) { TraceLog(LOG_INFO, "[SHDR ID %i] Default shader loaded successfully", shader.id); @@ -3298,7 +3298,7 @@ static Shader LoadShaderDefault(void) shader.locs[LOC_MATRIX_MVP] = glGetUniformLocation(shader.id, "mvp"); shader.locs[LOC_COLOR_DIFFUSE] = glGetUniformLocation(shader.id, "colDiffuse"); shader.locs[LOC_MAP_DIFFUSE] = glGetUniformLocation(shader.id, "texture0"); - + // NOTE: We could also use below function but in case DEFAULT_ATTRIB_* points are // changed for external custom shaders, we just use direct bindings above //SetShaderDefaultLocations(&shader); @@ -3349,7 +3349,7 @@ static void UnloadShaderDefault(void) glDetachShader(defaultShader.id, defaultFShaderId); glDeleteShader(defaultVShaderId); glDeleteShader(defaultFShaderId); - + glDeleteProgram(defaultShader.id); } @@ -3601,7 +3601,7 @@ static void DrawBuffersDefault(void) { Matrix matProjection = projection; Matrix matModelView = modelview; - + int eyesCount = 1; #if defined(SUPPORT_VR_SIMULATOR) if (vrStereoRender) eyesCount = 2; @@ -3825,7 +3825,7 @@ static void GenDrawQuad(void) { unsigned int quadVAO = 0; unsigned int quadVBO = 0; - + float vertices[] = { // Positions // Texture Coords -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, @@ -3853,7 +3853,7 @@ static void GenDrawQuad(void) glBindVertexArray(quadVAO); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glBindVertexArray(0); - + glDeleteBuffers(1, &quadVBO); glDeleteVertexArrays(1, &quadVAO); } @@ -3926,7 +3926,7 @@ static void GenDrawCube(void) glBindVertexArray(cubeVAO); glDrawArrays(GL_TRIANGLES, 0, 36); glBindVertexArray(0); - + glDeleteBuffers(1, &cubeVBO); glDeleteVertexArrays(1, &cubeVAO); } @@ -3948,7 +3948,7 @@ static void SetStereoConfig(VrDeviceInfo hmd) // Compute distortion scale parameters // NOTE: To get lens max radius, lensShift must be normalized to [-1..1] - float lensRadius = fabsf(-1.0f - 4.0f*lensShift); + float lensRadius = fabs(-1.0f - 4.0f*lensShift); float lensRadiusSq = lensRadius*lensRadius; float distortionScale = hmd.lensDistortionValues[0] + hmd.lensDistortionValues[1]*lensRadiusSq + @@ -4031,7 +4031,7 @@ static void GetGlFormats(int format, int *glInternalFormat, int *glFormat, int * *glInternalFormat = -1; *glFormat = -1; *glType = -1; - + switch (format) { #if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_21) || defined(GRAPHICS_API_OPENGL_ES2) @@ -2,10 +2,10 @@ * * rlgl - raylib OpenGL abstraction layer * -* rlgl is a wrapper for multiple OpenGL versions (1.1, 2.1, 3.3 Core, ES 2.0) to -* pseudo-OpenGL 1.1 style functions (rlVertex, rlTranslate, rlRotate...). +* rlgl is a wrapper for multiple OpenGL versions (1.1, 2.1, 3.3 Core, ES 2.0) to +* pseudo-OpenGL 1.1 style functions (rlVertex, rlTranslate, rlRotate...). * -* When chosing an OpenGL version greater than OpenGL 1.1, rlgl stores vertex data on internal +* When chosing an OpenGL version greater than OpenGL 1.1, rlgl stores vertex data on internal * VBO buffers (and VAOs if available). It requires calling 3 functions: * rlglInit() - Initialize internal buffers and auxiliar resources * rlglDraw() - Process internal buffers and send required draw calls @@ -18,7 +18,7 @@ * #define GRAPHICS_API_OPENGL_33 * #define GRAPHICS_API_OPENGL_ES2 * Use selected OpenGL graphics backend, should be supported by platform -* Those preprocessor defines are only used on rlgl module, if OpenGL version is +* Those preprocessor defines are only used on rlgl module, if OpenGL version is * required by any other module, use rlGetVersion() tocheck it * * #define RLGL_STANDALONE @@ -124,7 +124,7 @@ #define RL_WRAP_CLAMP_MIRROR 0x8742 // GL_MIRROR_CLAMP_EXT // Matrix modes (equivalent to OpenGL) -#define RL_MODELVIEW 0x1700 // GL_MODELVIEW +#define RL_MODELVIEW 0x1700 // GL_MODELVIEW #define RL_PROJECTION 0x1701 // GL_PROJECTION #define RL_TEXTURE 0x1702 // GL_TEXTURE @@ -153,7 +153,7 @@ typedef unsigned char byte; unsigned char b; unsigned char a; } Color; - + // Rectangle type typedef struct Rectangle { int x; @@ -161,7 +161,7 @@ typedef unsigned char byte; int width; int height; } Rectangle; - + // Texture2D type // NOTE: Data stored in GPU memory typedef struct Texture2D { @@ -194,11 +194,11 @@ typedef unsigned char byte; unsigned int vaoId; // OpenGL Vertex Array Object id unsigned int vboId[7]; // OpenGL Vertex Buffer Objects id (7 types of vertex data) } Mesh; - + // Shader and material limits #define MAX_SHADER_LOCATIONS 32 #define MAX_MATERIAL_MAPS 12 - + // Shader type (generic) typedef struct Shader { unsigned int id; // Shader program id @@ -226,7 +226,7 @@ typedef unsigned char byte; Vector3 up; // Camera up vector (rotation over its axis) float fovy; // Camera field-of-view apperture in Y (degrees) } Camera; - + // Head-Mounted-Display device parameters typedef struct VrDeviceInfo { int hResolution; // HMD horizontal resolution in pixels @@ -240,16 +240,16 @@ typedef unsigned char byte; float lensDistortionValues[4]; // HMD lens distortion constant parameters float chromaAbCorrection[4]; // HMD chromatic aberration correction parameters } VrDeviceInfo; - + // TraceLog message types - typedef enum { - LOG_INFO = 0, - LOG_ERROR, - LOG_WARNING, - LOG_DEBUG, - LOG_OTHER + typedef enum { + LOG_INFO = 0, + LOG_ERROR, + LOG_WARNING, + LOG_DEBUG, + LOG_OTHER } TraceLogType; - + // Texture formats (support depends on OpenGL version) typedef enum { UNCOMPRESSED_GRAYSCALE = 1, // 8 bit per pixel (no alpha) @@ -278,7 +278,7 @@ typedef unsigned char byte; // Texture parameters: filter mode // NOTE 1: Filtering considers mipmaps if available in the texture // NOTE 2: Filter is accordingly set for minification and magnification - typedef enum { + typedef enum { FILTER_POINT = 0, // No filter, just pixel aproximation FILTER_BILINEAR, // Linear filtering FILTER_TRILINEAR, // Trilinear filtering (linear with mipmaps) @@ -286,19 +286,19 @@ typedef unsigned char byte; FILTER_ANISOTROPIC_8X, // Anisotropic filtering 8x FILTER_ANISOTROPIC_16X, // Anisotropic filtering 16x } TextureFilterMode; - + // Texture parameters: wrap mode - typedef enum { - WRAP_REPEAT = 0, - WRAP_CLAMP, - WRAP_MIRROR + typedef enum { + WRAP_REPEAT = 0, + WRAP_CLAMP, + WRAP_MIRROR } TextureWrapMode; // Color blending modes (pre-defined) - typedef enum { - BLEND_ALPHA = 0, - BLEND_ADDITIVE, - BLEND_MULTIPLIED + typedef enum { + BLEND_ALPHA = 0, + BLEND_ADDITIVE, + BLEND_MULTIPLIED } BlendMode; // Shader location point type @@ -465,7 +465,7 @@ void SetShaderValuei(Shader shader, int uniformLoc, const int *value, int size); void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat); // Set shader uniform value (matrix 4x4) void SetMatrixProjection(Matrix proj); // Set a custom projection matrix (replaces internal projection matrix) void SetMatrixModelview(Matrix view); // Set a custom modelview matrix (replaces internal modelview matrix) -Matrix GetMatrixModelview(); // Get internal modelview matrix +Matrix GetMatrixModelview(); // Get internal modelview matrix // Texture maps generation (PBR) diff --git a/src/shapes.c b/src/shapes.c index dc547e0d..604dcb87 100644 --- a/src/shapes.c +++ b/src/shapes.c @@ -648,8 +648,8 @@ bool CheckCollisionRecs(Rectangle rec1, Rectangle rec2) { bool collision = false; - float dx = fabsf((rec1.x + rec1.width/2) - (rec2.x + rec2.width/2)); - float dy = fabsf((rec1.y + rec1.height/2) - (rec2.y + rec2.height/2)); + float dx = fabs((rec1.x + rec1.width/2) - (rec2.x + rec2.width/2)); + float dy = fabs((rec1.y + rec1.height/2) - (rec2.y + rec2.height/2)); if ((dx <= (rec1.width/2 + rec2.width/2)) && ((dy <= (rec1.height/2 + rec2.height/2)))) collision = true; @@ -678,8 +678,8 @@ bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec) int recCenterX = rec.x + rec.width/2; int recCenterY = rec.y + rec.height/2; - float dx = fabsf(center.x - recCenterX); - float dy = fabsf(center.y - recCenterY); + float dx = fabs(center.x - recCenterX); + float dy = fabs(center.y - recCenterY); if (dx > (rec.width/2.0f + radius)) { return false; } if (dy > (rec.height/2.0f + radius)) { return false; } @@ -700,8 +700,8 @@ Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2) if (CheckCollisionRecs(rec1, rec2)) { - float dxx = fabsf(rec1.x - rec2.x); - float dyy = fabsf(rec1.y - rec2.y); + float dxx = fabs(rec1.x - rec2.x); + float dyy = fabs(rec1.y - rec2.y); if (rec1.x <= rec2.x) { @@ -47,16 +47,14 @@ #include "utils.h" // Required for: fopen() Android mapping #if defined(SUPPORT_FILEFORMAT_TTF) - // Following libs are used on LoadTTF() - #define STBTT_STATIC // Define stb_truetype functions static to this module + #define STB_RECT_PACK_IMPLEMENTATION + #include "external/stb_rect_pack.h" // Required for: ttf font rectangles packaging + + #define STBTT_STATIC #define STB_TRUETYPE_IMPLEMENTATION - #include "external/stb_truetype.h" // Required for: stbtt_BakeFontBitmap() + #include "external/stb_truetype.h" // Required for: ttf font data reading #endif -// Rectangle packing functions (not used at the moment) -//#define STB_RECT_PACK_IMPLEMENTATION -//#include "stb_rect_pack.h" - //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- @@ -89,7 +87,7 @@ static Font LoadImageFont(Image image, Color key, int firstChar); // Load a Imag static Font LoadBMFont(const char *fileName); // Load a BMFont file (AngelCode font file) #endif #if defined(SUPPORT_FILEFORMAT_TTF) -static Font LoadTTF(const char *fileName, int fontSize, int charsCount, int *fontChars); // Load spritefont from TTF data +//static Font LoadTTF(const char *fileName, int fontSize, int charsCount, int *fontChars); // Load spritefont from TTF data #endif #if defined(SUPPORT_DEFAULT_FONT) @@ -276,32 +274,40 @@ Font LoadFont(const char *fileName) // Default hardcoded values for ttf file loading #define DEFAULT_TTF_FONTSIZE 32 // Font first character (32 - space) #define DEFAULT_TTF_NUMCHARS 95 // ASCII 32..126 is 95 glyphs - #define DEFAULT_FIRST_CHAR 32 // Expected first char for image spritefont + #define DEFAULT_FIRST_CHAR 32 // Expected first char for image sprite font - Font spriteFont = { 0 }; + Font font = { 0 }; #if defined(SUPPORT_FILEFORMAT_TTF) - if (IsFileExtension(fileName, ".ttf")) spriteFont = LoadFontEx(fileName, DEFAULT_TTF_FONTSIZE, 0, NULL); + if (IsFileExtension(fileName, ".ttf")) + { + font.baseSize = DEFAULT_TTF_FONTSIZE; + font.charsCount = DEFAULT_TTF_NUMCHARS; + font.chars = LoadFontData(fileName, font.baseSize, NULL, font.charsCount, false); + Image atlas = GenImageFontAtlas(font.chars, font.charsCount, font.baseSize, 4, 0); + font.texture = LoadTextureFromImage(atlas); + UnloadImage(atlas); + } else #endif #if defined(SUPPORT_FILEFORMAT_FNT) - if (IsFileExtension(fileName, ".fnt")) spriteFont = LoadBMFont(fileName); + if (IsFileExtension(fileName, ".fnt")) font = LoadBMFont(fileName); else #endif { Image image = LoadImage(fileName); - if (image.data != NULL) spriteFont = LoadImageFont(image, MAGENTA, DEFAULT_FIRST_CHAR); + if (image.data != NULL) font = LoadImageFont(image, MAGENTA, DEFAULT_FIRST_CHAR); UnloadImage(image); } - if (spriteFont.texture.id == 0) + if (font.texture.id == 0) { TraceLog(LOG_WARNING, "[%s] Font could not be loaded, using default font", fileName); - spriteFont = GetDefaultFont(); + font = GetDefaultFont(); } - else SetTextureFilter(spriteFont.texture, FILTER_POINT); // By default we set point filter (best performance) + else SetTextureFilter(font.texture, FILTER_POINT); // By default we set point filter (best performance) - return spriteFont; + return font; } // Load Font from TTF font file with generation parameters @@ -309,31 +315,212 @@ Font LoadFont(const char *fileName) // if array is NULL, default char set is selected 32..126 Font LoadFontEx(const char *fileName, int fontSize, int charsCount, int *fontChars) { - Font spriteFont = { 0 }; - int totalChars = 95; // Default charset [32..126] + Font font = { 0 }; + + font.baseSize = fontSize; + font.charsCount = (charsCount > 0) ? charsCount : 95; + font.chars = LoadFontData(fileName, font.baseSize, fontChars, font.charsCount, false); + Image atlas = GenImageFontAtlas(font.chars, font.charsCount, font.baseSize, 0, 0); + font.texture = LoadTextureFromImage(atlas); + UnloadImage(atlas); + + return font; +} -#if defined(SUPPORT_FILEFORMAT_TTF) - if (IsFileExtension(fileName, ".ttf")) +// Load font data for further use +// NOTE: Requires TTF font and can generate SDF data +CharInfo *LoadFontData(const char *fileName, int fontSize, int *fontChars, int charsCount, bool sdf) +{ + // NOTE: Using some SDF generation default values, + // trades off precision with ability to handle *smaller* sizes + #define SDF_CHAR_PADDING 4 + #define SDF_ON_EDGE_VALUE 128 + #define SDF_PIXEL_DIST_SCALE 64.0f + + CharInfo *chars = (CharInfo *)malloc(charsCount*sizeof(CharInfo)); + + // Load font data (including pixel data) from TTF file + // NOTE: Loaded information should be enough to generate font image atlas, + // using any packaging method + FILE *fontFile = fopen(fileName, "rb"); // Load font file + + fseek(fontFile, 0, SEEK_END); + long size = ftell(fontFile); // Get file size + fseek(fontFile, 0, SEEK_SET); // Reset file pointer + + unsigned char *fontBuffer = (unsigned char *)malloc(size); + + fread(fontBuffer, size, 1, fontFile); + fclose(fontFile); + + // Init font for data reading + stbtt_fontinfo fontInfo; + if (!stbtt_InitFont(&fontInfo, fontBuffer, 0)) TraceLog(LOG_WARNING, "Failed to init font!"); + + // Calculate font scale factor + float scaleFactor = stbtt_ScaleForPixelHeight(&fontInfo, fontSize); + + // Calculate font basic metrics + // NOTE: ascent is equivalent to font baseline + int ascent, descent, lineGap; + stbtt_GetFontVMetrics(&fontInfo, &ascent, &descent, &lineGap); + ascent *= scaleFactor; + descent *= scaleFactor; + + // Fill fontChars in case not provided externally + // NOTE: By default we fill charsCount consecutevely, starting at 32 (Space) + int genFontChars = false; + if (fontChars == NULL) genFontChars = true; + if (genFontChars) { - if (charsCount != 0) totalChars = charsCount; + fontChars = (int *)malloc(charsCount*sizeof(int)); + for (int i = 0; i < charsCount; i++) fontChars[i] = i + 32; + } + + // NOTE: Using simple packaging, one char after another + for (int i = 0; i < charsCount; i++) + { + int chw = 0, chh = 0; // Character width and height (on generation) + int ch = fontChars[i]; // Character value to get info for + chars[i].value = ch; + + // Render a unicode codepoint to a bitmap + // stbtt_GetCodepointBitmap() -- allocates and returns a bitmap + // stbtt_GetCodepointBitmapBox() -- how big the bitmap must be + // stbtt_MakeCodepointBitmap() -- renders into bitmap you provide + + if (!sdf) chars[i].data = stbtt_GetCodepointBitmap(&fontInfo, scaleFactor, scaleFactor, ch, &chw, &chh, &chars[i].offsetX, &chars[i].offsetY); + else if (ch != 32) chars[i].data = stbtt_GetCodepointSDF(&fontInfo, scaleFactor, ch, SDF_CHAR_PADDING, SDF_ON_EDGE_VALUE, SDF_PIXEL_DIST_SCALE, &chw, &chh, &chars[i].offsetX, &chars[i].offsetY); + + chars[i].rec.width = (float)chw; + chars[i].rec.height = (float)chh; + chars[i].offsetY += ascent; + + // Get bounding box for character (may be offset to account for chars that dip above or below the line) + int chX1, chY1, chX2, chY2; + stbtt_GetCodepointBitmapBox(&fontInfo, ch, scaleFactor, scaleFactor, &chX1, &chY1, &chX2, &chY2); + + TraceLog(LOG_DEBUG, "Character box measures: %i, %i, %i, %i", chX1, chY1, chX2 - chX1, chY2 - chY1); + TraceLog(LOG_DEBUG, "Character offsetY: %i", ascent + chY1); + + stbtt_GetCodepointHMetrics(&fontInfo, ch, &chars[i].advanceX, NULL); + chars[i].advanceX *= scaleFactor; + } + + free(fontBuffer); + if (genFontChars) free(fontChars); + + return chars; +} + +// Generate image font atlas using chars info +// NOTE: Packing method: 0-Default, 1-Skyline +Image GenImageFontAtlas(CharInfo *chars, int charsCount, int fontSize, int padding, int packMethod) +{ + Image atlas = { 0 }; + + // Calculate texture size based on required pixel area + // NOTE: Texture is forced to be squared and POT + float requiredArea = 0; + for (int i = 0; i < charsCount; i++) requiredArea += ((chars[i].rec.width + 2*padding)*(chars[i].rec.height + 2*padding)); + float guessSize = sqrtf(requiredArea)*1.25f; + int textureSize = (int)powf(2, ceilf(logf((float)guessSize)/logf(2))); // Calculate next POT + + atlas.width = textureSize; // Atlas bitmap width + atlas.height = textureSize; // Atlas bitmap height + atlas.data = (unsigned char *)calloc(1, atlas.width*atlas.height); // Create a bitmap to store characters (8 bpp) + atlas.format = UNCOMPRESSED_GRAYSCALE; + atlas.mipmaps = 1; + + if (packMethod == 0) // Use basic packing algorythm + { + int offsetX = padding; + int offsetY = padding; - if (fontChars == NULL) + // NOTE: Using simple packaging, one char after another + for (int i = 0; i < charsCount; i++) { - fontChars = (int *)malloc(totalChars*sizeof(int)); - for (int i = 0; i < totalChars; i++) fontChars[i] = i + 32; // Default first character: SPACE[32] + // Copy pixel data from fc.data to atlas + for (int y = 0; y < (int)chars[i].rec.height; y++) + { + for (int x = 0; x < (int)chars[i].rec.width; x++) + { + ((unsigned char *)atlas.data)[(offsetY + y)*atlas.width + (offsetX + x)] = chars[i].data[y*(int)chars[i].rec.width + x]; + } + } + + chars[i].rec.x = offsetX; + chars[i].rec.y = offsetY; + + // Move atlas position X for next character drawing + offsetX += ((int)chars[i].advanceX + 2*padding); + + if (offsetX >= (atlas.width - (int)chars[i].rec.width - padding)) + { + offsetX = padding; + offsetY += (fontSize + 2*padding); + + if (offsetY > (atlas.height - fontSize - padding)) break; + } } + } + else if (packMethod == 1) // Use Skyline rect packing algorythm (stb_pack_rect) + { + stbrp_context *context = (stbrp_context *)malloc(sizeof(*context)); + stbrp_node *nodes = (stbrp_node *)malloc(charsCount*sizeof(*nodes)); + + stbrp_init_target(context, atlas.width, atlas.height, nodes, charsCount); + stbrp_rect *rects = (stbrp_rect *)malloc(charsCount*sizeof(stbrp_rect)); - spriteFont = LoadTTF(fileName, fontSize, totalChars, fontChars); + // Fill rectangles for packaging + for (int i = 0; i < charsCount; i++) + { + rects[i].id = i; + rects[i].w = (int)chars[i].rec.width + 2*padding; + rects[i].h = (int)chars[i].rec.height + 2*padding; + } + + // Package rectangles into atlas + stbrp_pack_rects(context, rects, charsCount); + + for (int i = 0; i < charsCount; i++) + { + chars[i].rec.x = rects[i].x + padding; + chars[i].rec.y = rects[i].y + padding; + + if (rects[i].was_packed) + { + // Copy pixel data from fc.data to atlas + for (int y = 0; y < (int)chars[i].rec.height; y++) + { + for (int x = 0; x < (int)chars[i].rec.width; x++) + { + ((unsigned char *)atlas.data)[(rects[i].y + padding + y)*atlas.width + (rects[i].x + padding + x)] = chars[i].data[y*(int)chars[i].rec.width + x]; + } + } + } + else TraceLog(LOG_WARNING, "Character could not be packed: %i", i); + } + + free(nodes); + free(context); } -#endif + + // Convert image data from GRAYSCALE to GRAY_ALPHA + // WARNING: ImageAlphaMask(&atlas, atlas) does not work in this case, requires manual operation + unsigned char *dataGrayAlpha = (unsigned char *)malloc(textureSize*textureSize*sizeof(unsigned char)*2); // Two channels - if (spriteFont.texture.id == 0) + for (int i = 0, k = 0; i < atlas.width*atlas.height; i++, k += 2) { - TraceLog(LOG_WARNING, "[%s] Font could not be generated, using default font", fileName); - spriteFont = GetDefaultFont(); + dataGrayAlpha[k] = 255; + dataGrayAlpha[k + 1] = ((unsigned char *)atlas.data)[i]; } - return spriteFont; + free(atlas.data); + atlas.data = dataGrayAlpha; + atlas.format = UNCOMPRESSED_GRAY_ALPHA; + + return atlas; } // Unload Font from GPU memory (VRAM) @@ -807,108 +994,4 @@ static Font LoadBMFont(const char *fileName) return font; } -#endif - -#if defined(SUPPORT_FILEFORMAT_TTF) -// Generate a sprite font from TTF file data (font size required) -// TODO: Review texture packing method and generation (use oversampling) -static Font LoadTTF(const char *fileName, int fontSize, int charsCount, int *fontChars) -{ - #define MAX_TTF_SIZE 16 // Maximum ttf file size in MB - - // NOTE: Font texture size is predicted (being as much conservative as possible) - // Predictive method consist of supposing same number of chars by line-column (sqrtf) - // and a maximum character width of 3/4 of fontSize... it worked ok with all my tests... - - // Calculate next power-of-two value - float guessSize = ceilf((float)fontSize*3/4)*ceilf(sqrtf((float)charsCount)); - int textureSize = (int)powf(2, ceilf(logf((float)guessSize)/logf(2))); // Calculate next POT - - TraceLog(LOG_INFO, "TTF spritefont loading: Predicted texture size: %ix%i", textureSize, textureSize); - - unsigned char *ttfBuffer = (unsigned char *)malloc(MAX_TTF_SIZE*1024*1024); - unsigned char *dataBitmap = (unsigned char *)malloc(textureSize*textureSize*sizeof(unsigned char)); // One channel bitmap returned! - stbtt_bakedchar *charData = (stbtt_bakedchar *)malloc(sizeof(stbtt_bakedchar)*charsCount); - - Font font = { 0 }; - - FILE *ttfFile = fopen(fileName, "rb"); - - if (ttfFile == NULL) - { - TraceLog(LOG_WARNING, "[%s] TTF file could not be opened", fileName); - return font; - } - - // NOTE: We try reading up to 16 MB of elements of 1 byte - fread(ttfBuffer, 1, MAX_TTF_SIZE*1024*1024, ttfFile); - - // Find font baseline (vertical origin of the font) - // NOTE: This value is required because y-offset depends on it! - stbtt_fontinfo fontInfo; - int ascent, baseline; - float scale; - - stbtt_InitFont(&fontInfo, ttfBuffer, 0); - scale = stbtt_ScaleForPixelHeight(&fontInfo, fontSize); - stbtt_GetFontVMetrics(&fontInfo, &ascent, 0, 0); - baseline = (int)(ascent*scale); - - if (fontChars[0] != 32) TraceLog(LOG_WARNING, "TTF spritefont loading: first character is not SPACE(32) character"); - - // NOTE: Using stb_truetype crappy packing method, no guarantee the font fits the image... - // TODO: Replace this function by a proper packing method and support random chars order, - // we already receive a list (fontChars) with the ordered expected characters - int result = stbtt_BakeFontBitmap(ttfBuffer, 0, fontSize, dataBitmap, textureSize, textureSize, fontChars[0], charsCount, charData); - - //if (result > 0) TraceLog(LOG_INFO, "TTF spritefont loading: first unused row of generated bitmap: %i", result); - if (result < 0) TraceLog(LOG_WARNING, "TTF spritefont loading: Not all the characters fit in the font"); - - free(ttfBuffer); - - // Convert image data from grayscale to to UNCOMPRESSED_GRAY_ALPHA - unsigned char *dataGrayAlpha = (unsigned char *)malloc(textureSize*textureSize*sizeof(unsigned char)*2); // Two channels - - for (int i = 0, k = 0; i < textureSize*textureSize; i++, k += 2) - { - dataGrayAlpha[k] = 0xff; - dataGrayAlpha[k + 1] = dataBitmap[i]; - } - - free(dataBitmap); - - // Sprite font generation from TTF extracted data - Image image; - image.width = textureSize; - image.height = textureSize; - image.mipmaps = 1; - image.format = UNCOMPRESSED_GRAY_ALPHA; - image.data = dataGrayAlpha; - font.texture = LoadTextureFromImage(image); // Load image into texture - UnloadImage(image); // Unloads image data (dataGrayAlpha) - - - // Fill font characters info data - font.baseSize = fontSize; - font.charsCount = charsCount; - font.chars = (CharInfo *)malloc(font.charsCount*sizeof(CharInfo)); - - for (int i = 0; i < font.charsCount; i++) - { - font.chars[i].value = fontChars[i]; - - font.chars[i].rec.x = (int)charData[i].x0; - font.chars[i].rec.y = (int)charData[i].y0; - font.chars[i].rec.width = (int)charData[i].x1 - (int)charData[i].x0; - font.chars[i].rec.height = (int)charData[i].y1 - (int)charData[i].y0; - - font.chars[i].offsetX = charData[i].xoff; - font.chars[i].offsetY = baseline + charData[i].yoff; - font.chars[i].advanceX = (int)charData[i].xadvance; - } - - free(charData); - - return font; -} -#endif +#endif
\ No newline at end of file diff --git a/src/textures.c b/src/textures.c index 3a1934b9..29316a7a 100644 --- a/src/textures.c +++ b/src/textures.c @@ -405,87 +405,231 @@ void UnloadRenderTexture(RenderTexture2D target) } // Get pixel data from image in the form of Color struct array -// TODO: Support float pixel data retrieval Color *GetImageData(Image image) { Color *pixels = (Color *)malloc(image.width*image.height*sizeof(Color)); - for (int i = 0, k = 0; i < image.width*image.height; i++) + if (image.format >= COMPRESSED_DXT1_RGB) TraceLog(LOG_WARNING, "Pixel data retrieval not supported for compressed image formats"); + else { - switch (image.format) + if ((image.format == UNCOMPRESSED_R32) || + (image.format == UNCOMPRESSED_R32G32B32) || + (image.format == UNCOMPRESSED_R32G32B32A32)) TraceLog(LOG_WARNING, "32bit pixel format converted to 8bit per channel"); + + for (int i = 0, k = 0; i < image.width*image.height; i++) { - case UNCOMPRESSED_GRAYSCALE: + switch (image.format) { - pixels[i].r = ((unsigned char *)image.data)[i]; - pixels[i].g = ((unsigned char *)image.data)[i]; - pixels[i].b = ((unsigned char *)image.data)[i]; - pixels[i].a = 255; + case UNCOMPRESSED_GRAYSCALE: + { + pixels[i].r = ((unsigned char *)image.data)[i]; + pixels[i].g = ((unsigned char *)image.data)[i]; + pixels[i].b = ((unsigned char *)image.data)[i]; + pixels[i].a = 255; - } break; - case UNCOMPRESSED_GRAY_ALPHA: - { - pixels[i].r = ((unsigned char *)image.data)[k]; - pixels[i].g = ((unsigned char *)image.data)[k]; - pixels[i].b = ((unsigned char *)image.data)[k]; - pixels[i].a = ((unsigned char *)image.data)[k + 1]; - - k += 2; - } break; - case UNCOMPRESSED_R5G5B5A1: - { - unsigned short pixel = ((unsigned short *)image.data)[i]; + } break; + case UNCOMPRESSED_GRAY_ALPHA: + { + pixels[i].r = ((unsigned char *)image.data)[k]; + pixels[i].g = ((unsigned char *)image.data)[k]; + pixels[i].b = ((unsigned char *)image.data)[k]; + pixels[i].a = ((unsigned char *)image.data)[k + 1]; - pixels[i].r = (unsigned char)((float)((pixel & 0b1111100000000000) >> 11)*(255/31)); - pixels[i].g = (unsigned char)((float)((pixel & 0b0000011111000000) >> 6)*(255/31)); - pixels[i].b = (unsigned char)((float)((pixel & 0b0000000000111110) >> 1)*(255/31)); - pixels[i].a = (unsigned char)((pixel & 0b0000000000000001)*255); + k += 2; + } break; + case UNCOMPRESSED_R5G5B5A1: + { + unsigned short pixel = ((unsigned short *)image.data)[i]; - } break; - case UNCOMPRESSED_R5G6B5: - { - unsigned short pixel = ((unsigned short *)image.data)[i]; + pixels[i].r = (unsigned char)((float)((pixel & 0b1111100000000000) >> 11)*(255/31)); + pixels[i].g = (unsigned char)((float)((pixel & 0b0000011111000000) >> 6)*(255/31)); + pixels[i].b = (unsigned char)((float)((pixel & 0b0000000000111110) >> 1)*(255/31)); + pixels[i].a = (unsigned char)((pixel & 0b0000000000000001)*255); - pixels[i].r = (unsigned char)((float)((pixel & 0b1111100000000000) >> 11)*(255/31)); - pixels[i].g = (unsigned char)((float)((pixel & 0b0000011111100000) >> 5)*(255/63)); - pixels[i].b = (unsigned char)((float)(pixel & 0b0000000000011111)*(255/31)); - pixels[i].a = 255; + } break; + case UNCOMPRESSED_R5G6B5: + { + unsigned short pixel = ((unsigned short *)image.data)[i]; - } break; - case UNCOMPRESSED_R4G4B4A4: - { - unsigned short pixel = ((unsigned short *)image.data)[i]; + pixels[i].r = (unsigned char)((float)((pixel & 0b1111100000000000) >> 11)*(255/31)); + pixels[i].g = (unsigned char)((float)((pixel & 0b0000011111100000) >> 5)*(255/63)); + pixels[i].b = (unsigned char)((float)(pixel & 0b0000000000011111)*(255/31)); + pixels[i].a = 255; - pixels[i].r = (unsigned char)((float)((pixel & 0b1111000000000000) >> 12)*(255/15)); - pixels[i].g = (unsigned char)((float)((pixel & 0b0000111100000000) >> 8)*(255/15)); - pixels[i].b = (unsigned char)((float)((pixel & 0b0000000011110000) >> 4)*(255/15)); - pixels[i].a = (unsigned char)((float)(pixel & 0b0000000000001111)*(255/15)); + } break; + case UNCOMPRESSED_R4G4B4A4: + { + unsigned short pixel = ((unsigned short *)image.data)[i]; - } break; - case UNCOMPRESSED_R8G8B8A8: - { - pixels[i].r = ((unsigned char *)image.data)[k]; - pixels[i].g = ((unsigned char *)image.data)[k + 1]; - pixels[i].b = ((unsigned char *)image.data)[k + 2]; - pixels[i].a = ((unsigned char *)image.data)[k + 3]; - - k += 4; - } break; - case UNCOMPRESSED_R8G8B8: - { - pixels[i].r = (unsigned char)((unsigned char *)image.data)[k]; - pixels[i].g = (unsigned char)((unsigned char *)image.data)[k + 1]; - pixels[i].b = (unsigned char)((unsigned char *)image.data)[k + 2]; - pixels[i].a = 255; - - k += 3; - } break; - default: TraceLog(LOG_WARNING, "Format not supported for pixel data retrieval"); break; + pixels[i].r = (unsigned char)((float)((pixel & 0b1111000000000000) >> 12)*(255/15)); + pixels[i].g = (unsigned char)((float)((pixel & 0b0000111100000000) >> 8)*(255/15)); + pixels[i].b = (unsigned char)((float)((pixel & 0b0000000011110000) >> 4)*(255/15)); + pixels[i].a = (unsigned char)((float)(pixel & 0b0000000000001111)*(255/15)); + + } break; + case UNCOMPRESSED_R8G8B8A8: + { + pixels[i].r = ((unsigned char *)image.data)[k]; + pixels[i].g = ((unsigned char *)image.data)[k + 1]; + pixels[i].b = ((unsigned char *)image.data)[k + 2]; + pixels[i].a = ((unsigned char *)image.data)[k + 3]; + + k += 4; + } break; + case UNCOMPRESSED_R8G8B8: + { + pixels[i].r = (unsigned char)((unsigned char *)image.data)[k]; + pixels[i].g = (unsigned char)((unsigned char *)image.data)[k + 1]; + pixels[i].b = (unsigned char)((unsigned char *)image.data)[k + 2]; + pixels[i].a = 255; + + k += 3; + } break; + case UNCOMPRESSED_R32: + { + pixels[i].r = (unsigned char)(((float *)image.data)[k]*255.0f); + pixels[i].g = 0; + pixels[i].b = 0; + pixels[i].a = 255; + + } break; + case UNCOMPRESSED_R32G32B32: + { + pixels[i].r = (unsigned char)(((float *)image.data)[k]*255.0f); + pixels[i].g = (unsigned char)(((float *)image.data)[k + 1]*255.0f); + pixels[i].b = (unsigned char)(((float *)image.data)[k + 2]*255.0f); + pixels[i].a = 255; + + k += 3; + } + case UNCOMPRESSED_R32G32B32A32: + { + pixels[i].r = (unsigned char)(((float *)image.data)[k]*255.0f); + pixels[i].g = (unsigned char)(((float *)image.data)[k]*255.0f); + pixels[i].b = (unsigned char)(((float *)image.data)[k]*255.0f); + pixels[i].a = (unsigned char)(((float *)image.data)[k]*255.0f); + + k += 4; + } + default: break; + } } } return pixels; } +// Get pixel data from image as Vector4 array (float normalized) +Vector4 *GetImageDataNormalized(Image image) +{ + Vector4 *pixels = (Vector4 *)malloc(image.width*image.height*sizeof(Vector4)); + + if (image.format >= COMPRESSED_DXT1_RGB) TraceLog(LOG_WARNING, "Pixel data retrieval not supported for compressed image formats"); + else + { + for (int i = 0, k = 0; i < image.width*image.height; i++) + { + switch (image.format) + { + case UNCOMPRESSED_GRAYSCALE: + { + pixels[i].x = (float)((unsigned char *)image.data)[i]/255.0f; + pixels[i].y = (float)((unsigned char *)image.data)[i]/255.0f; + pixels[i].z = (float)((unsigned char *)image.data)[i]/255.0f; + pixels[i].w = 1.0f; + + } break; + case UNCOMPRESSED_GRAY_ALPHA: + { + pixels[i].x = (float)((unsigned char *)image.data)[k]/255.0f; + pixels[i].y = (float)((unsigned char *)image.data)[k]/255.0f; + pixels[i].z = (float)((unsigned char *)image.data)[k]/255.0f; + pixels[i].w = (float)((unsigned char *)image.data)[k + 1]/255.0f; + + k += 2; + } break; + case UNCOMPRESSED_R5G5B5A1: + { + unsigned short pixel = ((unsigned short *)image.data)[i]; + + pixels[i].x = (float)((pixel & 0b1111100000000000) >> 11)*(1.0f/31); + pixels[i].y = (float)((pixel & 0b0000011111000000) >> 6)*(1.0f/31); + pixels[i].z = (float)((pixel & 0b0000000000111110) >> 1)*(1.0f/31); + pixels[i].w = ((pixel & 0b0000000000000001) == 0) ? 0.0f : 1.0f; + + } break; + case UNCOMPRESSED_R5G6B5: + { + unsigned short pixel = ((unsigned short *)image.data)[i]; + + pixels[i].x = (float)((pixel & 0b1111100000000000) >> 11)*(1.0f/31); + pixels[i].y = (float)((pixel & 0b0000011111100000) >> 5)*(1.0f/63); + pixels[i].z = (float)(pixel & 0b0000000000011111)*(1.0f/31); + pixels[i].w = 1.0f; + + } break; + case UNCOMPRESSED_R4G4B4A4: + { + unsigned short pixel = ((unsigned short *)image.data)[i]; + + pixels[i].x = (float)((pixel & 0b1111000000000000) >> 12)*(1.0f/15); + pixels[i].y = (float)((pixel & 0b0000111100000000) >> 8)*(1.0f/15); + pixels[i].z = (float)((pixel & 0b0000000011110000) >> 4)*(1.0f/15); + pixels[i].w = (float)(pixel & 0b0000000000001111)*(1.0f/15); + + } break; + case UNCOMPRESSED_R8G8B8A8: + { + pixels[i].x = (float)((unsigned char *)image.data)[k]/255.0f; + pixels[i].y = (float)((unsigned char *)image.data)[k + 1]/255.0f; + pixels[i].z = (float)((unsigned char *)image.data)[k + 2]/255.0f; + pixels[i].w = (float)((unsigned char *)image.data)[k + 3]/255.0f; + + k += 4; + } break; + case UNCOMPRESSED_R8G8B8: + { + pixels[i].x = (float)((unsigned char *)image.data)[k]/255.0f; + pixels[i].y = (float)((unsigned char *)image.data)[k + 1]/255.0f; + pixels[i].z = (float)((unsigned char *)image.data)[k + 2]/255.0f; + pixels[i].w = 1.0f; + + k += 3; + } break; + case UNCOMPRESSED_R32: + { + pixels[i].x = ((float *)image.data)[k]; + pixels[i].y = 0.0f; + pixels[i].z = 0.0f; + pixels[i].w = 1.0f; + + } break; + case UNCOMPRESSED_R32G32B32: + { + pixels[i].x = ((float *)image.data)[k]; + pixels[i].y = ((float *)image.data)[k + 1]; + pixels[i].z = ((float *)image.data)[k + 2]; + pixels[i].w = 1.0f; + + k += 3; + } + case UNCOMPRESSED_R32G32B32A32: + { + pixels[i].x = ((float *)image.data)[k]; + pixels[i].y = ((float *)image.data)[k + 1]; + pixels[i].z = ((float *)image.data)[k + 2]; + pixels[i].w = ((float *)image.data)[k + 3]; + + k += 4; + } + default: break; + } + } + } + + return pixels; +} + // Get pixel data size in bytes (image or texture) // NOTE: Size depends on pixel format int GetPixelDataSize(int width, int height, int format) @@ -567,8 +711,10 @@ void ExportImage(const char *fileName, Image image) { // NOTE: Getting Color array as RGBA unsigned char values unsigned char *imgData = (unsigned char *)GetImageData(image); + + // NOTE: SavePNG() not supported by some platforms: PLATFORM_WEB, PLATFORM_ANDROID SavePNG(fileName, imgData, image.width, image.height, 4); - // FIXME ^ this fails on PLATFORM_WEB, what should we do? + free(imgData); } @@ -644,8 +790,7 @@ void ImageToPOT(Image *image, Color fillColor) int format = image->format; // Store image data format to reconvert later - // TODO: Image width and height changes... do we want to store new values or keep the old ones? - // NOTE: Issues when using image.width and image.height for sprite animations... + // NOTE: Image size changes, new width and height *image = LoadImageEx(pixelsPOT, potWidth, potHeight); free(pixelsPOT); // Free POT pixels data @@ -657,11 +802,11 @@ void ImageToPOT(Image *image, Color fillColor) // Convert image data to desired format void ImageFormat(Image *image, int newFormat) { - if (image->format != newFormat) + if ((newFormat != 0) && (image->format != newFormat)) { if ((image->format < COMPRESSED_DXT1_RGB) && (newFormat < COMPRESSED_DXT1_RGB)) { - Color *pixels = GetImageData(*image); + Vector4 *pixels = GetImageDataNormalized(*image); // Supports 8 to 32 bit per channel free(image->data); // WARNING! We loose mipmaps data --> Regenerated at the end... image->data = NULL; @@ -677,18 +822,18 @@ void ImageFormat(Image *image, int newFormat) for (int i = 0; i < image->width*image->height; i++) { - ((unsigned char *)image->data)[i] = (unsigned char)((float)pixels[i].r*0.299f + (float)pixels[i].g*0.587f + (float)pixels[i].b*0.114f); + ((unsigned char *)image->data)[i] = (unsigned char)((pixels[i].x*0.299f + pixels[i].y*0.587f + pixels[i].z*0.114f)*255.0f); } } break; case UNCOMPRESSED_GRAY_ALPHA: { - image->data = (unsigned char *)malloc(image->width*image->height*2*sizeof(unsigned char)); + image->data = (unsigned char *)malloc(image->width*image->height*2*sizeof(unsigned char)); - for (int i = 0; i < image->width*image->height*2; i += 2, k++) + for (int i = 0; i < image->width*image->height*2; i += 2, k++) { - ((unsigned char *)image->data)[i] = (unsigned char)((float)pixels[k].r*0.299f + (float)pixels[k].g*0.587f + (float)pixels[k].b*0.114f); - ((unsigned char *)image->data)[i + 1] = pixels[k].a; + ((unsigned char *)image->data)[i] = (unsigned char)((pixels[k].x*0.299f + (float)pixels[k].y*0.587f + (float)pixels[k].z*0.114f)*255.0f); + ((unsigned char *)image->data)[i + 1] = (unsigned char)(pixels[k].w*255.0f); } } break; @@ -702,9 +847,9 @@ void ImageFormat(Image *image, int newFormat) for (int i = 0; i < image->width*image->height; i++) { - r = (unsigned char)(round((float)pixels[i].r*31.0f/255)); - g = (unsigned char)(round((float)pixels[i].g*63.0f/255)); - b = (unsigned char)(round((float)pixels[i].b*31.0f/255)); + r = (unsigned char)(round(pixels[i].x*31.0f)); + g = (unsigned char)(round(pixels[i].y*63.0f)); + b = (unsigned char)(round(pixels[i].z*31.0f)); ((unsigned short *)image->data)[i] = (unsigned short)r << 11 | (unsigned short)g << 5 | (unsigned short)b; } @@ -716,9 +861,9 @@ void ImageFormat(Image *image, int newFormat) for (int i = 0, k = 0; i < image->width*image->height*3; i += 3, k++) { - ((unsigned char *)image->data)[i] = pixels[k].r; - ((unsigned char *)image->data)[i + 1] = pixels[k].g; - ((unsigned char *)image->data)[i + 2] = pixels[k].b; + ((unsigned char *)image->data)[i] = (unsigned char)(pixels[k].x*255.0f); + ((unsigned char *)image->data)[i + 1] = (unsigned char)(pixels[k].y*255.0f); + ((unsigned char *)image->data)[i + 2] = (unsigned char)(pixels[k].z*255.0f); } } break; case UNCOMPRESSED_R5G5B5A1: @@ -734,10 +879,10 @@ void ImageFormat(Image *image, int newFormat) for (int i = 0; i < image->width*image->height; i++) { - r = (unsigned char)(round((float)pixels[i].r*31.0f/255)); - g = (unsigned char)(round((float)pixels[i].g*31.0f/255)); - b = (unsigned char)(round((float)pixels[i].b*31.0f/255)); - a = (pixels[i].a > ALPHA_THRESHOLD) ? 1 : 0; + r = (unsigned char)(round(pixels[i].x*31.0f)); + g = (unsigned char)(round(pixels[i].y*31.0f)); + b = (unsigned char)(round(pixels[i].z*31.0f)); + a = (pixels[i].w > ((float)ALPHA_THRESHOLD/255.0f)) ? 1 : 0; ((unsigned short *)image->data)[i] = (unsigned short)r << 11 | (unsigned short)g << 6 | (unsigned short)b << 1 | (unsigned short)a; } @@ -754,10 +899,10 @@ void ImageFormat(Image *image, int newFormat) for (int i = 0; i < image->width*image->height; i++) { - r = (unsigned char)(round((float)pixels[i].r*15.0f/255)); - g = (unsigned char)(round((float)pixels[i].g*15.0f/255)); - b = (unsigned char)(round((float)pixels[i].b*15.0f/255)); - a = (unsigned char)(round((float)pixels[i].a*15.0f/255)); + r = (unsigned char)(round(pixels[i].x*15.0f)); + g = (unsigned char)(round(pixels[i].y*15.0f)); + b = (unsigned char)(round(pixels[i].z*15.0f)); + a = (unsigned char)(round(pixels[i].w*15.0f)); ((unsigned short *)image->data)[i] = (unsigned short)r << 12 | (unsigned short)g << 8 | (unsigned short)b << 4 | (unsigned short)a; } @@ -769,19 +914,21 @@ void ImageFormat(Image *image, int newFormat) for (int i = 0, k = 0; i < image->width*image->height*4; i += 4, k++) { - ((unsigned char *)image->data)[i] = pixels[k].r; - ((unsigned char *)image->data)[i + 1] = pixels[k].g; - ((unsigned char *)image->data)[i + 2] = pixels[k].b; - ((unsigned char *)image->data)[i + 3] = pixels[k].a; + ((unsigned char *)image->data)[i] = (unsigned char)(pixels[k].x*255.0f); + ((unsigned char *)image->data)[i + 1] = (unsigned char)(pixels[k].y*255.0f); + ((unsigned char *)image->data)[i + 2] = (unsigned char)(pixels[k].z*255.0f); + ((unsigned char *)image->data)[i + 3] = (unsigned char)(pixels[k].w*255.0f); } } break; case UNCOMPRESSED_R32: { + // WARNING: Image is converted to GRAYSCALE eqeuivalent 32bit + image->data = (float *)malloc(image->width*image->height*sizeof(float)); for (int i = 0; i < image->width*image->height; i++) { - ((float *)image->data)[i] = (float)((float)pixels[i].r*0.299f/255.0f + (float)pixels[i].g*0.587f/255.0f + (float)pixels[i].b*0.114f/255.0f); + ((float *)image->data)[i] = (float)(pixels[i].x*0.299f + pixels[i].y*0.587f + pixels[i].z*0.114f); } } break; case UNCOMPRESSED_R32G32B32: @@ -790,9 +937,9 @@ void ImageFormat(Image *image, int newFormat) for (int i = 0, k = 0; i < image->width*image->height*3; i += 3, k++) { - ((float *)image->data)[i] = (float)pixels[k].r/255.0f; - ((float *)image->data)[i + 1] = (float)pixels[k].g/255.0f; - ((float *)image->data)[i + 2] = (float)pixels[k].b/255.0f; + ((float *)image->data)[i] = pixels[k].x; + ((float *)image->data)[i + 1] = pixels[k].y; + ((float *)image->data)[i + 2] = pixels[k].z; } } break; case UNCOMPRESSED_R32G32B32A32: @@ -801,10 +948,10 @@ void ImageFormat(Image *image, int newFormat) for (int i = 0, k = 0; i < image->width*image->height*4; i += 4, k++) { - ((float *)image->data)[i] = (float)pixels[k].r/255.0f; - ((float *)image->data)[i + 1] = (float)pixels[k].g/255.0f; - ((float *)image->data)[i + 2] = (float)pixels[k].b/255.0f; - ((float *)image->data)[i + 3] = (float)pixels[k].a/255.0f; + ((float *)image->data)[i] = pixels[k].x; + ((float *)image->data)[i + 1] = pixels[k].y; + ((float *)image->data)[i + 2] = pixels[k].z; + ((float *)image->data)[i + 3] = pixels[k].w; } } break; default: break; @@ -812,13 +959,13 @@ void ImageFormat(Image *image, int newFormat) free(pixels); pixels = NULL; + // In case original image had mipmaps, generate mipmaps for formated image // NOTE: Original mipmaps are replaced by new ones, if custom mipmaps were used, they are lost if (image->mipmaps > 1) { image->mipmaps = 1; - assert(image->data != NULL); - ImageMipmaps(image); + if (image->data != NULL) ImageMipmaps(image); } } else TraceLog(LOG_WARNING, "Image data format is compressed, can not be converted"); @@ -1064,6 +1211,29 @@ void ImageResizeNN(Image *image,int newWidth,int newHeight) free(pixels); } +// Resize canvas and fill with color +// NOTE: Resize offset is relative to the top-left corner of the original image +void ImageResizeCanvas(Image *image, int newWidth,int newHeight, int offsetX, int offsetY, Color color) +{ + Image imTemp = GenImageColor(newWidth, newHeight, color); + Rectangle srcRec = { 0, 0, image->width, image->height }; + Rectangle dstRec = { offsetX, offsetY, srcRec.width, srcRec.height }; + + // TODO: Review different scaling situations + + if ((newWidth > image->width) && (newHeight > image->height)) + { + ImageDraw(&imTemp, *image, srcRec, dstRec); + ImageFormat(&imTemp, image->format); + UnloadImage(*image); + *image = imTemp; + } + else + { + // TODO: ImageCrop(), define proper cropping rectangle + } +} + // Generate all mipmap levels for a provided image // NOTE 1: Supports POT and NPOT images // NOTE 2: image.data is scaled to include mipmap levels @@ -1269,7 +1439,6 @@ void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec) { srcRec.height = src.height - srcRec.y; TraceLog(LOG_WARNING, "Source rectangle height out of bounds, rescaled height: %i", srcRec.height); - cropRequired = true; } Image srcCopy = ImageCopy(src); // Make a copy of source image to work with it @@ -1281,10 +1450,7 @@ void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec) if (dstRec.y < 0) dstRec.y = 0; // Scale source image in case destination rec size is different than source rec size - if ((dstRec.width != srcRec.width) || (dstRec.height != srcRec.height)) - { - ImageResize(&srcCopy, dstRec.width, dstRec.height); - } + if ((dstRec.width != srcRec.width) || (dstRec.height != srcRec.height)) ImageResize(&srcCopy, dstRec.width, dstRec.height); if ((dstRec.x + dstRec.width) > dst->width) { @@ -1483,7 +1649,7 @@ void ImageDrawTextEx(Image *dst, Vector2 position, Font font, const char *text, void ImageFlipVertical(Image *image) { Color *srcPixels = GetImageData(*image); - Color *dstPixels = (Color *)malloc(sizeof(Color)*image->width*image->height); + Color *dstPixels = (Color *)malloc(image->width*image->height*sizeof(Color)); for (int y = 0; y < image->height; y++) { @@ -1507,7 +1673,7 @@ void ImageFlipVertical(Image *image) void ImageFlipHorizontal(Image *image) { Color *srcPixels = GetImageData(*image); - Color *dstPixels = (Color *)malloc(sizeof(Color)*image->width*image->height); + Color *dstPixels = (Color *)malloc(image->width*image->height*sizeof(Color)); for (int y = 0; y < image->height; y++) { @@ -1527,6 +1693,58 @@ void ImageFlipHorizontal(Image *image) image->data = processed.data; } +// Rotate image clockwise 90deg +void ImageRotateCW(Image *image) +{ + Color *srcPixels = GetImageData(*image); + Color *rotPixels = (Color *)malloc(image->width*image->height*sizeof(Color)); + + for (int y = 0; y < image->height; y++) + { + for (int x = 0; x < image->width; x++) + { + rotPixels[x*image->height + (image->height - y - 1)] = srcPixels[y*image->width + x]; + } + } + + Image processed = LoadImageEx(rotPixels, image->height, image->width); + ImageFormat(&processed, image->format); + UnloadImage(*image); + + free(srcPixels); + free(rotPixels); + + image->data = processed.data; + image->width = processed.width; + image->height = processed.height; +} + +// Rotate image counter-clockwise 90deg +void ImageRotateCCW(Image *image) +{ + Color *srcPixels = GetImageData(*image); + Color *rotPixels = (Color *)malloc(image->width*image->height*sizeof(Color)); + + for (int y = 0; y < image->height; y++) + { + for (int x = 0; x < image->width; x++) + { + rotPixels[x*image->height + y] = srcPixels[y*image->width + (image->width - x - 1)]; + } + } + + Image processed = LoadImageEx(rotPixels, image->height, image->width); + ImageFormat(&processed, image->format); + UnloadImage(*image); + + free(srcPixels); + free(rotPixels); + + image->data = processed.data; + image->width = processed.width; + image->height = processed.height; +} + // Modify image color: tint void ImageColorTint(Image *image, Color color) { @@ -1905,6 +2123,18 @@ Image GenImageCellular(int width, int height, int tileSize) return image; } + +// Generate image: font atlas. Requires TTF as input file. +// NOTE: Generated atlas packs characters in order and rectangles are defined with magenta borders (?) +// NOTE: Characters info data should be allocated by user for charsCount +Image GenImageFont(const char *fileName, int fontSize, int charsCount, int *fontChars, CharInfo *chars) +{ + Image image = { 0 }; + + // TODO. + + return image; +} #endif // SUPPORT_IMAGE_GENERATION // Generate GPU mipmaps for a texture @@ -2020,9 +2250,9 @@ void DrawTextureV(Texture2D texture, Vector2 position, Color tint) // Draw a Texture2D with extended parameters void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, float scale, Color tint) { - Rectangle sourceRec = { 0, 0, texture.width, texture.height }; - Rectangle destRec = { position.x, position.y, texture.width*scale, texture.height*scale }; - Vector2 origin = { 0, 0 }; + Rectangle sourceRec = { 0.0f, 0.0f, (float)texture.width, (float)texture.height }; + Rectangle destRec = { position.x, position.y, (float)texture.width*scale, (float)texture.height*scale }; + Vector2 origin = { 0.0f, 0.0f }; DrawTexturePro(texture, sourceRec, destRec, origin, rotation, tint); } @@ -2030,8 +2260,8 @@ void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, float sc // Draw a part of a texture (defined by a rectangle) void DrawTextureRec(Texture2D texture, Rectangle sourceRec, Vector2 position, Color tint) { - Rectangle destRec = { position.x, position.y, sourceRec.width, fabsf(sourceRec.height) }; - Vector2 origin = { 0, 0 }; + Rectangle destRec = { position.x, position.y, sourceRec.width, fabs(sourceRec.height) }; + Vector2 origin = { 0.0f, 0.0f }; DrawTexturePro(texture, sourceRec, destRec, origin, 0.0f, tint); } @@ -2043,6 +2273,9 @@ void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle destRec, V // Check if texture is valid if (texture.id > 0) { + float width = (float)texture.width; + float height = (float)texture.height; + if (sourceRec.width < 0) sourceRec.x -= sourceRec.width; if (sourceRec.height < 0) sourceRec.y -= sourceRec.height; @@ -2058,19 +2291,19 @@ void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle destRec, V rlNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer // Bottom-left corner for texture and quad - rlTexCoord2f(sourceRec.x/texture.width, sourceRec.y/texture.height); + rlTexCoord2f(sourceRec.x/width, sourceRec.y/height); rlVertex2f(0.0f, 0.0f); // Bottom-right corner for texture and quad - rlTexCoord2f(sourceRec.x/texture.width, (sourceRec.y + sourceRec.height)/texture.height); + rlTexCoord2f(sourceRec.x/width, (sourceRec.y + sourceRec.height)/height); rlVertex2f(0.0f, destRec.height); // Top-right corner for texture and quad - rlTexCoord2f((sourceRec.x + sourceRec.width)/texture.width, (sourceRec.y + sourceRec.height)/texture.height); + rlTexCoord2f((sourceRec.x + sourceRec.width)/width, (sourceRec.y + sourceRec.height)/height); rlVertex2f(destRec.width, destRec.height); // Top-left corner for texture and quad - rlTexCoord2f((sourceRec.x + sourceRec.width)/texture.width, sourceRec.y/texture.height); + rlTexCoord2f((sourceRec.x + sourceRec.width)/width, sourceRec.y/height); rlVertex2f(destRec.width, 0.0f); rlEnd(); rlPopMatrix(); |
