diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile | 163 | ||||
| -rw-r--r-- | src/audio.c | 29 | ||||
| -rw-r--r-- | src/camera.h | 65 | ||||
| -rw-r--r-- | src/core.c | 75 | ||||
| -rw-r--r-- | src/models.c | 4 | ||||
| -rw-r--r-- | src/raylib.h | 4 | ||||
| -rw-r--r-- | src/raymath.h | 51 | ||||
| -rw-r--r-- | src/rlgl.c | 38 | ||||
| -rw-r--r-- | src/rlgl.h | 127 | ||||
| -rw-r--r-- | src/text.c | 2 | ||||
| -rw-r--r-- | src/textures.c | 67 |
11 files changed, 364 insertions, 261 deletions
diff --git a/src/Makefile b/src/Makefile index b616b583..f2e09988 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,10 +1,19 @@ #****************************************************************************** # -# raylib makefile for desktop platforms, Raspberry Pi and HTML5 (emscripten) +# raylib makefile # -# Many Thanks to Emanuele Petriglia for his contribution on GNU/Linux pipeline. +# Platforms supported: +# PLATFORM_DESKTOP: Windows (win32/Win64) +# PLATFORM_DESKTOP: Linux +# PLATFORM_DESKTOP: OSX (Mac) +# PLATFORM_ANDROID: Android (ARM or ARM64) +# PLATFORM_RPI: Raspberry Pi (Raspbian) +# PLATFORM_WEB: HTML5 (Chrome, Firefox) # -# Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) +# Many thanks to Milan Nikolic (@gen2brain) for implementing Android platform pipeline. +# Many thanks to Emanuele Petriglia for his contribution on GNU/Linux pipeline. +# +# Copyright (c) 2014-2017 Ramon Santamaria (@raysan5) # # This software is provided "as-is", without any express or implied warranty. # In no event will the authors be held liable for any damages arising from @@ -29,7 +38,7 @@ # Please read the wiki to know how to compile raylib, because there are # different methods. -.PHONY: all clean install unistall +.PHONY: all clean install uninstall # define raylib platform to compile for # possible platforms: PLATFORM_DESKTOP PLATFORM_ANDROID PLATFORM_RPI PLATFORM_WEB @@ -38,12 +47,16 @@ PLATFORM ?= PLATFORM_DESKTOP # define YES if you want shared/dynamic version of library instead of static (default) SHARED ?= NO -# define NO to use OpenAL Soft as static library (or shared by default) -SHARED_OPENAL ?= YES +# use OpenAL Soft as shared library (.so / .dll) +# NOTE: If defined NO, static OpenAL Soft library should be provided +SHARED_OPENAL ?= NO # on PLATFORM_WEB force OpenAL Soft shared library ifeq ($(PLATFORM),PLATFORM_WEB) - SHARED_OPENAL ?= YES + SHARED_OPENAL = YES +endif +ifeq ($(PLATFORM),PLATFORM_ANDROID) + SHARED_OPENAL = YES endif # determine if the file has root access (only for installing raylib) @@ -69,48 +82,67 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) endif endif +ifeq ($(PLATFORM),PLATFORM_WEB) + # Emscripten required variables + EMSDK_PATH = C:/emsdk + EMSCRIPTEN_VERSION = 1.37.9 + CLANG_VERSION=e1.37.9_64bit + PYTHON_VERSION=2.7.5.3_64bit + NODE_VERSION=4.1.1_64bit + export PATH=$(EMSDK_PATH);$(EMSDK_PATH)\clang\$(CLANG_VERSION);$(EMSDK_PATH)\node\$(NODE_VERSION)\bin;$(EMSDK_PATH)\python\$(PYTHON_VERSION);$(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION);C:\raylib\MinGW\bin:$$(PATH) + EMSCRIPTEN=$(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION) +endif + ifeq ($(PLATFORM),PLATFORM_ANDROID) - # path to Android NDK + # Android NDK path + # NOTE: Required for standalone toolchain generation ANDROID_NDK = $(ANDROID_NDK_HOME) + + # Android standalone toolchain path + # NOTE: This path is also used if toolchain generation + #ANDROID_TOOLCHAIN = $(CURDIR)/toolchain + ANDROID_TOOLCHAIN = C:/raylib/android-standalone-toolchain - # possible Android architectures: ARM ARM64 + # Android architecture: ARM or ARM64 ANDROID_ARCH ?= ARM - # define YES to use clang instead of gcc + # Android compiler: gcc or clang + # NOTE: Define YES to use clang instead of gcc ANDROID_LLVM ?= NO - - # standalone Android toolchain install dir - ANDROID_TOOLCHAIN = $(CURDIR)/toolchain endif ifeq ($(PLATFORM),PLATFORM_RPI) + # RPI cross-compiler CROSS_COMPILE ?= NO endif # define raylib graphics api depending on selected platform -ifeq ($(PLATFORM),PLATFORM_ANDROID) - GRAPHICS = GRAPHICS_API_OPENGL_ES2 -endif -ifeq ($(PLATFORM),PLATFORM_RPI) - # define raylib graphics api to use (on RPI, OpenGL ES 2.0 must be used) - GRAPHICS = GRAPHICS_API_OPENGL_ES2 -else - # define raylib graphics api to use (OpenGL 3.3 by default) +ifeq ($(PLATFORM),PLATFORM_DESKTOP) + # by default use OpenGL 3.3 on desktop platforms GRAPHICS ?= GRAPHICS_API_OPENGL_33 #GRAPHICS = GRAPHICS_API_OPENGL_11 # Uncomment to use OpenGL 1.1 #GRAPHICS = GRAPHICS_API_OPENGL_21 # Uncomment to use OpenGL 2.1 endif +ifeq ($(PLATFORM),PLATFORM_RPI) + # on RPI OpenGL ES 2.0 must be used + GRAPHICS = GRAPHICS_API_OPENGL_ES2 +endif ifeq ($(PLATFORM),PLATFORM_WEB) + # on HTML5 OpenGL ES 2.0 is used, emscripten translates it to WebGL 1.0 + GRAPHICS = GRAPHICS_API_OPENGL_ES2 +endif +ifeq ($(PLATFORM),PLATFORM_ANDROID) + # by default use OpenGL ES 2.0 on Android GRAPHICS = GRAPHICS_API_OPENGL_ES2 endif # NOTE: makefiles targets require tab indentation - -# define compiler: gcc for C program, define as g++ for C++ +# NOTE: define compiler: gcc for C program, define as g++ for C++ # default gcc compiler CC = gcc +# Android toolchain compiler ifeq ($(PLATFORM),PLATFORM_ANDROID) ifeq ($(ANDROID_ARCH),ARM) ifeq ($(ANDROID_LLVM),YES) @@ -128,6 +160,7 @@ ifeq ($(PLATFORM),PLATFORM_ANDROID) endif endif +# RPI cross-compiler ifeq ($(PLATFORM),PLATFORM_RPI) ifeq ($(CROSS_COMPILE),YES) # rpi compiler @@ -135,13 +168,15 @@ ifeq ($(PLATFORM),PLATFORM_RPI) endif endif +# HTML5 emscripten compiler ifeq ($(PLATFORM),PLATFORM_WEB) - # emscripten compiler CC = emcc endif +# default archiver program to pack libraries AR = ar +# Android archiver ifeq ($(PLATFORM),PLATFORM_ANDROID) ifeq ($(ANDROID_ARCH),ARM) AR = $(ANDROID_TOOLCHAIN)/bin/arm-linux-androideabi-ar @@ -159,29 +194,17 @@ endif # -std=gnu99 defines C language mode (GNU C from 1999 revision) # -fgnu89-inline declaring inline functions support (GCC optimized) # -Wno-missing-braces ignore invalid warning (GCC bug 53119) -# -D_DEFAULT_SOURCE use with -std=c99 on Linux and PLATFORM_WEB -ifeq ($(PLATFORM),PLATFORM_DESKTOP) - ifeq ($(PLATFORM_OS),WINDOWS) - CFLAGS = -O1 -Wall -std=gnu99 -fgnu89-inline -Wno-missing-braces - endif - ifeq ($(PLATFORM_OS),LINUX) - CFLAGS = -O1 -Wall -std=c99 -D_DEFAULT_SOURCE - endif - ifeq ($(PLATFORM_OS),OSX) - CFLAGS = -O1 -Wall -std=gnu99 -fgnu89-inline -Wno-missing-braces - endif -endif +# -D_DEFAULT_SOURCE use with -std=c99 +CFLAGS = -O1 -Wall -std=c99 -D_DEFAULT_SOURCE -fgnu89-inline -Wno-missing-braces + ifeq ($(PLATFORM),PLATFORM_WEB) - CFLAGS = -O1 -Wall -std=c99 -D_DEFAULT_SOURCE -s USE_GLFW=3 -s ASSERTIONS=1 --profiling --preload-file resources + CFLAGS += -s USE_GLFW=3 -s ASSERTIONS=1 --profiling --preload-file resources # -O2 # if used, also set --memory-init-file 0 # --memory-init-file 0 # to avoid an external memory initialization code file (.mem) # -s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing # -s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB) # -s USE_PTHREADS=1 # multithreading support endif -ifeq ($(PLATFORM),PLATFORM_RPI) - CFLAGS = -O1 -Wall -std=gnu99 -fgnu89-inline -Wno-missing-braces -endif #CFLAGSEXTRA = -Wextra -Wmissing-prototypes -Wstrict-prototypes @@ -205,32 +228,32 @@ endif #CFLAGSEXTRA = -Wextra -Wmissing-prototypes -Wstrict-prototypes -# define any directories containing required header files -ifeq ($(PLATFORM),PLATFORM_ANDROID) -# STB libraries and others - INCLUDES = -I. -Iexternal +# external required libraries (stb and others) +INCLUDES = -I. -Iexternal # OpenAL Soft library - INCLUDES += -Iexternal/openal_soft/include -# Android includes - INCLUDES += -I$(ANDROID_TOOLCHAIN)/sysroot/usr/include - INCLUDES += -I$(ANDROID_NDK)/sources/android/native_app_glue -else -# STB libraries and others - INCLUDES = -I. -Iexternal -# GLFW3 library +INCLUDES += -Iexternal/openal_soft/include + +# define any directories containing required header files +ifeq ($(PLATFORM),PLATFORM_DESKTOP) + # GLFW3 library INCLUDES += -Iexternal/glfw3/include -# OpenAL Soft library - INCLUDES += -Iexternal/openal_soft/include endif ifeq ($(PLATFORM),PLATFORM_RPI) -# STB libraries and others - INCLUDES = -I. -Iexternal -# RPi libraries + # RPI requried libraries INCLUDES += -I/opt/vc/include INCLUDES += -I/opt/vc/include/interface/vmcs_host/linux INCLUDES += -I/opt/vc/include/interface/vcos/pthreads -# OpenAL Soft library - INCLUDES += -Iexternal/openal_soft/include +endif +ifeq ($(PLATFORM),PLATFORM_WEB) + # GLFW3 library + INCLUDES += -Iexternal/glfw3/include +endif +ifeq ($(PLATFORM),PLATFORM_ANDROID) + # Android required libraries + INCLUDES += -I$(ANDROID_TOOLCHAIN)/sysroot/usr/include + # Include android_native_app_glue.h + INCLUDES += -Iandroid/jni/include + #INCLUDES += -I$(ANDROID_NDK)/sources/android/native_app_glue endif # define output directory for compiled library @@ -245,6 +268,12 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) OUTPUT_PATH = ../release/osx endif endif +ifeq ($(PLATFORM),PLATFORM_RPI) + OUTPUT_PATH = ../release/rpi +endif +ifeq ($(PLATFORM),PLATFORM_WEB) + OUTPUT_PATH = ../release/html5 +endif ifeq ($(PLATFORM),PLATFORM_ANDROID) ifeq ($(ANDROID_ARCH),ARM) OUTPUT_PATH = ../release/android/armeabi-v7a @@ -253,12 +282,6 @@ ifeq ($(PLATFORM),PLATFORM_ANDROID) OUTPUT_PATH = ../release/android/arm64-v8a endif endif -ifeq ($(PLATFORM),PLATFORM_WEB) - OUTPUT_PATH = ../release/html5 -endif -ifeq ($(PLATFORM),PLATFORM_RPI) - OUTPUT_PATH = ../release/rpi -endif # define all object files required with a wildcard # The wildcard takes all files that finish with ".c", then it replaces the @@ -268,9 +291,10 @@ OBJS += external/stb_vorbis.o # typing 'make' will invoke the default target entry called 'all', # in this case, the 'default' target entry is raylib -all: toolchain raylib +all: raylib -# make standalone Android toolchain +# generate standalone Android toolchain +# NOTE: Android toolchain could already be provided toolchain: ifeq ($(PLATFORM),PLATFORM_ANDROID) ifeq ($(ANDROID_ARCH),ARM) @@ -304,7 +328,7 @@ else @echo "raylib shared library (libraylib.so) generated!" endif else - # compile raylib static library. + # compile raylib static library. $(AR) rcs $(OUTPUT_PATH)/libraylib.a $(OBJS) @echo "libraylib.a generated (static library)!" ifeq ($(SHARED_OPENAL),NO) @@ -353,6 +377,7 @@ external/stb_vorbis.o: external/stb_vorbis.c external/stb_vorbis.h utils.o : utils.c utils.h $(CC) -c $< $(CFLAGS) $(INCLUDES) -D$(PLATFORM) -D$(SHAREDFLAG) + # It installs generated and needed files to compile projects using raylib. # The installation works manually. # TODO: add other platforms. @@ -379,7 +404,7 @@ endif # it removes raylib dev files installed on the system. # TODO: see 'install' target. -unistall : +uninstall : ifeq ($(ROOT),root) ifeq ($(PLATFORM_OS),LINUX) rm --force /usr/local/include/raylib.h diff --git a/src/audio.c b/src/audio.c index d63047a8..39befbbc 100644 --- a/src/audio.c +++ b/src/audio.c @@ -79,7 +79,7 @@ #include "utils.h" // Required for: fopen() Android mapping #endif -#ifdef __APPLE__ +#if defined(__APPLE__) #include "OpenAL/al.h" // OpenAL basic header #include "OpenAL/alc.h" // OpenAL context header (like OpenGL, OpenAL requires a context to work) #else @@ -570,7 +570,7 @@ void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels) // NOTE: Only supported mono <--> stereo if (wave->channels != channels) { - void *data = malloc(wave->sampleCount*channels*wave->sampleSize/8); + void *data = malloc(wave->sampleCount*wave->sampleSize/8*channels); if ((wave->channels == 1) && (channels == 2)) // mono ---> stereo (duplicate mono information) { @@ -607,7 +607,7 @@ Wave WaveCopy(Wave wave) { Wave newWave = { 0 }; - newWave.data = malloc(wave.sampleCount*wave.channels*wave.sampleSize/8); + newWave.data = malloc(wave.sampleCount*wave.sampleSize/8*wave.channels); if (newWave.data != NULL) { @@ -632,7 +632,7 @@ void WaveCrop(Wave *wave, int initSample, int finalSample) { int sampleCount = finalSample - initSample; - void *data = malloc(sampleCount*wave->channels*wave->sampleSize/8); + void *data = malloc(sampleCount*wave->sampleSize/8*wave->channels); memcpy(data, (unsigned char*)wave->data + (initSample*wave->channels*wave->sampleSize/8), sampleCount*wave->channels*wave->sampleSize/8); @@ -810,7 +810,8 @@ void StopMusicStream(Music music) for (int i = 0; i < MAX_STREAM_BUFFERS; i++) { - alBufferData(music->stream.buffers[i], music->stream.format, pcm, AUDIO_BUFFER_SIZE*music->stream.sampleSize/8*music->stream.channels, music->stream.sampleRate); + UpdateAudioStream(music->stream, pcm, AUDIO_BUFFER_SIZE); + //alBufferData(music->stream.buffers[i], music->stream.format, pcm, AUDIO_BUFFER_SIZE*music->stream.sampleSize/8*music->stream.channels, music->stream.sampleRate); } free(pcm); @@ -849,11 +850,11 @@ void UpdateMusicStream(Music music) bool active = true; // NOTE: Using dynamic allocation because it could require more than 16KB - void *pcm = calloc(AUDIO_BUFFER_SIZE*music->stream.channels*music->stream.sampleSize/8, 1); + void *pcm = calloc(AUDIO_BUFFER_SIZE*music->stream.sampleSize/8*music->stream.channels, 1); int numBuffersToProcess = processed; int samplesCount = 0; // Total size of data steamed in L+R samples for xm floats, - //individual L or R for ogg shorts + // individual L or R for ogg shorts for (int i = 0; i < numBuffersToProcess; i++) { @@ -1245,23 +1246,19 @@ static Wave LoadWAV(const char *fileName) // NOTE: Using stb_vorbis library static Wave LoadOGG(const char *fileName) { - Wave wave; + Wave wave = { 0 }; stb_vorbis *oggFile = stb_vorbis_open_filename(fileName, NULL, NULL); - if (oggFile == NULL) - { - TraceLog(WARNING, "[%s] OGG file could not be opened", fileName); - wave.data = NULL; - } + if (oggFile == NULL) TraceLog(WARNING, "[%s] OGG file could not be opened", fileName); else { stb_vorbis_info info = stb_vorbis_get_info(oggFile); - + wave.sampleRate = info.sample_rate; wave.sampleSize = 16; // 16 bit per sample (short) wave.channels = info.channels; - wave.sampleCount = (int)stb_vorbis_stream_length_in_samples(oggFile); + wave.sampleCount = (int)stb_vorbis_stream_length_in_samples(oggFile); // Independent by channel float totalSeconds = stb_vorbis_stream_length_in_seconds(oggFile); if (totalSeconds > 10) TraceLog(WARNING, "[%s] Ogg audio length is larger than 10 seconds (%f), that's a big file in memory, consider music streaming", fileName, totalSeconds); @@ -1329,7 +1326,7 @@ void TraceLog(int msgType, const char *text, ...) va_list args; int traceDebugMsgs = 0; -#ifdef DO_NOT_TRACE_DEBUG_MSGS +#if defined(DO_NOT_TRACE_DEBUG_MSGS) traceDebugMsgs = 0; #endif diff --git a/src/camera.h b/src/camera.h index e1b00ac2..8067e7bf 100644 --- a/src/camera.h +++ b/src/camera.h @@ -181,7 +181,14 @@ void SetCameraMoveControls(int frontKey, int backKey, // Types and Structures Definition //---------------------------------------------------------------------------------- // Camera move modes (first person and third person cameras) -typedef enum { MOVE_FRONT = 0, MOVE_BACK, MOVE_RIGHT, MOVE_LEFT, MOVE_UP, MOVE_DOWN } CameraMove; +typedef enum { + MOVE_FRONT = 0, + MOVE_BACK, + MOVE_RIGHT, + MOVE_LEFT, + MOVE_UP, + MOVE_DOWN +} CameraMove; //---------------------------------------------------------------------------------- // Global Variables Definition @@ -203,15 +210,14 @@ static int cameraMode = CAMERA_CUSTOM; // Current camera mode #if defined(CAMERA_STANDALONE) // NOTE: Camera controls depend on some raylib input functions // TODO: Set your own input functions (used in UpdateCamera()) -static Vector2 GetMousePosition() { return (Vector2){ 0.0f, 0.0f }; } -static void SetMousePosition(Vector2 pos) {} +static void EnableCursor() {} // Unlock cursor +static void DisableCursor() {} // Lock cursor + +static int IsKeyDown(int key) { return 0; } + static int IsMouseButtonDown(int button) { return 0;} static int GetMouseWheelMove() { return 0; } -static int GetScreenWidth() { return 1280; } -static int GetScreenHeight() { return 720; } -static void ShowCursor() {} -static void HideCursor() {} -static int IsKeyDown(int key) { return 0; } +static Vector2 GetMousePosition() { return (Vector2){ 0.0f, 0.0f }; } #endif //---------------------------------------------------------------------------------- @@ -242,18 +248,23 @@ void SetCameraMode(Camera camera, int mode) cameraAngle.y = -asinf(fabsf(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) + //cameraAngle.x = 0.0f*DEG2RAD; // Camera angle in plane XZ (0 aligned with Z, move positive CCW) //cameraAngle.y = -60.0f*DEG2RAD; // Camera angle in plane XY (0 aligned with X, move positive CW) playerEyesPosition = camera.position.y; + + // Lock cursor for first person and third person cameras + if ((mode == CAMERA_FIRST_PERSON) || + (mode == CAMERA_THIRD_PERSON)) DisableCursor(); + else EnableCursor(); cameraMode = mode; } // Update camera depending on selected mode // NOTE: Camera controls depend on some raylib functions: -// Mouse: GetMousePosition(), SetMousePosition(), IsMouseButtonDown(), GetMouseWheelMove() -// System: GetScreenWidth(), GetScreenHeight(), ShowCursor(), HideCursor() +// System: EnableCursor(), DisableCursor() +// Mouse: IsMouseButtonDown(), GetMousePosition(), GetMouseWheelMove() // Keys: IsKeyDown() // TODO: Port to quaternion-based camera void UpdateCamera(Camera *camera) @@ -284,36 +295,10 @@ void UpdateCamera(Camera *camera) if (cameraMode != CAMERA_CUSTOM) { - // Get screen size - int screenWidth = GetScreenWidth(); - int screenHeight = GetScreenHeight(); - - if ((cameraMode == CAMERA_FIRST_PERSON) || - (cameraMode == CAMERA_THIRD_PERSON)) - { - HideCursor(); - - if (mousePosition.x < (float)screenHeight/3.0f) SetMousePosition((Vector2){ screenWidth - screenHeight/3, mousePosition.y }); - else if (mousePosition.y < (float)screenHeight/3.0f) SetMousePosition((Vector2){ mousePosition.x, screenHeight - screenHeight/3 }); - else if (mousePosition.x > (screenWidth - (float)screenHeight/3.0f)) SetMousePosition((Vector2){ screenHeight/3, mousePosition.y }); - else if (mousePosition.y > (screenHeight - (float)screenHeight/3.0f)) SetMousePosition((Vector2){ mousePosition.x, screenHeight/3 }); - else - { - mousePositionDelta.x = mousePosition.x - previousMousePosition.x; - mousePositionDelta.y = mousePosition.y - previousMousePosition.y; - } - } - else // CAMERA_FREE, CAMERA_ORBITAL - { - ShowCursor(); - - mousePositionDelta.x = mousePosition.x - previousMousePosition.x; - mousePositionDelta.y = mousePosition.y - previousMousePosition.y; - } + mousePositionDelta.x = mousePosition.x - previousMousePosition.x; + mousePositionDelta.y = mousePosition.y - previousMousePosition.y; - // NOTE: We GetMousePosition() again because it can be modified by a previous SetMousePosition() call - // If using directly mousePosition variable we have problems on CAMERA_FIRST_PERSON and CAMERA_THIRD_PERSON - previousMousePosition = GetMousePosition(); + previousMousePosition = mousePosition; } // Support for multiple automatic camera modes @@ -5,11 +5,10 @@ * PLATFORMS SUPPORTED: * - Windows (win32/Win64) * - Linux (tested on Ubuntu) -* - Mac (OSX) -* - Android (API Level 9 or greater) +* - OSX (Mac) +* - Android (ARM or ARM64) * - Raspberry Pi (Raspbian) * - HTML5 (Chrome, Firefox) -* - Oculus Rift CV1 * * CONFIGURATION: * @@ -42,6 +41,9 @@ * #define SUPPORT_MOUSE_GESTURES * Mouse gestures are directly mapped like touches and processed by gestures system. * +* #define SUPPORT_BUSY_WAIT_LOOP +* Use busy wait loop for timming sync, if not defined, a high-resolution timer is setup and used +* * DEPENDENCIES: * GLFW3 - Manage graphic device, OpenGL context and inputs on PLATFORM_DESKTOP (Windows, Linux, OSX) * raymath - 3D math functionality (Vector3, Matrix, Quaternion) @@ -76,6 +78,7 @@ #define SUPPORT_MOUSE_GESTURES #define SUPPORT_CAMERA_SYSTEM #define SUPPORT_GESTURES_SYSTEM +#define SUPPORT_BUSY_WAIT_LOOP //------------------------------------------------- #include "raylib.h" @@ -105,9 +108,9 @@ #include <string.h> // Required for: strrchr(), strcmp() //#include <errno.h> // Macros for reporting and retrieving error conditions through error codes -#if defined __linux__ || defined(PLATFORM_WEB) +#if defined(__linux__) || defined(PLATFORM_WEB) #include <sys/time.h> // Required for: timespec, nanosleep(), select() - POSIX -#elif defined __APPLE__ +#elif defined(__APPLE__) #include <unistd.h> // Required for: usleep() #endif @@ -115,13 +118,19 @@ //#define GLFW_INCLUDE_NONE // Disable the standard OpenGL header inclusion on GLFW3 #include <GLFW/glfw3.h> // GLFW3 library: Windows, OpenGL context and Input management - #ifdef __linux__ + #if defined(__linux__) #define GLFW_EXPOSE_NATIVE_X11 // Linux specific definitions for getting #define GLFW_EXPOSE_NATIVE_GLX // native functions like glfwGetX11Window #include <GLFW/glfw3native.h> // which are required for hiding mouse #endif //#include <GL/gl.h> // OpenGL functions (GLFW3 already includes gl.h) //#define GLFW_DLL // Using GLFW DLL on Windows -> No, we use static version! + + #if !defined(SUPPORT_BUSY_WAIT_LOOP) && defined(_WIN32) + // NOTE: Those functions require linking with winmm library + __stdcall unsigned int timeBeginPeriod(unsigned int uPeriod); + __stdcall unsigned int timeEndPeriod(unsigned int uPeriod); + #endif #endif #if defined(PLATFORM_ANDROID) @@ -277,6 +286,10 @@ static int gamepadAxisCount = 0; // Register number of available game static Vector2 mousePosition; // Mouse position on screen +#if defined(PLATFORM_WEB) +static bool toggleCursorLock = false; // Ask for cursor pointer lock on next click +#endif + #if defined(SUPPORT_GESTURES_SYSTEM) static Vector2 touchPosition[MAX_TOUCH_POINTS]; // Touch position on screen #endif @@ -507,6 +520,10 @@ void CloseWindow(void) glfwTerminate(); #endif +#if !defined(SUPPORT_BUSY_WAIT_LOOP) && defined(_WIN32) + timeEndPeriod(1); // Restore time period +#endif + #if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) // Close surface, context and display if (display != EGL_NO_DISPLAY) @@ -629,6 +646,15 @@ void SetWindowMonitor(int monitor) #endif } +// Set window minimum dimensions (for FLAG_WINDOW_RESIZABLE) +void SetWindowMinSize(int width, int height) +{ +#if defined(PLATFORM_DESKTOP) + const GLFWvidmode *mode = glfwGetVideoMode(glfwGetPrimaryMonitor()); + glfwSetWindowSizeLimits(window, width, height, mode->width, mode->height); +#endif +} + // Get current screen width int GetScreenWidth(void) { @@ -646,7 +672,7 @@ int GetScreenHeight(void) void ShowCursor() { #if defined(PLATFORM_DESKTOP) - #ifdef __linux__ + #if defined(__linux__) XUndefineCursor(glfwGetX11Display(), glfwGetX11Window(window)); #else glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); @@ -659,7 +685,7 @@ void ShowCursor() void HideCursor() { #if defined(PLATFORM_DESKTOP) - #ifdef __linux__ + #if defined(__linux__) XColor col; const char nil[] = {0}; @@ -687,6 +713,9 @@ void EnableCursor() #if defined(PLATFORM_DESKTOP) glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); #endif +#if defined(PLATFORM_WEB) + toggleCursorLock = true; +#endif cursorHidden = false; } @@ -696,6 +725,9 @@ void DisableCursor() #if defined(PLATFORM_DESKTOP) glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); #endif +#if defined(PLATFORM_WEB) + toggleCursorLock = true; +#endif cursorHidden = true; } #endif // !defined(PLATFORM_ANDROID) @@ -1657,7 +1689,7 @@ static void InitGraphicsDevice(int width, int height) glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); // Choose OpenGL minor version (just hint) glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // Profiles Hint: Only 3.3 and above! // Other values: GLFW_OPENGL_ANY_PROFILE, GLFW_OPENGL_COMPAT_PROFILE -#ifdef __APPLE__ +#if defined(__APPLE__) glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // OSX Requires #else glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_FALSE); // Fordward Compatibility Hint: Only 3.3 and above! @@ -1799,12 +1831,13 @@ static void InitGraphicsDevice(int width, int height) const EGLint framebufferAttribs[] = { - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, // Type of context support -> Required on RPI? - //EGL_SURFACE_TYPE, EGL_WINDOW_BIT, // Don't use it on Android! + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, // Type of context support -> Required on RPI? + //EGL_SURFACE_TYPE, EGL_WINDOW_BIT, // Don't use it on Android! EGL_RED_SIZE, 8, // RED color bit depth (alternative: 5) EGL_GREEN_SIZE, 8, // GREEN color bit depth (alternative: 6) EGL_BLUE_SIZE, 8, // BLUE color bit depth (alternative: 5) //EGL_ALPHA_SIZE, 8, // ALPHA bit depth + //EGL_TRANSPARENT_TYPE, EGL_TRANSPARENT_RGB, // Request transparent framebuffer EGL_DEPTH_SIZE, 16, // Depth buffer size (Required to use Depth testing!) //EGL_STENCIL_SIZE, 8, // Stencil buffer size EGL_SAMPLE_BUFFERS, sampleBuffer, // Activate MSAA @@ -1942,7 +1975,7 @@ static void InitGraphicsDevice(int width, int height) // Set viewport parameters static void SetupViewport(void) { -#ifdef __APPLE__ +#if defined(__APPLE__) // Get framebuffer size of current window // NOTE: Required to handle HighDPI display correctly on OSX because framebuffer // is automatically reasized to adapt to new DPI. @@ -2034,6 +2067,10 @@ static void SetupFramebufferSize(int displayWidth, int displayHeight) static void InitTimer(void) { srand(time(NULL)); // Initialize random seed + +#if !defined(SUPPORT_BUSY_WAIT_LOOP) && defined(_WIN32) + timeBeginPeriod(1); // Setup high-resolution timer to 1ms (granularity of 1-2 ms) +#endif #if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) struct timespec now; @@ -2070,7 +2107,6 @@ static double GetTime(void) // http://stackoverflow.com/questions/43057578/c-programming-win32-games-sleep-taking-longer-than-expected static void Wait(float ms) { -#define SUPPORT_BUSY_WAIT_LOOP #if defined(SUPPORT_BUSY_WAIT_LOOP) double prevTime = GetTime(); double nextTime = 0.0; @@ -2078,9 +2114,9 @@ static void Wait(float ms) // Busy wait loop while ((nextTime - prevTime) < ms/1000.0f) nextTime = GetTime(); #else - #if defined _WIN32 + #if defined(_WIN32) Sleep((unsigned int)ms); - #elif defined __linux__ || defined(PLATFORM_WEB) + #elif defined(__linux__) || defined(PLATFORM_WEB) struct timespec req = { 0 }; time_t sec = (int)(ms/1000.0f); ms -= (sec*1000); @@ -2089,7 +2125,7 @@ static void Wait(float ms) // NOTE: Use nanosleep() on Unix platforms... usleep() it's deprecated. while (nanosleep(&req, &req) == -1) continue; - #elif defined __APPLE__ + #elif defined(__APPLE__) usleep(ms*1000.0f); #endif #endif @@ -2719,7 +2755,8 @@ static EM_BOOL EmscriptenKeyboardCallback(int eventType, const EmscriptenKeyboar // Register mouse input events static EM_BOOL EmscriptenMouseCallback(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData) { - if (eventType == EMSCRIPTEN_EVENT_CLICK) + // Lock mouse pointer when click on screen + if ((eventType == EMSCRIPTEN_EVENT_CLICK) && toggleCursorLock) { EmscriptenPointerlockChangeEvent plce; emscripten_get_pointerlock_status(&plce); @@ -2731,6 +2768,8 @@ static EM_BOOL EmscriptenMouseCallback(int eventType, const EmscriptenMouseEvent emscripten_get_pointerlock_status(&plce); //if (plce.isActive) TraceLog(WARNING, "Pointer lock exit did not work!"); } + + toggleCursorLock = false; } return 0; @@ -3251,7 +3290,7 @@ static void *GamepadThread(void *arg) // Plays raylib logo appearing animation static void LogoAnimation(void) { -#ifndef PLATFORM_WEB +#if !defined(PLATFORM_WEB) int logoPositionX = screenWidth/2 - 128; int logoPositionY = screenHeight/2 - 128; diff --git a/src/models.c b/src/models.c index fa6faf16..2459edf1 100644 --- a/src/models.c +++ b/src/models.c @@ -1218,11 +1218,13 @@ void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rota Matrix matRotation = MatrixRotate(rotationAxis, rotationAngle*DEG2RAD); Matrix matScale = MatrixScale(scale.x, scale.y, scale.z); Matrix matTranslation = MatrixTranslate(position.x, position.y, position.z); + + Matrix matTransform = MatrixMultiply(MatrixMultiply(matScale, matRotation), matTranslation); // Combine model transformation matrix (model.transform) with matrix generated by function parameters (matTransform) //Matrix matModel = MatrixMultiply(model.transform, matTransform); // Transform to world-space coordinates - model.transform = MatrixMultiply(MatrixMultiply(matScale, matRotation), matTranslation); + model.transform = MatrixMultiply(model.transform, matTransform); model.material.colDiffuse = tint; // TODO: Multiply tint color by diffuse color? rlglDrawMesh(model.mesh, model.material, model.transform); diff --git a/src/raylib.h b/src/raylib.h index 18d442d1..4038215e 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -351,7 +351,7 @@ typedef struct Image { int format; // Data format (TextureFormat type) } Image; -// Texture2D type, bpp always RGBA (32bit) +// Texture2D type // NOTE: Data stored in GPU memory typedef struct Texture2D { unsigned int id; // OpenGL texture id @@ -553,6 +553,7 @@ typedef enum { UNCOMPRESSED_R5G5B5A1, // 16 bpp (1 bit alpha) UNCOMPRESSED_R4G4B4A4, // 16 bpp (4 bit alpha) UNCOMPRESSED_R8G8B8A8, // 32 bpp + UNCOMPRESSED_R32G32B32, // 32 bit per channel (float) - HDR COMPRESSED_DXT1_RGB, // 4 bpp (no alpha) COMPRESSED_DXT1_RGBA, // 4 bpp (1 bit alpha) COMPRESSED_DXT3_RGBA, // 8 bpp @@ -667,6 +668,7 @@ RLAPI void ToggleFullscreen(void); // Fullscreen RLAPI void SetWindowIcon(Image image); // Set icon for window (only PLATFORM_DESKTOP) RLAPI void SetWindowPosition(int x, int y); // Set window position on screen (only PLATFORM_DESKTOP) RLAPI void SetWindowMonitor(int monitor); // Set monitor for the current window (fullscreen mode) +RLAPI void SetWindowMinSize(int width, int height); // Set window minimum dimensions (for FLAG_WINDOW_RESIZABLE) RLAPI int GetScreenWidth(void); // Get current screen width RLAPI int GetScreenHeight(void); // Get current screen height diff --git a/src/raymath.h b/src/raymath.h index 3bde10fc..1dbebc07 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -189,8 +189,10 @@ RMDEF Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float slerp); // RMDEF Quaternion QuaternionFromMatrix(Matrix matrix); // Returns a quaternion for a given rotation matrix RMDEF Matrix QuaternionToMatrix(Quaternion q); // Returns a matrix for a given quaternion RMDEF Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle); // Returns rotation quaternion for an angle and axis -RMDEF void QuaternionToAxisAngle(Quaternion q, Vector3 *outAxis, float *outAngle); // Returns the rotation angle and axis for a given quaternion -RMDEF void QuaternionTransform(Quaternion *q, Matrix mat); // Transform a quaternion given a transformation matrix +RMDEF void QuaternionToAxisAngle(Quaternion q, Vector3 *outAxis, float *outAngle); // Returns the rotation angle and axis for a given quaternion +RMDEF Quaternion QuaternionFromEuler(float roll, float pitch, float yaw); // Returns he quaternion equivalent to Euler angles +RMDEF Vector3 QuaternionToEuler(Quaternion q); // Return the Euler angles equivalent to quaternion (roll, pitch, yaw) +RMDEF void QuaternionTransform(Quaternion *q, Matrix mat); // Transform a quaternion given a transformation matrix #endif // notdef RAYMATH_EXTERN_INLINE @@ -1180,6 +1182,51 @@ RMDEF void QuaternionToAxisAngle(Quaternion q, Vector3 *outAxis, float *outAngle *outAngle = resAngle; } +// Returns he quaternion equivalent to Euler angles +RMDEF Quaternion QuaternionFromEuler(float roll, float pitch, float yaw) +{ + Quaternion q = { 0 }; + + float x0 = cosf(roll*0.5f); + float x1 = sinf(roll*0.5f); + float y0 = cosf(pitch*0.5f); + float y1 = sinf(pitch*0.5f); + float z0 = cosf(yaw*0.5f); + float z1 = sinf(yaw*0.5f); + + q.x = x1*y0*z0 - x0*y1*z1; + 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; +} + +// Return the Euler angles equivalent to quaternion (roll, pitch, yaw) +// NOTE: Angles are returned in a Vector3 struct and in degrees +RMDEF Vector3 QuaternionToEuler(Quaternion q) +{ + Vector3 v = { 0 }; + + // roll (x-axis rotation) + float x0 = 2.0f*(q.w*q.x + q.y*q.z); + float x1 = 1.0f - 2.0f*(q.x*q.x + q.y*q.y); + v.x = atan2f(x0, x1)*RAD2DEG; + + // pitch (y-axis rotation) + float y0 = 2.0f*(q.w*q.y - q.z*q.x); + y0 = y0 > 1.0f ? 1.0f : y0; + y0 = y0 < -1.0f ? -1.0f : y0; + v.y = asinf(y0)*RAD2DEG; + + // yaw (z-axis rotation) + float z0 = 2.0f*(q.w*q.z + q.x*q.y); + float z1 = 1.0f - 2.0f*(q.y*q.y + q.z*q.z); + v.z = atan2f(z0, z1)*RAD2DEG; + + return v; +} + // Transform a quaternion given a transformation matrix RMDEF void QuaternionTransform(Quaternion *q, Matrix mat) { @@ -64,15 +64,15 @@ #include <stdio.h> // Required for: fopen(), fclose(), fread()... [Used only on LoadText()] #include <stdlib.h> // Required for: malloc(), free(), rand() -#include <string.h> // Required for: strcmp(), strlen(), strtok() +#include <string.h> // Required for: strcmp(), strlen(), strtok() [Used only in extensions loading] #include <math.h> // Required for: atan2() -#ifndef RLGL_STANDALONE +#if !defined(RLGL_STANDALONE) #include "raymath.h" // Required for: Vector3 and Matrix functions #endif #if defined(GRAPHICS_API_OPENGL_11) - #ifdef __APPLE__ + #if defined(__APPLE__) #include <OpenGL/gl.h> // OpenGL 1.1 library for OSX #else #include <GL/gl.h> // OpenGL 1.1 library @@ -84,7 +84,7 @@ #endif #if defined(GRAPHICS_API_OPENGL_33) - #ifdef __APPLE__ + #if defined(__APPLE__) #include <OpenGL/gl3.h> // OpenGL 3 library for OSX #else #define GLAD_IMPLEMENTATION @@ -317,7 +317,8 @@ static PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArrays; // Compressed textures support flags static bool texCompDXTSupported = false; // DDS texture compression support -static bool npotSupported = false; // NPOT textures full support +static bool texNPOTSupported = false; // NPOT textures full support +static bool texFloatSupported = false; // float textures support (32 bit per channel) static int blendMode = 0; // Track current blending mode @@ -1050,7 +1051,7 @@ void rlglInit(int width, int height) // NOTE: On OpenGL 3.3 VAO and NPOT are supported by default vaoSupported = true; - npotSupported = true; + texNPOTSupported = true; // We get a list of available extensions and we check for some of them (compressed textures) // NOTE: We don't need to check again supported extensions but we do (GLAD already dealt with that) @@ -1119,7 +1120,10 @@ 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) npotSupported = true; + if (strcmp(extList[i], (const char *)"GL_OES_texture_npot") == 0) texNPOTSupported = true; + + // Check texture float support + if (strcmp(extList[i], (const char *)"OES_texture_float") == 0) texFloatSupported = true; #endif // DDS texture compression support @@ -1159,7 +1163,7 @@ void rlglInit(int width, int height) if (vaoSupported) TraceLog(INFO, "[EXTENSION] VAO extension detected, VAO functions initialized successfully"); else TraceLog(WARNING, "[EXTENSION] VAO extension not found, VAO usage not supported"); - if (npotSupported) TraceLog(INFO, "[EXTENSION] NPOT textures extension detected, full NPOT textures supported"); + if (texNPOTSupported) TraceLog(INFO, "[EXTENSION] NPOT textures extension detected, full NPOT textures supported"); else TraceLog(WARNING, "[EXTENSION] NPOT textures extension not found, limited NPOT support (no-mipmaps, no-repeat)"); #endif @@ -1286,21 +1290,17 @@ void rlglLoadExtensions(void *loader) { #if defined(GRAPHICS_API_OPENGL_21) || defined(GRAPHICS_API_OPENGL_33) // NOTE: glad is generated and contains only required OpenGL 3.3 Core extensions (and lower versions) - #ifndef __APPLE__ + #if !defined(__APPLE__) if (!gladLoadGLLoader((GLADloadproc)loader)) TraceLog(WARNING, "GLAD: Cannot load OpenGL extensions"); else TraceLog(INFO, "GLAD: OpenGL extensions loaded successfully"); - #endif -#if defined(GRAPHICS_API_OPENGL_21) - #ifndef __APPLE__ + #if defined(GRAPHICS_API_OPENGL_21) if (GLAD_GL_VERSION_2_1) TraceLog(INFO, "OpenGL 2.1 profile supported"); - #endif -#elif defined(GRAPHICS_API_OPENGL_33) - #ifndef __APPLE__ + #elif defined(GRAPHICS_API_OPENGL_33) if(GLAD_GL_VERSION_3_3) TraceLog(INFO, "OpenGL 3.3 Core profile supported"); else TraceLog(ERROR, "OpenGL 3.3 Core profile not supported"); + #endif #endif -#endif // With GLAD, we can check if an extension is supported using the GLAD_GL_xxx booleans //if (GLAD_GL_ARB_vertex_array_object) // Use GL_ARB_vertex_array_object @@ -1425,6 +1425,7 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int format, int case UNCOMPRESSED_R5G5B5A1: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5_A1, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, (unsigned short *)data); break; case UNCOMPRESSED_R4G4B4A4: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA4, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, (unsigned short *)data); break; case UNCOMPRESSED_R8G8B8A8: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)data); break; + case UNCOMPRESSED_R32G32B32: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, width, height, 0, GL_RGB, GL_FLOAT, (float *)data); break; case COMPRESSED_DXT1_RGB: if (texCompDXTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGB_S3TC_DXT1_EXT); break; case COMPRESSED_DXT1_RGBA: if (texCompDXTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT); break; case COMPRESSED_DXT3_RGBA: if (texCompDXTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT); break; @@ -1450,6 +1451,7 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int format, int case UNCOMPRESSED_R4G4B4A4: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, (unsigned short *)data); break; case UNCOMPRESSED_R8G8B8A8: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)data); break; #if defined(GRAPHICS_API_OPENGL_ES2) + case UNCOMPRESSED_R32G32B32: if (texFloatSupported) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_FLOAT, (float *)data); break; // Requries extension OES_texture_float case COMPRESSED_DXT1_RGB: if (texCompDXTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGB_S3TC_DXT1_EXT); break; case COMPRESSED_DXT1_RGBA: if (texCompDXTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT); break; case COMPRESSED_DXT3_RGBA: if (texCompDXTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT); break; // NOTE: Not supported by WebGL @@ -1470,7 +1472,7 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int format, int // NOTE: glTexParameteri does NOT affect texture uploading, just the way it's used #if defined(GRAPHICS_API_OPENGL_ES2) // NOTE: OpenGL ES 2.0 with no GL_OES_texture_npot support (i.e. WebGL) has limited NPOT support, so CLAMP_TO_EDGE must be used - if (npotSupported) + if (texNPOTSupported) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Set texture to repeat on x-axis glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // Set texture to repeat on y-axis @@ -1650,7 +1652,7 @@ void rlglGenerateMipmaps(Texture2D *texture) if (((texture->width > 0) && ((texture->width & (texture->width - 1)) == 0)) && ((texture->height > 0) && ((texture->height & (texture->height - 1)) == 0))) texIsPOT = true; - if ((texIsPOT) || (npotSupported)) + if ((texIsPOT) || (texNPOTSupported)) { #if defined(GRAPHICS_API_OPENGL_11) // Compute required mipmaps @@ -17,7 +17,9 @@ * #define GRAPHICS_API_OPENGL_21 * #define GRAPHICS_API_OPENGL_33 * #define GRAPHICS_API_OPENGL_ES2 -* Use selected OpenGL backend +* Use selected OpenGL graphics backend, should be supported by platform +* 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 * Use rlgl as standalone library (no raylib dependency) @@ -35,7 +37,7 @@ * * LICENSE: zlib/libpng * -* Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2017 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event * will the authors be held liable for any damages arising from the use of this software. @@ -57,28 +59,14 @@ #ifndef RLGL_H #define RLGL_H -//#define RLGL_STANDALONE // NOTE: To use rlgl as standalone lib, just uncomment this line - -#ifndef RLGL_STANDALONE - #include "raylib.h" // Required for: Model, Shader, Texture2D - #include "utils.h" // Required for: TraceLog() -#endif - -#ifdef RLGL_STANDALONE +#if defined(RLGL_STANDALONE) #define RAYMATH_STANDALONE +#else + #include "raylib.h" // Required for: Model, Shader, Texture2D, TraceLog() #endif #include "raymath.h" // Required for: Vector3, Matrix -// Select desired OpenGL version -// NOTE: Those preprocessor defines are only used on rlgl module, -// if OpenGL version is required by any other module, it uses rlGetVersion() - -// Choose opengl version here or just define it at compile time: -DGRAPHICS_API_OPENGL_33 -//#define GRAPHICS_API_OPENGL_11 // Only available on PLATFORM_DESKTOP -//#define GRAPHICS_API_OPENGL_33 // Only available on PLATFORM_DESKTOP and RLGL_OCULUS_SUPPORT -//#define GRAPHICS_API_OPENGL_ES2 // Only available on PLATFORM_ANDROID or PLATFORM_RPI or PLATFORM_WEB - // Security check in case no GRAPHICS_API_OPENGL_* defined #if !defined(GRAPHICS_API_OPENGL_11) && !defined(GRAPHICS_API_OPENGL_21) && !defined(GRAPHICS_API_OPENGL_33) && !defined(GRAPHICS_API_OPENGL_ES2) #define GRAPHICS_API_OPENGL_11 @@ -165,28 +153,23 @@ typedef unsigned char byte; unsigned char b; unsigned char a; } Color; + + // Texture2D type + // NOTE: Data stored in GPU memory + typedef struct Texture2D { + unsigned int id; // OpenGL texture id + int width; // Texture base width + int height; // Texture base height + int mipmaps; // Mipmap levels, 1 by default + int format; // Data format (TextureFormat) + } Texture2D; - // Texture formats (support depends on OpenGL version) - typedef enum { - UNCOMPRESSED_GRAYSCALE = 1, // 8 bit per pixel (no alpha) - UNCOMPRESSED_GRAY_ALPHA, - UNCOMPRESSED_R5G6B5, // 16 bpp - UNCOMPRESSED_R8G8B8, // 24 bpp - UNCOMPRESSED_R5G5B5A1, // 16 bpp (1 bit alpha) - UNCOMPRESSED_R4G4B4A4, // 16 bpp (4 bit alpha) - UNCOMPRESSED_R8G8B8A8, // 32 bpp - COMPRESSED_DXT1_RGB, // 4 bpp (no alpha) - COMPRESSED_DXT1_RGBA, // 4 bpp (1 bit alpha) - COMPRESSED_DXT3_RGBA, // 8 bpp - COMPRESSED_DXT5_RGBA, // 8 bpp - COMPRESSED_ETC1_RGB, // 4 bpp - COMPRESSED_ETC2_RGB, // 4 bpp - COMPRESSED_ETC2_EAC_RGBA, // 8 bpp - COMPRESSED_PVRT_RGB, // 4 bpp - COMPRESSED_PVRT_RGBA, // 4 bpp - COMPRESSED_ASTC_4x4_RGBA, // 8 bpp - COMPRESSED_ASTC_8x8_RGBA // 2 bpp - } TextureFormat; + // RenderTexture2D type, for texture rendering + typedef struct RenderTexture2D { + unsigned int id; // Render texture (fbo) id + Texture2D texture; // Color buffer attachment texture + Texture2D depth; // Depth buffer attachment texture + } RenderTexture2D; // Vertex data definning a mesh typedef struct Mesh { @@ -228,23 +211,6 @@ typedef unsigned char byte; int mapTexture2Loc; // Map texture uniform location point (default-texture-unit = 2) } Shader; - // Texture2D type - // NOTE: Data stored in GPU memory - typedef struct Texture2D { - unsigned int id; // OpenGL texture id - int width; // Texture base width - int height; // Texture base height - int mipmaps; // Mipmap levels, 1 by default - int format; // Data format (TextureFormat) - } Texture2D; - - // RenderTexture2D type, for texture rendering - typedef struct RenderTexture2D { - unsigned int id; // Render texture (fbo) id - Texture2D texture; // Color buffer attachment texture - Texture2D depth; // Depth buffer attachment texture - } RenderTexture2D; - // Material type typedef struct Material { Shader shader; // Standard shader (supports 3 map types: diffuse, normal, specular) @@ -267,6 +233,38 @@ typedef unsigned char byte; Vector3 up; // Camera up vector (rotation over its axis) float fovy; // Camera field-of-view apperture in Y (degrees) } Camera; + + // TraceLog message types + typedef enum { + INFO = 0, + ERROR, + WARNING, + DEBUG, + OTHER + } TraceLogType; + + // Texture formats (support depends on OpenGL version) + typedef enum { + UNCOMPRESSED_GRAYSCALE = 1, // 8 bit per pixel (no alpha) + UNCOMPRESSED_GRAY_ALPHA, + UNCOMPRESSED_R5G6B5, // 16 bpp + UNCOMPRESSED_R8G8B8, // 24 bpp + UNCOMPRESSED_R5G5B5A1, // 16 bpp (1 bit alpha) + UNCOMPRESSED_R4G4B4A4, // 16 bpp (4 bit alpha) + UNCOMPRESSED_R8G8B8A8, // 32 bpp + UNCOMPRESSED_R32G32B32, // 32 bit per channel (float) - HDR + COMPRESSED_DXT1_RGB, // 4 bpp (no alpha) + COMPRESSED_DXT1_RGBA, // 4 bpp (1 bit alpha) + COMPRESSED_DXT3_RGBA, // 8 bpp + COMPRESSED_DXT5_RGBA, // 8 bpp + COMPRESSED_ETC1_RGB, // 4 bpp + COMPRESSED_ETC2_RGB, // 4 bpp + COMPRESSED_ETC2_EAC_RGBA, // 8 bpp + COMPRESSED_PVRT_RGB, // 4 bpp + COMPRESSED_PVRT_RGBA, // 4 bpp + COMPRESSED_ASTC_4x4_RGBA, // 8 bpp + COMPRESSED_ASTC_8x8_RGBA // 2 bpp + } TextureFormat; // Texture parameters: filter mode // NOTE 1: Filtering considers mipmaps if available in the texture @@ -281,13 +279,18 @@ typedef unsigned char byte; } TextureFilterMode; // Texture parameters: wrap mode - typedef enum { WRAP_REPEAT = 0, WRAP_CLAMP, WRAP_MIRROR } TextureWrapMode; + typedef enum { + WRAP_REPEAT = 0, + WRAP_CLAMP, + WRAP_MIRROR + } TextureWrapMode; // Color blending modes (pre-defined) - typedef enum { BLEND_ALPHA = 0, BLEND_ADDITIVE, BLEND_MULTIPLIED } BlendMode; - - // TraceLog message types - typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType; + typedef enum { + BLEND_ALPHA = 0, + BLEND_ADDITIVE, + BLEND_MULTIPLIED + } BlendMode; // VR Head Mounted Display devices typedef enum { @@ -443,7 +443,7 @@ void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, float index = GetCharIndex(spriteFont, (int)letter + 64); i++; } - else index = GetCharIndex(spriteFont, (int)text[i]); + else index = GetCharIndex(spriteFont, (unsigned char)text[i]); DrawTexturePro(spriteFont.texture, spriteFont.chars[index].rec, (Rectangle){ position.x + textOffsetX + spriteFont.chars[index].offsetX*scaleFactor, diff --git a/src/textures.c b/src/textures.c index 6c56d6c5..115c8fff 100644 --- a/src/textures.c +++ b/src/textures.c @@ -53,6 +53,7 @@ // Default configuration flags (supported features) //------------------------------------------------- #define SUPPORT_FILEFORMAT_PNG +#define SUPPORT_FILEFORMAT_HDR #define SUPPORT_IMAGE_MANIPULATION //------------------------------------------------- @@ -98,7 +99,7 @@ defined(SUPPORT_FILEFORMAT_JPG) || defined(SUPPORT_FILEFORMAT_PSD) || defined(SUPPORT_FILEFORMAT_GIF) || \ defined(SUPPORT_FILEFORMAT_HDR)) #define STB_IMAGE_IMPLEMENTATION - #include "external/stb_image.h" // Required for: stbi_load() + #include "external/stb_image.h" // Required for: stbi_load_from_file() // NOTE: Used to read image data (multiple formats support) #endif @@ -154,14 +155,7 @@ static Image LoadASTC(const char *fileName); // Load ASTC file // Load image from file into CPU memory (RAM) Image LoadImage(const char *fileName) { - Image image; - - // Initialize image default values - image.data = NULL; - image.width = 0; - image.height = 0; - image.mipmaps = 0; - image.format = 0; + Image image = { 0 }; if (IsFileExtension(fileName, ".rres")) { @@ -212,6 +206,29 @@ Image LoadImage(const char *fileName) else if (imgBpp == 3) image.format = UNCOMPRESSED_R8G8B8; else if (imgBpp == 4) image.format = UNCOMPRESSED_R8G8B8A8; } +#if defined(SUPPORT_FILEFORMAT_HDR) + else if (IsFileExtension(fileName, ".hdr")) + { + int imgBpp = 0; + + FILE *imFile = fopen(fileName, "rb"); + + // Load 32 bit per channel floats data + image.data = stbi_loadf_from_file(imFile, &image.width, &image.height, &imgBpp, 0); + + fclose(imFile); + + image.mipmaps = 1; + + if (imgBpp == 3) image.format = UNCOMPRESSED_R32G32B32; + else + { + // TODO: Support different number of channels at 32 bit float + TraceLog(WARNING, "[%s] Image fileformat not supported (only 3 channel 32 bit floats)", fileName); + UnloadImage(image); + } + } +#endif #if defined(SUPPORT_FILEFORMAT_DDS) else if (IsFileExtension(fileName, ".dds")) image = LoadDDS(fileName); #endif @@ -282,13 +299,7 @@ Image LoadImagePro(void *data, int width, int height, int format) // Load an image from RAW file data Image LoadImageRaw(const char *fileName, int width, int height, int format, int headerSize) { - Image image; - - image.data = NULL; - image.width = 0; - image.height = 0; - image.mipmaps = 0; - image.format = 0; + Image image = { 0 }; FILE *rawFile = fopen(fileName, "rb"); @@ -311,6 +322,7 @@ Image LoadImageRaw(const char *fileName, int width, int height, int format, int case UNCOMPRESSED_R5G5B5A1: image.data = (unsigned short *)malloc(size); break; // 16 bpp (1 bit alpha) case UNCOMPRESSED_R4G4B4A4: image.data = (unsigned short *)malloc(size); break; // 16 bpp (4 bit alpha) case UNCOMPRESSED_R8G8B8A8: image.data = (unsigned char *)malloc(size*4); size *= 4; break; // 32 bpp + case UNCOMPRESSED_R32G32B32: image.data = (float *)malloc(size*12); size *= 12; break; // 4 byte per channel (12 byte) default: TraceLog(WARNING, "Image format not suported"); break; } @@ -342,7 +354,7 @@ Image LoadImageRaw(const char *fileName, int width, int height, int format, int // Load texture from file into GPU memory (VRAM) Texture2D LoadTexture(const char *fileName) { - Texture2D texture; + Texture2D texture = { 0 }; Image image = LoadImage(fileName); @@ -351,11 +363,7 @@ Texture2D LoadTexture(const char *fileName) texture = LoadTextureFromImage(image); UnloadImage(image); } - else - { - TraceLog(WARNING, "Texture could not be created"); - texture.id = 0; - } + else TraceLog(WARNING, "Texture could not be created"); return texture; } @@ -364,14 +372,7 @@ Texture2D LoadTexture(const char *fileName) // NOTE: image is not unloaded, it must be done manually Texture2D LoadTextureFromImage(Image image) { - Texture2D texture; - - // Init texture to default values - texture.id = 0; - texture.width = 0; - texture.height = 0; - texture.mipmaps = 0; - texture.format = 0; + Texture2D texture = { 0 }; texture.id = rlglLoadTexture(image.data, image.width, image.height, image.format, image.mipmaps); @@ -510,9 +511,8 @@ Color *GetImageData(Image image) // NOTE: Compressed texture formats not supported Image GetTextureData(Texture2D texture) { - Image image; - image.data = NULL; - + Image image = { 0 }; + if (texture.format < 8) { image.data = rlglReadTexturePixels(texture); @@ -787,6 +787,7 @@ Image ImageCopy(Image image) case UNCOMPRESSED_R4G4B4A4: byteSize *= 2; break; // 16 bpp (2 bytes) case UNCOMPRESSED_R8G8B8: byteSize *= 3; break; // 24 bpp (3 bytes) case UNCOMPRESSED_R8G8B8A8: byteSize *= 4; break; // 32 bpp (4 bytes) + case UNCOMPRESSED_R32G32B32: byteSize *= 12; break; // 4 byte per channel (12 bytes) case COMPRESSED_DXT3_RGBA: case COMPRESSED_DXT5_RGBA: case COMPRESSED_ETC2_EAC_RGBA: |
