From 29d8b48503f3064cdc1f3a87c01b4264e716a220 Mon Sep 17 00:00:00 2001 From: Palaui Date: Tue, 9 Dec 2014 13:10:05 +0100 Subject: Corrected some bugs... [core] Added SetMousePosition() [models] LoadHeightmap() - Corrected textures bug [raymath] Functions renaming [WEB] Prepare environment for emscripten! --- src/makefile | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) (limited to 'src/makefile') diff --git a/src/makefile b/src/makefile index bb37748a..76984bbe 100644 --- a/src/makefile +++ b/src/makefile @@ -24,7 +24,7 @@ #************************************************************************************************** # define raylib platform (by default, compile for RPI) -# Other possible platforms: PLATFORM_DESKTOP PLATFORM_DESKTOP_LINUX +# Other possible platforms: PLATFORM_DESKTOP_WIN PLATFORM_DESKTOP_LINUX PLATFORM_DESKTOP_MAC PLATFORM_WEB PLATFORM ?= PLATFORM_RPI # define raylib graphics api depending on selected platform @@ -40,16 +40,26 @@ endif # NOTE: makefiles targets require tab indentation # define compiler: gcc for C program, define as g++ for C++ -CC = gcc +ifeq ($(PLATFORM),PLATFORM_WEB) + # define emscripten compiler + CC = emcc +else + # define default gcc compiler + CC = gcc +endif # define compiler flags: # -O2 defines optimization level # -Wall turns on most, but not all, compiler warnings # -std=c99 use standard C from 1999 revision +ifeq ($(PLATFORM),PLATFORM_WEB) + CFLAGS = -O3 -s USE_GLFW=3 -s LEGACY_GL_EMULATION=1 +else ifeq ($(PLATFORM),PLATFORM_RPI) CFLAGS = -O2 -Wall -std=gnu99 -fgnu89-inline else - CFLAGS = -O2 -Wall -std=c99 -fgnu89-inline + CFLAGS = -O2 -Wall -std=c99 +endif endif #CFLAGSEXTRA = -Wextra -Wmissing-prototypes -Wstrict-prototypes @@ -69,11 +79,16 @@ default: raylib # compile raylib library raylib: $(OBJS) +ifeq ($(PLATFORM),PLATFORM_WEB) + emcc $(OBJS) -o raylib.bc +else ar rcs libraylib.a $(OBJS) +endif # compile core module +# emcc core.c -o core.bc -DPLATFORM_DESKTOP core.o: core.c - $(CC) -c core.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) + $(CC) -c core.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) -D$(GRAPHICS) # compile rlgl module rlgl.o: rlgl.c @@ -85,19 +100,19 @@ raymath.o: raymath.c # compile shapes module shapes.o: shapes.c - $(CC) -c shapes.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) + $(CC) -c shapes.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) -D$(GRAPHICS) # compile textures module textures.o: textures.c - $(CC) -c textures.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) + $(CC) -c textures.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) -D$(GRAPHICS) # compile text module text.o: text.c - $(CC) -c text.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) + $(CC) -c text.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) -D$(GRAPHICS) # compile models module models.o: models.c - $(CC) -c models.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) + $(CC) -c models.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) -D$(GRAPHICS) # compile audio module audio.o: audio.c -- cgit v1.2.3 From a2c8ddca1345722603637bddc3421f64025d7e5e Mon Sep 17 00:00:00 2001 From: Palaui Date: Tue, 9 Dec 2014 13:10:28 +0100 Subject: Revert "Corrected some bugs..." This reverts commit 29d8b48503f3064cdc1f3a87c01b4264e716a220. --- src/core.c | 11 +---------- src/makefile | 31 ++++++++----------------------- src/models.c | 2 +- src/raylib.h | 1 - src/raymath.h | 4 ++-- src/rlgl.c | 8 +------- 6 files changed, 13 insertions(+), 44 deletions(-) (limited to 'src/makefile') diff --git a/src/core.c b/src/core.c index 62ab5cbb..dec08eeb 100644 --- a/src/core.c +++ b/src/core.c @@ -165,7 +165,7 @@ static const char *windowTitle; // Window text title... static char configFlags = 0; static bool customCursor = false; // Tracks if custom cursor has been set -static bool cursorOnScreen = false; // Tracks if cursor is inside client area +static bool cursorOnScreen = true; // Tracks if cursor is inside client area static Texture2D cursor; // Cursor texture static Vector2 mousePosition; @@ -727,15 +727,6 @@ Vector2 GetMousePosition(void) return mousePosition; } -// Set mouse position XY -void SetMousePosition(Vector2 position) -{ - mousePosition = position; -#if defined(PLATFORM_DESKTOP) - glfwSetCursorPos(window, position.x, position.y); -#endif -} - // Returns mouse wheel movement Y int GetMouseWheelMove(void) { diff --git a/src/makefile b/src/makefile index 76984bbe..bb37748a 100644 --- a/src/makefile +++ b/src/makefile @@ -24,7 +24,7 @@ #************************************************************************************************** # define raylib platform (by default, compile for RPI) -# Other possible platforms: PLATFORM_DESKTOP_WIN PLATFORM_DESKTOP_LINUX PLATFORM_DESKTOP_MAC PLATFORM_WEB +# Other possible platforms: PLATFORM_DESKTOP PLATFORM_DESKTOP_LINUX PLATFORM ?= PLATFORM_RPI # define raylib graphics api depending on selected platform @@ -40,26 +40,16 @@ endif # NOTE: makefiles targets require tab indentation # define compiler: gcc for C program, define as g++ for C++ -ifeq ($(PLATFORM),PLATFORM_WEB) - # define emscripten compiler - CC = emcc -else - # define default gcc compiler - CC = gcc -endif +CC = gcc # define compiler flags: # -O2 defines optimization level # -Wall turns on most, but not all, compiler warnings # -std=c99 use standard C from 1999 revision -ifeq ($(PLATFORM),PLATFORM_WEB) - CFLAGS = -O3 -s USE_GLFW=3 -s LEGACY_GL_EMULATION=1 -else ifeq ($(PLATFORM),PLATFORM_RPI) CFLAGS = -O2 -Wall -std=gnu99 -fgnu89-inline else - CFLAGS = -O2 -Wall -std=c99 -endif + CFLAGS = -O2 -Wall -std=c99 -fgnu89-inline endif #CFLAGSEXTRA = -Wextra -Wmissing-prototypes -Wstrict-prototypes @@ -79,16 +69,11 @@ default: raylib # compile raylib library raylib: $(OBJS) -ifeq ($(PLATFORM),PLATFORM_WEB) - emcc $(OBJS) -o raylib.bc -else ar rcs libraylib.a $(OBJS) -endif # compile core module -# emcc core.c -o core.bc -DPLATFORM_DESKTOP core.o: core.c - $(CC) -c core.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) -D$(GRAPHICS) + $(CC) -c core.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) # compile rlgl module rlgl.o: rlgl.c @@ -100,19 +85,19 @@ raymath.o: raymath.c # compile shapes module shapes.o: shapes.c - $(CC) -c shapes.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) -D$(GRAPHICS) + $(CC) -c shapes.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) # compile textures module textures.o: textures.c - $(CC) -c textures.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) -D$(GRAPHICS) + $(CC) -c textures.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) # compile text module text.o: text.c - $(CC) -c text.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) -D$(GRAPHICS) + $(CC) -c text.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) # compile models module models.o: models.c - $(CC) -c models.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) -D$(GRAPHICS) + $(CC) -c models.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) # compile audio module audio.o: audio.c diff --git a/src/models.c b/src/models.c index f59a7b43..2d2af038 100644 --- a/src/models.c +++ b/src/models.c @@ -743,7 +743,7 @@ Model LoadHeightmap(Image heightmap, float maxHeight) vData.texcoords[tcCounter + 7] = vData.texcoords[tcCounter + 5]; vData.texcoords[tcCounter + 8] = vData.texcoords[tcCounter + 2]; - vData.texcoords[tcCounter + 9] = vData.texcoords[tcCounter + 3]; + vData.texcoords[tcCounter + 9] = vData.texcoords[tcCounter + 1]; vData.texcoords[tcCounter + 10] = (float)(x+1) / (mapX-1); vData.texcoords[tcCounter + 11] = (float)(z+1) / (mapZ-1); diff --git a/src/raylib.h b/src/raylib.h index e7ef3217..9809d823 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -340,7 +340,6 @@ bool IsMouseButtonUp(int button); // Detect if a mouse but int GetMouseX(void); // Returns mouse position X int GetMouseY(void); // Returns mouse position Y Vector2 GetMousePosition(void); // Returns mouse position XY -void SetMousePosition(Vector2 position); // Set mouse position XY int GetMouseWheelMove(void); // Returns mouse wheel movement Y bool IsGamepadAvailable(int gamepad); // Detect if a gamepad is available diff --git a/src/raymath.h b/src/raymath.h index 334df4f3..c396a347 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -108,8 +108,8 @@ Matrix MatrixAdd(Matrix left, Matrix right); // Add two matrices Matrix MatrixSubstract(Matrix left, Matrix right); // Substract two matrices (left - right) Matrix MatrixTranslate(float x, float y, float z); // Returns translation matrix Matrix MatrixRotate(float angleX, float angleY, float angleZ); // Returns rotation matrix -Matrix MatrixFromAxisAngle(Vector3 axis, float angle); // Returns rotation matrix for an angle around an specified axis -Matrix MatrixFromAxisAngle2(Vector3 axis, float angle); // Returns rotation matrix for an angle around an specified axis (test another implemntation) +Matrix MatrixRotateAroundAxis(Vector3 axis, float angle); // Returns rotation matrix for an angle around an specified axis +Matrix MatrixRotateAroundAxis2(Vector3 axis, float angle); // Returns rotation matrix for an angle around an specified axis (test another implemntation) Matrix MatrixFromQuaternion(Quaternion q); // Returns rotation matrix for a given quaternion Matrix MatrixRotateX(float angle); // Returns x-rotation matrix (angle in radians) Matrix MatrixRotateY(float angle); // Returns y-rotation matrix (angle in radians) diff --git a/src/rlgl.c b/src/rlgl.c index ad6883e0..5e51b2e2 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -301,10 +301,6 @@ void rlRotatef(float angleDeg, float x, float y, float z) if (x == 1) rot = MatrixRotateX(angleDeg*DEG2RAD); else if (y == 1) rot = MatrixRotateY(angleDeg*DEG2RAD); else if (z == 1) rot = MatrixRotateZ(angleDeg*DEG2RAD); - - //Vector3 vec = (Vector3){ 0, 0, 1 }; - //VectorNormalize(&vec); - //rot = MatrixFromAxisAngle(vec, angleDeg*DEG2RAD); // Working MatrixTranspose(&rot); @@ -1309,8 +1305,7 @@ unsigned int rlglLoadTexture(unsigned char *data, int width, int height, bool ge #if defined(GRAPHICS_API_OPENGL_33) // NOTE: We define internal (GPU) format as GL_RGBA8 (probably BGRA8 in practice, driver takes care) - //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); // OpenGL - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); // WebGL + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); #elif defined(GRAPHICS_API_OPENGL_ES2) // NOTE: On embedded systems, we let the driver choose the best internal format glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); @@ -1567,7 +1562,6 @@ static GLuint LoadDefaultShaders(void) char fShaderStr[] = " #version 110 \n" // NOTE: Equivalent to version 100 on ES2 #elif defined(GRAPHICS_API_OPENGL_ES2) char fShaderStr[] = " #version 100 \n" // NOTE: Must be defined this way! 110 doesn't work! - "precision mediump float; \n" // WebGL, required for PLATFORM_WEB #endif "uniform sampler2D texture0; \n" "varying vec2 fragTexCoord; \n" -- cgit v1.2.3 From d3cf316e40b531542b6f55b965f3369d4aca28d6 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Tue, 9 Dec 2014 13:21:55 +0100 Subject: Added features and corrected bugs... [core] Added SetMousePosition() [models] LoadHeightmap() - Corrected textures bug [raymath] Functions renaming [WEB] Prepare environment for emscripten! --- src/core.c | 11 ++++++++++- src/makefile | 31 +++++++++++++++++++++++-------- src/models.c | 2 +- src/raylib.h | 1 + src/raymath.h | 4 ++-- src/rlgl.c | 8 +++++++- 6 files changed, 44 insertions(+), 13 deletions(-) (limited to 'src/makefile') diff --git a/src/core.c b/src/core.c index dec08eeb..62ab5cbb 100644 --- a/src/core.c +++ b/src/core.c @@ -165,7 +165,7 @@ static const char *windowTitle; // Window text title... static char configFlags = 0; static bool customCursor = false; // Tracks if custom cursor has been set -static bool cursorOnScreen = true; // Tracks if cursor is inside client area +static bool cursorOnScreen = false; // Tracks if cursor is inside client area static Texture2D cursor; // Cursor texture static Vector2 mousePosition; @@ -727,6 +727,15 @@ Vector2 GetMousePosition(void) return mousePosition; } +// Set mouse position XY +void SetMousePosition(Vector2 position) +{ + mousePosition = position; +#if defined(PLATFORM_DESKTOP) + glfwSetCursorPos(window, position.x, position.y); +#endif +} + // Returns mouse wheel movement Y int GetMouseWheelMove(void) { diff --git a/src/makefile b/src/makefile index bb37748a..2a905052 100644 --- a/src/makefile +++ b/src/makefile @@ -24,7 +24,7 @@ #************************************************************************************************** # define raylib platform (by default, compile for RPI) -# Other possible platforms: PLATFORM_DESKTOP PLATFORM_DESKTOP_LINUX +# Other possible platforms: PLATFORM_DESKTOP_WIN PLATFORM_DESKTOP_LINUX PLATFORM_WEB PLATFORM ?= PLATFORM_RPI # define raylib graphics api depending on selected platform @@ -40,16 +40,26 @@ endif # NOTE: makefiles targets require tab indentation # define compiler: gcc for C program, define as g++ for C++ -CC = gcc +ifeq ($(PLATFORM),PLATFORM_WEB) + # define emscripten compiler + CC = emcc +else + # define default gcc compiler + CC = gcc +endif # define compiler flags: # -O2 defines optimization level # -Wall turns on most, but not all, compiler warnings # -std=c99 use standard C from 1999 revision +ifeq ($(PLATFORM),PLATFORM_WEB) + CFLAGS = -O3 -s USE_GLFW=3 -s LEGACY_GL_EMULATION=1 +else ifeq ($(PLATFORM),PLATFORM_RPI) CFLAGS = -O2 -Wall -std=gnu99 -fgnu89-inline else - CFLAGS = -O2 -Wall -std=c99 -fgnu89-inline + CFLAGS = -O2 -Wall -std=c99 +endif endif #CFLAGSEXTRA = -Wextra -Wmissing-prototypes -Wstrict-prototypes @@ -69,11 +79,16 @@ default: raylib # compile raylib library raylib: $(OBJS) +ifeq ($(PLATFORM),PLATFORM_WEB) + emcc $(OBJS) -o raylib.bc +else ar rcs libraylib.a $(OBJS) +endif # compile core module +# emcc core.c -o core.bc -DPLATFORM_DESKTOP core.o: core.c - $(CC) -c core.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) + $(CC) -c core.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) -D$(GRAPHICS) # compile rlgl module rlgl.o: rlgl.c @@ -85,19 +100,19 @@ raymath.o: raymath.c # compile shapes module shapes.o: shapes.c - $(CC) -c shapes.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) + $(CC) -c shapes.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) -D$(GRAPHICS) # compile textures module textures.o: textures.c - $(CC) -c textures.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) + $(CC) -c textures.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) -D$(GRAPHICS) # compile text module text.o: text.c - $(CC) -c text.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) + $(CC) -c text.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) -D$(GRAPHICS) # compile models module models.o: models.c - $(CC) -c models.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) + $(CC) -c models.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) -D$(GRAPHICS) # compile audio module audio.o: audio.c diff --git a/src/models.c b/src/models.c index 2d2af038..f59a7b43 100644 --- a/src/models.c +++ b/src/models.c @@ -743,7 +743,7 @@ Model LoadHeightmap(Image heightmap, float maxHeight) vData.texcoords[tcCounter + 7] = vData.texcoords[tcCounter + 5]; vData.texcoords[tcCounter + 8] = vData.texcoords[tcCounter + 2]; - vData.texcoords[tcCounter + 9] = vData.texcoords[tcCounter + 1]; + vData.texcoords[tcCounter + 9] = vData.texcoords[tcCounter + 3]; vData.texcoords[tcCounter + 10] = (float)(x+1) / (mapX-1); vData.texcoords[tcCounter + 11] = (float)(z+1) / (mapZ-1); diff --git a/src/raylib.h b/src/raylib.h index 9809d823..e7ef3217 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -340,6 +340,7 @@ bool IsMouseButtonUp(int button); // Detect if a mouse but int GetMouseX(void); // Returns mouse position X int GetMouseY(void); // Returns mouse position Y Vector2 GetMousePosition(void); // Returns mouse position XY +void SetMousePosition(Vector2 position); // Set mouse position XY int GetMouseWheelMove(void); // Returns mouse wheel movement Y bool IsGamepadAvailable(int gamepad); // Detect if a gamepad is available diff --git a/src/raymath.h b/src/raymath.h index c396a347..334df4f3 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -108,8 +108,8 @@ Matrix MatrixAdd(Matrix left, Matrix right); // Add two matrices Matrix MatrixSubstract(Matrix left, Matrix right); // Substract two matrices (left - right) Matrix MatrixTranslate(float x, float y, float z); // Returns translation matrix Matrix MatrixRotate(float angleX, float angleY, float angleZ); // Returns rotation matrix -Matrix MatrixRotateAroundAxis(Vector3 axis, float angle); // Returns rotation matrix for an angle around an specified axis -Matrix MatrixRotateAroundAxis2(Vector3 axis, float angle); // Returns rotation matrix for an angle around an specified axis (test another implemntation) +Matrix MatrixFromAxisAngle(Vector3 axis, float angle); // Returns rotation matrix for an angle around an specified axis +Matrix MatrixFromAxisAngle2(Vector3 axis, float angle); // Returns rotation matrix for an angle around an specified axis (test another implemntation) Matrix MatrixFromQuaternion(Quaternion q); // Returns rotation matrix for a given quaternion Matrix MatrixRotateX(float angle); // Returns x-rotation matrix (angle in radians) Matrix MatrixRotateY(float angle); // Returns y-rotation matrix (angle in radians) diff --git a/src/rlgl.c b/src/rlgl.c index 5e51b2e2..cfb33989 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -301,6 +301,10 @@ void rlRotatef(float angleDeg, float x, float y, float z) if (x == 1) rot = MatrixRotateX(angleDeg*DEG2RAD); else if (y == 1) rot = MatrixRotateY(angleDeg*DEG2RAD); else if (z == 1) rot = MatrixRotateZ(angleDeg*DEG2RAD); + + //Vector3 vec = (Vector3){ 0, 0, 1 }; + //VectorNormalize(&vec); + //rot = MatrixFromAxisAngle(vec, angleDeg*DEG2RAD); // Working MatrixTranspose(&rot); @@ -1305,7 +1309,8 @@ unsigned int rlglLoadTexture(unsigned char *data, int width, int height, bool ge #if defined(GRAPHICS_API_OPENGL_33) // NOTE: We define internal (GPU) format as GL_RGBA8 (probably BGRA8 in practice, driver takes care) - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); // OpenGL + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); // WebGL #elif defined(GRAPHICS_API_OPENGL_ES2) // NOTE: On embedded systems, we let the driver choose the best internal format glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); @@ -1562,6 +1567,7 @@ static GLuint LoadDefaultShaders(void) char fShaderStr[] = " #version 110 \n" // NOTE: Equivalent to version 100 on ES2 #elif defined(GRAPHICS_API_OPENGL_ES2) char fShaderStr[] = " #version 100 \n" // NOTE: Must be defined this way! 110 doesn't work! + "precision mediump float; \n" // WebGL, required for emscripten #endif "uniform sampler2D texture0; \n" "varying vec2 fragTexCoord; \n" -- cgit v1.2.3 From cfa60ab7e6313f85594f63d2830fdc2ce19e180e Mon Sep 17 00:00:00 2001 From: raysan5 Date: Mon, 15 Dec 2014 01:08:30 +0100 Subject: Added support for emscripten and more Added PLATFORM_WEB support (emscripten-webgl) [audio] Added LoadSoundFromWave() [textures] Added LoadTextureFromImage() to replace CreateTexture() Some TraceLogs edited... --- src/audio.c | 63 ++++++++++++++++++++++++++++----- src/core.c | 55 +++++++++++++++++++---------- src/makefile | 19 +++++----- src/raylib.h | 19 ++++++++-- src/rlgl.c | 16 ++++++--- src/rlgl.h | 2 +- src/text.c | 8 ++--- src/textures.c | 110 ++++++++++++++++++++++++++++++++++----------------------- src/utils.c | 2 ++ 9 files changed, 199 insertions(+), 95 deletions(-) (limited to 'src/makefile') diff --git a/src/audio.c b/src/audio.c index fd482534..d6d16360 100644 --- a/src/audio.c +++ b/src/audio.c @@ -69,15 +69,6 @@ typedef struct Music { } Music; -// Wave file data -typedef struct Wave { - void *data; // Buffer data pointer - unsigned int dataSize; // Data size in bytes - unsigned int sampleRate; - short bitsPerSample; - short channels; -} Wave; - //---------------------------------------------------------------------------------- // Global Variables Definition //---------------------------------------------------------------------------------- @@ -219,6 +210,60 @@ Sound LoadSound(char *fileName) return sound; } +// Load sound from wave data +Sound LoadSoundFromWave(Wave wave) +{ + Sound sound; + + if (wave.data != NULL) + { + ALenum format = 0; + // The OpenAL format is worked out by looking at the number of channels and the bits per sample + if (wave.channels == 1) + { + if (wave.bitsPerSample == 8 ) format = AL_FORMAT_MONO8; + else if (wave.bitsPerSample == 16) format = AL_FORMAT_MONO16; + } + else if (wave.channels == 2) + { + if (wave.bitsPerSample == 8 ) format = AL_FORMAT_STEREO8; + else if (wave.bitsPerSample == 16) format = AL_FORMAT_STEREO16; + } + + // Create an audio source + ALuint source; + alGenSources(1, &source); // Generate pointer to audio source + + alSourcef(source, AL_PITCH, 1); + alSourcef(source, AL_GAIN, 1); + alSource3f(source, AL_POSITION, 0, 0, 0); + alSource3f(source, AL_VELOCITY, 0, 0, 0); + alSourcei(source, AL_LOOPING, AL_FALSE); + + // Convert loaded data to OpenAL buffer + //---------------------------------------- + ALuint buffer; + alGenBuffers(1, &buffer); // Generate pointer to buffer + + // Upload sound data to buffer + alBufferData(buffer, format, wave.data, wave.dataSize, wave.sampleRate); + + // Attach sound buffer to source + alSourcei(source, AL_BUFFER, buffer); + + // Unallocate WAV data + UnloadWave(wave); + + TraceLog(INFO, "[Wave] Sound file loaded successfully"); + TraceLog(INFO, "[Wave] Sample rate: %i - Channels: %i", wave.sampleRate, wave.channels); + + sound.source = source; + sound.buffer = buffer; + } + + return sound; +} + // Load sound to memory from rRES file (raylib Resource) Sound LoadSoundFromRES(const char *rresName, int resId) { diff --git a/src/core.c b/src/core.c index 62ab5cbb..1488072e 100644 --- a/src/core.c +++ b/src/core.c @@ -8,6 +8,7 @@ * PLATFORM_DESKTOP - Windows, Linux, Mac (OSX) * PLATFORM_ANDROID - Only OpenGL ES 2.0 devices * PLATFORM_RPI - Rapsberry Pi (tested on Raspbian) +* PLATFORM_WEB - Emscripten, HTML5 * * On PLATFORM_DESKTOP, the external lib GLFW3 (www.glfw.com) is used to manage graphic * device, OpenGL context and input on multiple operating systems (Windows, Linux, OSX). @@ -49,7 +50,7 @@ #include // String function definitions, memset() #include // Macros for reporting and retrieving error conditions through error codes -#if defined(PLATFORM_DESKTOP) +#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) #include // GLFW3 library: Windows, OpenGL context and Input management //#include // OpenGL functions (GLFW3 already includes gl.h) //#define GLFW_DLL // Using GLFW DLL on Windows -> No, we use static version! @@ -101,7 +102,7 @@ //---------------------------------------------------------------------------------- // Global Variables Definition //---------------------------------------------------------------------------------- -#if defined(PLATFORM_DESKTOP) +#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) static GLFWwindow *window; // Native window (graphic device) #elif defined(PLATFORM_ANDROID) static struct android_app *app; // Android activity @@ -160,7 +161,7 @@ static int renderOffsetY = 0; // Offset Y from render area (must b static bool fullscreen = false; // Fullscreen mode (useful only for PLATFORM_DESKTOP) static Matrix downscaleView; // Matrix to downscale view (in case screen size bigger than display size) -#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) +#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB) static const char *windowTitle; // Window text title... static char configFlags = 0; @@ -226,12 +227,15 @@ static void RestoreKeyboard(void); // Restore keyboard syst static void InitGamepad(void); // Init raw gamepad input #endif -#if defined(PLATFORM_DESKTOP) +#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) static void ErrorCallback(int error, const char *description); // GLFW3 Error Callback, runs on GLFW3 error static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods); // GLFW3 Keyboard Callback, runs on key pressed static void ScrollCallback(GLFWwindow *window, double xoffset, double yoffset); // GLFW3 Srolling Callback, runs on mouse wheel static void CursorEnterCallback(GLFWwindow *window, int enter); // GLFW3 Cursor Enter Callback, cursor enters client area static void WindowSizeCallback(GLFWwindow *window, int width, int height); // GLFW3 WindowSize Callback, runs when window is resized +#endif + +#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) static void TakeScreenshot(void); // Takes a screenshot and saves it in the same folder as executable #endif @@ -243,7 +247,7 @@ static void CommandCallback(struct android_app *app, int32_t cmd); // //---------------------------------------------------------------------------------- // Module Functions Definition - Window and OpenGL Context Functions //---------------------------------------------------------------------------------- -#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) +#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB) // Initialize Window and Graphics Context (OpenGL) void InitWindow(int width, int height, const char *title) { @@ -348,7 +352,7 @@ void CloseWindow(void) rlglClose(); // De-init rlgl -#if defined(PLATFORM_DESKTOP) +#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) glfwDestroyWindow(window); glfwTerminate(); #elif defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) @@ -380,7 +384,7 @@ void CloseWindow(void) // Detect if KEY_ESCAPE pressed or Close icon pressed bool WindowShouldClose(void) { -#if defined(PLATFORM_DESKTOP) +#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) return (glfwWindowShouldClose(window)); #elif defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) return windowShouldClose; @@ -402,7 +406,7 @@ void ToggleFullscreen(void) #endif } -#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) +#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB) // Set a custom cursor icon/image void SetCustomCursor(const char *cursorImage) { @@ -411,6 +415,7 @@ void SetCustomCursor(const char *cursorImage) cursor = LoadTexture(cursorImage); #if defined(PLATFORM_DESKTOP) + // NOTE: emscripten not implemented glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); #endif customCursor = true; @@ -612,7 +617,7 @@ void ShowLogo(void) //---------------------------------------------------------------------------------- // Module Functions Definition - Input (Keyboard, Mouse, Gamepad) Functions //---------------------------------------------------------------------------------- -#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) +#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB) // Detect if a key has been pressed once bool IsKeyPressed(int key) { @@ -731,7 +736,8 @@ Vector2 GetMousePosition(void) void SetMousePosition(Vector2 position) { mousePosition = position; -#if defined(PLATFORM_DESKTOP) +#if defined(PLATFORM_DESKTOP) + // NOTE: emscripten not implemented glfwSetCursorPos(window, position.x, position.y); #endif } @@ -747,7 +753,8 @@ int GetMouseWheelMove(void) } #endif -// TODO: Enable gamepad usage on Rapsberr Pi +// TODO: Enable gamepad usage on Rapsberry Pi +// NOTE: emscripten not implemented #if defined(PLATFORM_DESKTOP) // Detect if a gamepad is available bool IsGamepadAvailable(int gamepad) @@ -890,11 +897,13 @@ static void InitDisplay(int width, int height) // Downscale matrix is required in case desired screen area is bigger than display area downscaleView = MatrixIdentity(); -#if defined(PLATFORM_DESKTOP) +#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) glfwSetErrorCallback(ErrorCallback); if (!glfwInit()) TraceLog(ERROR, "Failed to initialize GLFW"); + // NOTE: Getting video modes is not implemented in emscripten GLFW3 version +#if defined(PLATFORM_DESKTOP) // Find monitor resolution const GLFWvidmode *mode = glfwGetVideoMode(glfwGetPrimaryMonitor()); @@ -904,7 +913,11 @@ static void InitDisplay(int width, int height) // Screen size security check if (screenWidth <= 0) screenWidth = displayWidth; if (screenHeight <= 0) screenHeight = displayHeight; - +#elif defined(PLATFORM_WEB) + displayWidth = screenWidth; + displayHeight = screenHeight; +#endif + glfwDefaultWindowHints(); // Set default windows hints glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); // Avoid window being resizable @@ -953,7 +966,9 @@ static void InitDisplay(int width, int height) else { TraceLog(INFO, "Display device initialized successfully"); +#if defined(PLATFORM_DESKTOP) TraceLog(INFO, "Display size: %i x %i", displayWidth, displayHeight); +#endif TraceLog(INFO, "Render size: %i x %i", renderWidth, renderHeight); TraceLog(INFO, "Screen size: %i x %i", screenWidth, screenHeight); TraceLog(INFO, "Viewport offsets: %i, %i", renderOffsetX, renderOffsetY); @@ -1125,7 +1140,7 @@ void InitGraphics(void) #endif } -#if defined(PLATFORM_DESKTOP) +#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) // GLFW3 Error Callback, runs on GLFW3 error static void ErrorCallback(int error, const char *description) { @@ -1147,10 +1162,12 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i // NOTE: Before closing window, while loop must be left! } +#if defined(PLATFORM_DESKTOP) else if (key == GLFW_KEY_F12 && action == GLFW_PRESS) { TakeScreenshot(); } +#endif } // GLFW3 CursorEnter Callback, when cursor enters the window @@ -1395,7 +1412,7 @@ static void InitTimer(void) // Get current time measure since InitTimer() static double GetTime(void) { -#if defined(PLATFORM_DESKTOP) +#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) return glfwGetTime(); #elif defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) struct timespec ts; @@ -1409,7 +1426,7 @@ static double GetTime(void) // Get one key state static bool GetKeyStatus(int key) { -#if defined(PLATFORM_DESKTOP) +#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) return glfwGetKey(window, key); #elif defined(PLATFORM_ANDROID) // TODO: Check virtual keyboard (?) @@ -1424,7 +1441,7 @@ static bool GetKeyStatus(int key) // Get one mouse button state static bool GetMouseButtonStatus(int button) { -#if defined(PLATFORM_DESKTOP) +#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) return glfwGetMouseButton(window, button); #elif defined(PLATFORM_ANDROID) // TODO: Check virtual keyboard (?) @@ -1438,7 +1455,7 @@ static bool GetMouseButtonStatus(int button) // Poll (store) all input events static void PollInputEvents(void) { -#if defined(PLATFORM_DESKTOP) +#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) // Mouse input polling double mouseX; double mouseY; @@ -1732,7 +1749,7 @@ static void InitGamepad(void) // Copy back buffer to front buffers static void SwapBuffers(void) { -#if defined(PLATFORM_DESKTOP) +#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) glfwSwapBuffers(window); #elif defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) eglSwapBuffers(display, surface); diff --git a/src/makefile b/src/makefile index 2a905052..88d2258c 100644 --- a/src/makefile +++ b/src/makefile @@ -25,7 +25,7 @@ # define raylib platform (by default, compile for RPI) # Other possible platforms: PLATFORM_DESKTOP_WIN PLATFORM_DESKTOP_LINUX PLATFORM_WEB -PLATFORM ?= PLATFORM_RPI +PLATFORM ?= PLATFORM_DESKTOP # define raylib graphics api depending on selected platform ifeq ($(PLATFORM),PLATFORM_RPI) @@ -37,6 +37,10 @@ else #GRAPHICS = GRAPHICS_API_OPENGL_33 # Uncomment to use OpenGL 3.3 endif +ifeq ($(PLATFORM),PLATFORM_WEB) + GRAPHICS = GRAPHICS_API_OPENGL_ES2 +endif + # NOTE: makefiles targets require tab indentation # define compiler: gcc for C program, define as g++ for C++ @@ -52,15 +56,12 @@ endif # -O2 defines optimization level # -Wall turns on most, but not all, compiler warnings # -std=c99 use standard C from 1999 revision -ifeq ($(PLATFORM),PLATFORM_WEB) - CFLAGS = -O3 -s USE_GLFW=3 -s LEGACY_GL_EMULATION=1 -else ifeq ($(PLATFORM),PLATFORM_RPI) - CFLAGS = -O2 -Wall -std=gnu99 -fgnu89-inline + CFLAGS = -O1 -Wall -std=gnu99 -fgnu89-inline else - CFLAGS = -O2 -Wall -std=c99 -endif + CFLAGS = -O1 -Wall -std=c99 endif + #CFLAGSEXTRA = -Wextra -Wmissing-prototypes -Wstrict-prototypes # define any directories containing required header files @@ -80,7 +81,7 @@ default: raylib # compile raylib library raylib: $(OBJS) ifeq ($(PLATFORM),PLATFORM_WEB) - emcc $(OBJS) -o raylib.bc + emcc -O1 $(OBJS) -o raylib.bc else ar rcs libraylib.a $(OBJS) endif @@ -92,7 +93,7 @@ core.o: core.c # compile rlgl module rlgl.o: rlgl.c - $(CC) -c rlgl.c $(CFLAGS) $(INCLUDES) -D$(GRAPHICS) + $(CC) -c rlgl.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) -D$(GRAPHICS) # compile raymath module raymath.o: raymath.c diff --git a/src/raylib.h b/src/raylib.h index e7ef3217..c061a9b0 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -65,7 +65,7 @@ //#define PLATFORM_RPI // Raspberry Pi // Security check in case no PLATFORM_* defined -#if !defined(PLATFORM_DESKTOP) && !defined(PLATFORM_ANDROID) && !defined(PLATFORM_RPI) +#if !defined(PLATFORM_DESKTOP) && !defined(PLATFORM_ANDROID) && !defined(PLATFORM_RPI) && !defined(PLATFORM_WEB) #define PLATFORM_DESKTOP #endif @@ -275,6 +275,15 @@ typedef struct Sound { unsigned int buffer; } Sound; +// Wave type, defines audio wave data +typedef struct Wave { + void *data; // Buffer data pointer + unsigned int dataSize; // Data size in bytes + unsigned int sampleRate; + short bitsPerSample; + short channels; +} Wave; + #ifdef __cplusplus extern "C" { // Prevents name mangling of functions #endif @@ -327,7 +336,7 @@ void ShowLogo(void); // Activates raylib //------------------------------------------------------------------------------------ // Input Handling Functions (Module: core) //------------------------------------------------------------------------------------ -#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) +#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB) bool IsKeyPressed(int key); // Detect if a key has been pressed once bool IsKeyDown(int key); // Detect if a key is being pressed bool IsKeyReleased(int key); // Detect if a key has been released once @@ -342,7 +351,9 @@ int GetMouseY(void); // Returns mouse positio Vector2 GetMousePosition(void); // Returns mouse position XY void SetMousePosition(Vector2 position); // Set mouse position XY int GetMouseWheelMove(void); // Returns mouse wheel movement Y +#endif +#if defined(PLATFORM_DESKTOP) bool IsGamepadAvailable(int gamepad); // Detect if a gamepad is available Vector2 GetGamepadMovement(int gamepad); // Return axis movement vector for a gamepad bool IsGamepadButtonPressed(int gamepad, int button); // Detect if a gamepad button has been pressed once @@ -395,7 +406,8 @@ Image LoadImage(const char *fileName); Image LoadImageFromRES(const char *rresName, int resId); // Load an image from rRES file (raylib Resource) Texture2D LoadTexture(const char *fileName); // Load an image as texture into GPU memory Texture2D LoadTextureFromRES(const char *rresName, int resId); // Load an image as texture from rRES file (raylib Resource) -Texture2D CreateTexture(Image image, bool genMipmaps); // Create a Texture2D from Image data (and generate mipmaps) +Texture2D LoadTextureFromImage(Image image, bool genMipmaps); // Load a texture from image data (and generate mipmaps) +Texture2D CreateTexture(Image image, bool genMipmaps); // [DEPRECATED] Same as LoadTextureFromImage() void UnloadImage(Image image); // Unload image from CPU memory (RAM) void UnloadTexture(Texture2D texture); // Unload texture from GPU memory @@ -465,6 +477,7 @@ void InitAudioDevice(void); // Initialize au void CloseAudioDevice(void); // Close the audio device and context (and music stream) Sound LoadSound(char *fileName); // Load sound to memory +Sound LoadSoundFromWave(Wave wave); // Load sound from wave data Sound LoadSoundFromRES(const char *rresName, int resId); // Load sound to memory from rRES file (raylib Resource) void UnloadSound(Sound sound); // Unload sound void PlaySound(Sound sound); // Play a sound diff --git a/src/rlgl.c b/src/rlgl.c index cfb33989..ddd55a2d 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -177,6 +177,7 @@ static bool vaoSupported = false; #if defined(GRAPHICS_API_OPENGL_ES2) // NOTE: VAO functionality is exposed through extensions (OES) +// emscripten does not support VAOs static PFNGLGENVERTEXARRAYSOESPROC glGenVertexArrays; static PFNGLBINDVERTEXARRAYOESPROC glBindVertexArray; static PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArrays; @@ -764,10 +765,13 @@ void rlglInit(void) #endif #if defined(GRAPHICS_API_OPENGL_ES2) + // NOTE: emscripten does not support VAOs +#if !defined(PLATFORM_WEB) glGenVertexArrays = (PFNGLGENVERTEXARRAYSOESPROC)eglGetProcAddress("glGenVertexArraysOES"); glBindVertexArray = (PFNGLBINDVERTEXARRAYOESPROC)eglGetProcAddress("glBindVertexArrayOES"); glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSOESPROC)eglGetProcAddress("glDeleteVertexArraysOES"); glIsVertexArray = (PFNGLISVERTEXARRAYOESPROC)eglGetProcAddress("glIsVertexArrayOES"); +#endif if (glGenVertexArrays == NULL) TraceLog(WARNING, "Could not initialize VAO extensions, VAOs not supported"); else @@ -852,8 +856,8 @@ void rlglInit(void) whiteTexture = rlglLoadTexture(pixels, 1, 1, false); - if (whiteTexture != 0) TraceLog(INFO, "[TEX ID %i] Base white texture created successfully", whiteTexture); - else TraceLog(WARNING, "Base white texture could not be created"); + if (whiteTexture != 0) TraceLog(INFO, "[TEX ID %i] Base white texture loaded successfully", whiteTexture); + else TraceLog(WARNING, "Base white texture could not be loaded"); // Init draw calls tracking system draws = (DrawCall *)malloc(sizeof(DrawCall)*MAX_DRAWS_BY_TEXTURE); @@ -1352,7 +1356,7 @@ Model rlglLoadModel(VertexData mesh) #elif defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) model.textureId = 1; // Default whiteTexture - GLuint vaoModel; // Vertex Array Objects (VAO) + GLuint vaoModel = 0; // Vertex Array Objects (VAO) GLuint vertexBuffer[3]; // Vertex Buffer Objects (VBO) if (vaoSupported) @@ -1804,7 +1808,7 @@ static void InitializeBuffersGPU(void) glGenVertexArrays(1, &vaoTriangles); glBindVertexArray(vaoTriangles); } - + // Create buffers for our vertex data glGenBuffers(2, trianglesBuffer); @@ -1829,7 +1833,7 @@ static void InitializeBuffersGPU(void) glGenVertexArrays(1, &vaoQuads); glBindVertexArray(vaoQuads); } - + // Create buffers for our vertex data glGenBuffers(4, quadsBuffer); @@ -1865,6 +1869,8 @@ static void InitializeBuffersGPU(void) } // Update VBOs with vertex array data +// TODO: If there is not vertex data, buffers doesn't need to be updated (vertexCount > 0) +// TODO: If no data changed on the CPU arrays --> No need to update GPU arrays every frame! static void UpdateBuffers(void) { // Activate Lines VAO diff --git a/src/rlgl.h b/src/rlgl.h index 2e1d18f4..b1e16f3a 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -45,7 +45,7 @@ // 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 -//#define GRAPHICS_API_OPENGL_ES2 // Only available on PLATFORM_ANDROID or PLATFORM_RPI +//#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_33) && !defined(GRAPHICS_API_OPENGL_ES2) diff --git a/src/text.c b/src/text.c index 8b7e5b12..bc5eb7d3 100644 --- a/src/text.c +++ b/src/text.c @@ -135,7 +135,7 @@ extern void LoadDefaultFont(void) if (counter > 256) counter = 0; // Security check... } - defaultFont.texture = CreateTexture(image, false); // Convert loaded image to OpenGL texture + defaultFont.texture = LoadTextureFromImage(image, false); // Convert loaded image to OpenGL texture UnloadImage(image); // Reconstruct charSet using charsWidth[], charsHeight, charsDivisor, numChars @@ -168,7 +168,7 @@ extern void LoadDefaultFont(void) else currentPosX = testPosX; } - TraceLog(INFO, "Default font loaded successfully"); + TraceLog(INFO, "[TEX ID %i] Default font loaded successfully", defaultFont.texture.id); } extern void UnloadDefaultFont(void) @@ -240,7 +240,7 @@ SpriteFont LoadSpriteFont(const char *fileName) image.height = potHeight; } */ - spriteFont.texture = CreateTexture(image, false); // Convert loaded image to OpenGL texture + spriteFont.texture = LoadTextureFromImage(image, false); // Convert loaded image to OpenGL texture UnloadImage(image); } @@ -566,7 +566,7 @@ static SpriteFont LoadRBMF(const char *fileName) TraceLog(INFO, "[%s] Image reconstructed correctly, now converting it to texture", fileName); - spriteFont.texture = CreateTexture(image, false); + spriteFont.texture = LoadTextureFromImage(image, false); UnloadImage(image); // Unload image data TraceLog(INFO, "[%s] Starting charSet reconstruction", fileName); diff --git a/src/textures.c b/src/textures.c index 929cba78..1f9ca6ae 100644 --- a/src/textures.c +++ b/src/textures.c @@ -175,8 +175,6 @@ Image LoadImage(const char *fileName) // Load an image from rRES file (raylib Resource) Image LoadImageFromRES(const char *rresName, int resId) { - // TODO: rresName could be directly a char array with all the data! --> support it! :P - Image image; bool found = false; @@ -295,6 +293,11 @@ Image LoadImageFromRES(const char *rresName, int resId) Texture2D LoadTexture(const char *fileName) { Texture2D texture; + + // Init texture to default values + texture.id = 0; + texture.width = 0; + texture.height = 0; if (strcmp(GetExtension(fileName),"dds") == 0) { @@ -337,7 +340,7 @@ Texture2D LoadTexture(const char *fileName) if (image.pixels != NULL) { - texture = CreateTexture(image, false); + texture = LoadTextureFromImage(image, false); UnloadImage(image); } } @@ -345,13 +348,66 @@ Texture2D LoadTexture(const char *fileName) return texture; } +// Load a texture from image data +// NOTE: image is not unloaded, it must be done manually +Texture2D LoadTextureFromImage(Image image, bool genMipmaps) +{ + Texture2D texture; + + // Init texture to default values + texture.id = 0; + texture.width = 0; + texture.height = 0; + + if (image.pixels != NULL) + { + unsigned char *imgData = malloc(image.width * image.height * 4); + + int j = 0; + + for (int i = 0; i < image.width * image.height * 4; i += 4) + { + imgData[i] = image.pixels[j].r; + imgData[i+1] = image.pixels[j].g; + imgData[i+2] = image.pixels[j].b; + imgData[i+3] = image.pixels[j].a; + + j++; + } + + // NOTE: rlglLoadTexture() can generate mipmaps (POT image required) + texture.id = rlglLoadTexture(imgData, image.width, image.height, genMipmaps); + + texture.width = image.width; + texture.height = image.height; + + free(imgData); + } + else TraceLog(WARNING, "Texture could not be created, image data is not valid"); + + return texture; +} + +// [DEPRECATED] Load a texture from image data +// NOTE: Use LoadTextureFromImage() instead +Texture2D CreateTexture(Image image, bool genMipmaps) +{ + Texture2D texture; + + texture = LoadTextureFromImage(image, genMipmaps); + + TraceLog(INFO, "Created texture id: %i", texture.id); + + return texture; +} + // Load an image as texture from rRES file (raylib Resource) Texture2D LoadTextureFromRES(const char *rresName, int resId) { Texture2D texture; Image image = LoadImageFromRES(rresName, resId); - texture = CreateTexture(image, false); + texture = LoadTextureFromImage(image, false); UnloadImage(image); return texture; @@ -436,49 +492,13 @@ void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle destRec, V rlDisableTexture(); } -// Create a texture from an image -// NOTE: image is not unloaded, iot must be done manually -Texture2D CreateTexture(Image image, bool genMipmaps) -{ - Texture2D texture; - - // Init texture to default values - texture.id = 0; - texture.width = 0; - texture.height = 0; - - if (image.pixels != NULL) - { - unsigned char *imgData = malloc(image.width * image.height * 4); - - int j = 0; - - for (int i = 0; i < image.width * image.height * 4; i += 4) - { - imgData[i] = image.pixels[j].r; - imgData[i+1] = image.pixels[j].g; - imgData[i+2] = image.pixels[j].b; - imgData[i+3] = image.pixels[j].a; - - j++; - } - - // NOTE: rlglLoadTexture() can generate mipmaps (POT image required) - texture.id = rlglLoadTexture(imgData, image.width, image.height, genMipmaps); - - texture.width = image.width; - texture.height = image.height; - - free(imgData); - } - else TraceLog(WARNING, "Texture could not be created, image data is not valid"); - - return texture; -} +//---------------------------------------------------------------------------------- +// Module specific Functions Definition +//---------------------------------------------------------------------------------- // Loading DDS image data (compressed or uncompressed) // NOTE: Compressed data loading not supported on OpenGL 1.1 -ImageEx LoadDDS(const char *fileName) +static ImageEx LoadDDS(const char *fileName) { #define FOURCC_DXT1 0x31545844 // Equivalent to "DXT1" in ASCII #define FOURCC_DXT3 0x33545844 // Equivalent to "DXT3" in ASCII @@ -636,7 +656,7 @@ ImageEx LoadDDS(const char *fileName) // Loading PKM image data (ETC1/ETC2 compression) // NOTE: KTX is the standard Khronos Group compression format (ETC1/ETC2, mipmaps) // PKM is a much simpler file format used mainly to contain a single ETC1/ETC2 compressed image (no mipmaps) -ImageEx LoadPKM(const char *fileName) +static ImageEx LoadPKM(const char *fileName) { // If OpenGL ES 2.0. the following format could be supported (ETC1): //GL_ETC1_RGB8_OES diff --git a/src/utils.c b/src/utils.c index b5112111..27b72870 100644 --- a/src/utils.c +++ b/src/utils.c @@ -157,7 +157,9 @@ void WritePNG(const char *fileName, unsigned char *imgData, int width, int heigh { stbi_write_png(fileName, width, height, 4, imgData, width*4); // It WORKS!!! } +#endif +#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB) // Outputs a trace log message (INFO, ERROR, WARNING) // NOTE: If a file has been init, output log is written there void TraceLog(int msgType, const char *text, ...) -- cgit v1.2.3 From 905b6ec53df01a4f660c12c08c32e2cc301f7ad6 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Wed, 31 Dec 2014 18:03:32 +0100 Subject: Added full support for HTML5 (emscripten) Corrected some bugs on the way... Automatically convert textures to POT on RPI and WEB --- src/audio.c | 49 ++++++----- src/core.c | 251 ++++++++++++++++++++++++++++++++++++++++++++++++--------- src/makefile | 14 ++-- src/models.c | 42 ++++++++-- src/raylib.h | 12 +-- src/raymath.c | 47 ++++++++++- src/raymath.h | 4 +- src/rlgl.c | 35 ++++---- src/rlgl.h | 5 +- src/shapes.c | 4 +- src/text.c | 174 +++++++++++++++------------------------ src/textures.c | 55 +++++++++++-- src/utils.c | 44 +++++++--- src/utils.h | 1 + 14 files changed, 515 insertions(+), 222 deletions(-) (limited to 'src/makefile') diff --git a/src/audio.c b/src/audio.c index d6d16360..40c24895 100644 --- a/src/audio.c +++ b/src/audio.c @@ -45,9 +45,14 @@ // Defines and Macros //---------------------------------------------------------------------------------- #define MUSIC_STREAM_BUFFERS 2 -#define MUSIC_BUFFER_SIZE 4096*2 // PCM data buffer (short) - 16Kb - // NOTE: Reduced to avoid frame-stalls on RPI -//#define MUSIC_BUFFER_SIZE 4096*8 // PCM data buffer (short) - 64Kb + +#if defined(PLATFORM_RPI) + // NOTE: On RPI should be lower to avoid frame-stalls + #define MUSIC_BUFFER_SIZE 4096*2 // PCM data buffer (short) - 16Kb (RPI) +#else + // NOTE: On HTML5 (emscripten) this is allocated on heap, by default it's only 16MB!...just take care... + #define MUSIC_BUFFER_SIZE 4096*8 // PCM data buffer (short) - 64Kb +#endif //---------------------------------------------------------------------------------- // Types and Structures Definition @@ -97,7 +102,7 @@ void InitAudioDevice(void) // Open and initialize a device with default settings ALCdevice *device = alcOpenDevice(NULL); - if(!device) TraceLog(ERROR, "Could not open audio device"); + if(!device) TraceLog(ERROR, "Audio device could not be opened"); ALCcontext *context = alcCreateContext(device, NULL); @@ -196,13 +201,12 @@ Sound LoadSound(char *fileName) // Attach sound buffer to source alSourcei(source, AL_BUFFER, buffer); + + TraceLog(INFO, "[%s] Sound file loaded successfully (SampleRate: %i, BitRate: %i, Channels: %i)", fileName, wave.sampleRate, wave.bitsPerSample, wave.channels); // Unallocate WAV data UnloadWave(wave); - TraceLog(INFO, "[%s] Sound file loaded successfully", fileName); - TraceLog(INFO, "[%s] Sample rate: %i - Channels: %i", fileName, wave.sampleRate, wave.channels); - sound.source = source; sound.buffer = buffer; } @@ -254,8 +258,7 @@ Sound LoadSoundFromWave(Wave wave) // Unallocate WAV data UnloadWave(wave); - TraceLog(INFO, "[Wave] Sound file loaded successfully"); - TraceLog(INFO, "[Wave] Sample rate: %i - Channels: %i", wave.sampleRate, wave.channels); + TraceLog(INFO, "[Wave] Sound file loaded successfully (SampleRate: %i, BitRate: %i, Channels: %i)", wave.sampleRate, wave.bitsPerSample, wave.channels); sound.source = source; sound.buffer = buffer; @@ -280,7 +283,10 @@ Sound LoadSoundFromRES(const char *rresName, int resId) FILE *rresFile = fopen(rresName, "rb"); - if (!rresFile) TraceLog(WARNING, "[%s] Could not open raylib resource file", rresName); + if (rresFile == NULL) + { + TraceLog(WARNING, "[%s] rRES raylib resource file could not be opened", rresName); + } else { // Read rres file (basic file check - id) @@ -372,12 +378,12 @@ Sound LoadSoundFromRES(const char *rresName, int resId) // Attach sound buffer to source alSourcei(source, AL_BUFFER, buffer); + + TraceLog(INFO, "[%s] Sound loaded successfully from resource (SampleRate: %i, BitRate: %i, Channels: %i)", rresName, wave.sampleRate, wave.bitsPerSample, wave.channels); // Unallocate WAV data UnloadWave(wave); - TraceLog(INFO, "[%s] Sound loaded successfully from resource, sample rate: %i", rresName, (int)sampleRate); - sound.source = source; sound.buffer = buffer; } @@ -492,7 +498,10 @@ void PlayMusicStream(char *fileName) // Open audio stream currentMusic.stream = stb_vorbis_open_filename(fileName, NULL, NULL); - if (currentMusic.stream == NULL) TraceLog(WARNING, "[%s] Could not open ogg audio file", fileName); + if (currentMusic.stream == NULL) + { + TraceLog(WARNING, "[%s] OGG audio file could not be opened", fileName); + } else { // Get file info @@ -582,11 +591,13 @@ void ResumeMusicStream(void) // Check if music is playing bool MusicIsPlaying(void) { - ALenum state; + bool playing = false; + ALint state; alGetSourcei(currentMusic.source, AL_SOURCE_STATE, &state); + if (state == AL_PLAYING) playing = true; - return (state == AL_PLAYING); + return playing; } // Set volume for music @@ -757,9 +768,9 @@ static Wave LoadWAV(const char *fileName) wavFile = fopen(fileName, "rb"); - if (!wavFile) + if (wavFile == NULL) { - TraceLog(WARNING, "[%s] Could not open WAV file", fileName); + TraceLog(WARNING, "[%s] WAV file could not be opened", fileName); } else { @@ -811,7 +822,7 @@ static Wave LoadWAV(const char *fileName) wave.channels = waveFormat.numChannels; wave.bitsPerSample = waveFormat.bitsPerSample; - TraceLog(INFO, "[%s] Wave file loaded successfully", fileName); + TraceLog(INFO, "[%s] WAV file loaded successfully (SampleRate: %i, BitRate: %i, Channels: %i)", fileName, wave.sampleRate, wave.bitsPerSample, wave.channels); } } } @@ -860,6 +871,8 @@ static Wave LoadOGG(char *fileName) int samplesObtained = stb_vorbis_get_samples_short_interleaved(oggFile, info.channels, wave.data, totalSamplesLength); TraceLog(DEBUG, "[%s] Samples obtained: %i", fileName, samplesObtained); + + TraceLog(INFO, "[%s] OGG file loaded successfully (SampleRate: %i, BitRate: %i, Channels: %i)", fileName, wave.sampleRate, wave.bitsPerSample, wave.channels); stb_vorbis_close(oggFile); diff --git a/src/core.c b/src/core.c index 1488072e..5ff44f89 100644 --- a/src/core.c +++ b/src/core.c @@ -92,7 +92,7 @@ //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- -// ... +#define MAX_TOUCH_POINTS 256 //---------------------------------------------------------------------------------- // Types and Structures Definition @@ -112,7 +112,14 @@ static bool windowReady = false; // Used to detect display initia // Gestures detection variables static float tapTouchX, tapTouchY; +static int64_t lastTapTime = 0; +static float lastTapX = 0, lastTapY = 0; static bool touchTap = false; +static bool doubleTap = false; +static bool drag = false; +static int stdVector[MAX_TOUCH_POINTS]; +static int indexPosition = 0; +const AInputEvent* eventDrag; static int32_t touchId; const int32_t DOUBLE_TAP_TIMEOUT = 300*1000000; const int32_t DOUBLE_TAP_SLOP = 100; @@ -184,6 +191,7 @@ static int previousMouseWheelY = 0; // Required to track mouse wheel var static int currentMouseWheelY = 0; // Required to track mouse wheel variation static int exitKey = KEY_ESCAPE; // Default exit key (ESC) +static int lastKeyPressed = -1; #endif #if defined(PLATFORM_ANDROID) @@ -230,6 +238,8 @@ static void InitGamepad(void); // Init raw gamepad inpu #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) static void ErrorCallback(int error, const char *description); // GLFW3 Error Callback, runs on GLFW3 error static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods); // GLFW3 Keyboard Callback, runs on key pressed +static void MouseButtonCallback(GLFWwindow *window, int button, int action, int mods); // GLFW3 Mouse Button Callback, runs on mouse button pressed +static void CharCallback(GLFWwindow *window, unsigned int key); // GLFW3 Char Key Callback, runs on key pressed (get char value) static void ScrollCallback(GLFWwindow *window, double xoffset, double yoffset); // GLFW3 Srolling Callback, runs on mouse wheel static void CursorEnterCallback(GLFWwindow *window, int enter); // GLFW3 Cursor Enter Callback, cursor enters client area static void WindowSizeCallback(GLFWwindow *window, int width, int height); // GLFW3 WindowSize Callback, runs when window is resized @@ -441,6 +451,12 @@ int GetScreenHeight(void) return screenHeight; } +// Get the last key pressed +int GetKeyPressed(void) +{ + return lastKeyPressed; +} + // Sets Background Color void ClearBackground(Color color) { @@ -623,13 +639,7 @@ bool IsKeyPressed(int key) { bool pressed = false; - currentKeyState[key] = IsKeyDown(key); - - if (currentKeyState[key] != previousKeyState[key]) - { - if (currentKeyState[key]) pressed = true; - previousKeyState[key] = currentKeyState[key]; - } + if ((currentKeyState[key] != previousKeyState[key]) && (currentKeyState[key] == 1)) pressed = true; else pressed = false; return pressed; @@ -647,13 +657,7 @@ bool IsKeyReleased(int key) { bool released = false; - currentKeyState[key] = IsKeyUp(key); - - if (currentKeyState[key] != previousKeyState[key]) - { - if (currentKeyState[key]) released = true; - previousKeyState[key] = currentKeyState[key]; - } + if ((currentKeyState[key] != previousKeyState[key]) && (currentKeyState[key] == 0)) released = true; else released = false; return released; @@ -671,13 +675,7 @@ bool IsMouseButtonPressed(int button) { bool pressed = false; - currentMouseState[button] = IsMouseButtonDown(button); - - if (currentMouseState[button] != previousMouseState[button]) - { - if (currentMouseState[button]) pressed = true; - previousMouseState[button] = currentMouseState[button]; - } + if ((currentMouseState[button] != previousMouseState[button]) && (currentMouseState[button] == 1)) pressed = true; else pressed = false; return pressed; @@ -695,13 +693,7 @@ bool IsMouseButtonReleased(int button) { bool released = false; - currentMouseState[button] = IsMouseButtonUp(button); - - if (currentMouseState[button] != previousMouseState[button]) - { - if (currentMouseState[button]) released = true; - previousMouseState[button] = currentMouseState[button]; - } + if ((currentMouseState[button] != previousMouseState[button]) && (currentMouseState[button] == 0)) released = true; else released = false; return released; @@ -858,6 +850,18 @@ bool IsScreenTouched(void) return touchTap; } +bool IsDoubleTap(void) +{ + if (doubleTap) TraceLog(INFO, "DOUBLE TAP gesture detected"); + + return doubleTap; +} + +bool IsDragGesture(void) +{ + return drag; +} + // Returns touch position X int GetTouchX(void) { @@ -877,6 +881,27 @@ Vector2 GetTouchPosition(void) return position; } + +/*bool GetPointer(Vector2 *dragPositions) +{ + //static int stdVector[MAX_TOUCH_POINTS]; + //static int indexPosition = 0; + //if (indexPosition == 0) return false; + Vector2 vec_pointers_[]; + + //eventDrag + int32_t iIndex = FindIndex( eventDrag, vec_pointers_[0] ); + + if (iIndex == -1) return false; + + float x = AMotionEvent_getX(eventDrag, iIndex); + float y = AMotionEvent_getY(eventDrag, iIndex); + + *dragPositions = Vector2( x, y ); + + + return true; +}*/ #endif //---------------------------------------------------------------------------------- @@ -977,6 +1002,8 @@ static void InitDisplay(int width, int height) glfwSetWindowSizeCallback(window, WindowSizeCallback); glfwSetCursorEnterCallback(window, CursorEnterCallback); glfwSetKeyCallback(window, KeyCallback); + glfwSetMouseButtonCallback(window, MouseButtonCallback); + glfwSetCharCallback(window, CharCallback); glfwSetScrollCallback(window, ScrollCallback); glfwMakeContextCurrent(window); @@ -1168,6 +1195,25 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i TakeScreenshot(); } #endif + else currentKeyState[key] = action; + + // HACK for GuiTextBox, to deteck back key + // TODO: Review... + if ((key == 259) && (action == GLFW_PRESS)) lastKeyPressed = 3; +} + +// GLFW3 Mouse Button Callback, runs on mouse button pressed +static void MouseButtonCallback(GLFWwindow *window, int button, int action, int mods) +{ + currentMouseState[button] = action; +} + +// GLFW3 Char Key Callback, runs on key pressed (get char value) +static void CharCallback(GLFWwindow *window, unsigned int key) +{ + lastKeyPressed = key; + + //TraceLog(INFO, "Char Callback Key pressed: %i\n", key); } // GLFW3 CursorEnter Callback, when cursor enters the window @@ -1203,6 +1249,7 @@ static int32_t InputCallback(struct android_app *app, AInputEvent *event) if (type == AINPUT_EVENT_TYPE_MOTION) { + // Detect TOUCH position if ((screenWidth > displayWidth) || (screenHeight > displayHeight)) { // TODO: Seems to work ok but... review! @@ -1266,7 +1313,124 @@ static int32_t InputCallback(struct android_app *app, AInputEvent *event) //size_t pointerCount = AMotionEvent_getPointerCount(event); //float AMotionEvent_getPressure(const AInputEvent *motion_event, size_t pointer_index); // 0 to 1 //float AMotionEvent_getSize(const AInputEvent *motion_event, size_t pointer_index); // Pressed area + + // Detect DOUBLE TAP event + bool tapDetected = touchTap; + switch (flags) + { + case AMOTION_EVENT_ACTION_DOWN: + { + int64_t eventTime = AMotionEvent_getEventTime(event); + + if (eventTime - lastTapTime <= DOUBLE_TAP_TIMEOUT) + { + float x = AMotionEvent_getX(event, 0) - lastTapX; + float y = AMotionEvent_getY(event, 0) - lastTapY; + + float densityFactor = 1.0f; + + if ((x*x + y*y) < (DOUBLE_TAP_SLOP*DOUBLE_TAP_SLOP*densityFactor)) + { + // Doubletap detected + doubleTap = true; + + } + } + } break; + case AMOTION_EVENT_ACTION_UP: + { + if (tapDetected) + { + lastTapTime = AMotionEvent_getEventTime(event); + lastTapX = AMotionEvent_getX(event, 0); + lastTapY = AMotionEvent_getY(event, 0); + + } + } break; + } + + + // Detect DRAG event + //int32_t action = AMotionEvent_getAction(event); + + int32_t index = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; + //uint32_t flags = action & AMOTION_EVENT_ACTION_MASK; + //event_ = event; + + int32_t count = AMotionEvent_getPointerCount(event); + + switch (flags) + { + case AMOTION_EVENT_ACTION_DOWN: + { + stdVector[indexPosition] = AMotionEvent_getPointerId(event, 0); + indexPosition++; + TraceLog(INFO, "ACTION_DOWN"); + + //ret = GESTURE_STATE_START; + } break; + case AMOTION_EVENT_ACTION_POINTER_DOWN: + { + stdVector[indexPosition] = AMotionEvent_getPointerId(event, index); + indexPosition++; + TraceLog(INFO, "ACTION_POINTER_DOWN"); + + } break; + case AMOTION_EVENT_ACTION_UP: + { + //int value = stdVector[indexPosition]; + indexPosition--; + //ret = GESTURE_STATE_END; + TraceLog(INFO, "ACTION_UP"); + + } break; + case AMOTION_EVENT_ACTION_POINTER_UP: + { + int32_t releasedPointerId = AMotionEvent_getPointerId(event, index); + + int i = 0; + for (i = 0; i < MAX_TOUCH_POINTS; i++) + { + if (stdVector[i] == releasedPointerId) + { + for (int k = i; k < indexPosition - 1; k++) + { + stdVector[k] = stdVector[k + 1]; + } + + //indexPosition--; + indexPosition = 0; + break; + } + } + + if (i <= 1) + { + // Reset pinch or drag + //if (count == 2) //ret = GESTURE_STATE_START; + } + TraceLog(INFO, "ACTION_POINTER_UP"); + + } break; + case AMOTION_EVENT_ACTION_MOVE: + { + if (count == 1) + { + //TraceLog(INFO, "DRAG gesture detected"); + + drag = true; //ret = GESTURE_STATE_MOVE; + } + else break; + TraceLog(INFO, "ACTION_MOVE"); + + } break; + case AMOTION_EVENT_ACTION_CANCEL: break; + default: break; + } + + //-------------------------------------------------------------------- + return 1; } else if (type == AINPUT_EVENT_TYPE_KEY) @@ -1467,14 +1631,23 @@ static void PollInputEvents(void) // Keyboard polling // Automatically managed by GLFW3 through callback - + lastKeyPressed = -1; + + // Register previous keys states + for (int i = 0; i < 512; i++) previousKeyState[i] = currentKeyState[i]; + + // Register previous mouse states + for (int i = 0; i < 3; i++) previousMouseState[i] = currentMouseState[i]; + glfwPollEvents(); // Register keyboard/mouse events #elif defined(PLATFORM_ANDROID) // TODO: Check virtual keyboard (?) - // Reset touchTap event + // Reset touch events touchTap = false; + doubleTap = false; + drag = false; // Poll Events (registered events) while ((ident = ALooper_pollAll(0, NULL, &events,(void**)&source)) >= 0) @@ -1623,14 +1796,17 @@ static void PollInputEvents(void) static void InitMouse(void) { // NOTE: We can use /dev/input/mice to read from all available mice - if ((mouseStream = open(DEFAULT_MOUSE_DEV, O_RDONLY|O_NONBLOCK)) < 0) TraceLog(WARNING, "Could not open mouse device, no mouse available"); + if ((mouseStream = open(DEFAULT_MOUSE_DEV, O_RDONLY|O_NONBLOCK)) < 0) + { + TraceLog(WARNING, "Mouse device could not be opened, no mouse available"); + } else { mouseReady = true; - int err = pthread_create(&mouseThreadId, NULL, &MouseThread, NULL); + int error = pthread_create(&mouseThreadId, NULL, &MouseThread, NULL); - if (err != 0) TraceLog(WARNING, "Error creating mouse input event thread"); + if (error != 0) TraceLog(WARNING, "Error creating mouse input event thread"); else TraceLog(INFO, "Mouse device initialized successfully"); } } @@ -1741,7 +1917,7 @@ static void RestoreKeyboard(void) static void InitGamepad(void) { // TODO: Gamepad support - if ((gamepadStream = open(DEFAULT_GAMEPAD_DEV, O_RDONLY|O_NONBLOCK)) < 0) TraceLog(WARNING, "Could not open gamepad device, no gamepad available"); + if ((gamepadStream = open(DEFAULT_GAMEPAD_DEV, O_RDONLY|O_NONBLOCK)) < 0) TraceLog(WARNING, "Gamepad device could not be opened, no gamepad available"); else TraceLog(INFO, "Gamepad device initialized successfully"); } #endif @@ -1763,7 +1939,7 @@ static void SetupFramebufferSize(int displayWidth, int displayHeight) // Calculate renderWidth and renderHeight, we have the display size (input params) and the desired screen size (global var) if ((screenWidth > displayWidth) || (screenHeight > displayHeight)) { - TraceLog(WARNING, "DOWNSCALING: Required screen size (%i x %i) is bigger than display size (%i x %i)", screenWidth, screenHeight, displayWidth, displayHeight); + TraceLog(WARNING, "DOWNSCALING: Required screen size (%ix%i) is bigger than display size (%ix%i)", screenWidth, screenHeight, displayWidth, displayHeight); // Downscaling to fit display with border-bars float widthRatio = (float)displayWidth/(float)screenWidth; @@ -1832,6 +2008,7 @@ static void SetupFramebufferSize(int displayWidth, int displayHeight) // Plays raylib logo appearing animation static void LogoAnimation(void) { +#ifndef PLATFORM_WEB int logoPositionX = screenWidth/2 - 128; int logoPositionY = screenHeight/2 - 128; @@ -1949,6 +2126,8 @@ static void LogoAnimation(void) EndDrawing(); //---------------------------------------------------------------------------------- } +#endif showLogo = false; // Prevent for repeating when reloading window (Android) } + diff --git a/src/makefile b/src/makefile index 88d2258c..501bd0c9 100644 --- a/src/makefile +++ b/src/makefile @@ -1,8 +1,6 @@ #************************************************************************************************** # -# raylib for Raspberry Pi and Windows desktop -# -# makefile for library compilation (raylib.a) +# raylib makefile for desktop platforms, Raspberry Pi and HTML5 (emscripten) # # Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com) # @@ -23,8 +21,8 @@ # #************************************************************************************************** -# define raylib platform (by default, compile for RPI) -# Other possible platforms: PLATFORM_DESKTOP_WIN PLATFORM_DESKTOP_LINUX PLATFORM_WEB +# define raylib platform to compile for +# possible platforms: PLATFORM_DESKTOP PLATFORM_RPI PLATFORM_WEB PLATFORM ?= PLATFORM_DESKTOP # define raylib graphics api depending on selected platform @@ -81,7 +79,7 @@ default: raylib # compile raylib library raylib: $(OBJS) ifeq ($(PLATFORM),PLATFORM_WEB) - emcc -O1 $(OBJS) -o raylib.bc + emcc -O1 $(OBJS) -o libraylib.bc else ar rcs libraylib.a $(OBJS) endif @@ -135,9 +133,13 @@ else ifeq ($(PLATFORM),PLATFORM_DESKTOP_LINUX) find . -type f -executable -delete rm -f *.o libraylib.a +else +ifeq ($(PLATFORM),PLATFORM_WEB) + del *.o libraylib.bc else del *.o libraylib.a endif +endif endif @echo Cleaning done diff --git a/src/models.c b/src/models.c index 539af3f9..e8e4f635 100644 --- a/src/models.c +++ b/src/models.c @@ -50,7 +50,7 @@ //---------------------------------------------------------------------------------- // Global Variables Definition //---------------------------------------------------------------------------------- -// It's lonely here... +extern unsigned int whiteTexture; //---------------------------------------------------------------------------------- // Module specific Functions Declaration @@ -476,7 +476,7 @@ void DrawQuad(Vector3 vertices[4], Vector2 textcoords[4], Vector3 normals[4], Co void DrawPlane(Vector3 centerPos, Vector2 size, Vector3 rotation, Color color) { // NOTE: QUADS usage require defining a texture on OpenGL 3.3+ - if (rlGetVersion() != OPENGL_11) rlEnableTexture(1); // Default white texture + if (rlGetVersion() != OPENGL_11) rlEnableTexture(whiteTexture); // Default white texture // NOTE: Plane is always created on XZ ground and then rotated rlPushMatrix(); @@ -812,7 +812,7 @@ Model LoadHeightmap(Image heightmap, float maxHeight) } // Load a map image as a 3d model (cubes based) -Model LoadCubesmap(Image cubesmap) +Model LoadCubicmap(Image cubesmap) { VertexData vData; @@ -1068,8 +1068,6 @@ Model LoadCubesmap(Image cubesmap) // Move data from mapVertices temp arays to vertices float array vData.vertexCount = vCounter; - //printf("Vertex count: %i\n", vCounter); - vData.vertices = (float *)malloc(vData.vertexCount * 3 * sizeof(float)); vData.normals = (float *)malloc(vData.vertexCount * 3 * sizeof(float)); vData.texcoords = (float *)malloc(vData.vertexCount * 2 * sizeof(float)); @@ -1523,4 +1521,36 @@ static VertexData LoadOBJ(const char *fileName) TraceLog(INFO, "[%s] Model loaded successfully in RAM (CPU)", fileName); return vData; -} \ No newline at end of file +} + +bool CheckCollisionSpheres(Vector3 centerA, float radiusA, Vector3 centerB, float radiusB) +{ + + return false; +} + +bool CheckCollisionBoxes(Vector3 minBBox1, Vector3 maxBBox1, Vector3 minBBox2, Vector3 maxBBox2) +{ + /* + // Get min and max vertex to construct bounds (AABB) + Vector3 minVertex = tempVertices[0]; + Vector3 maxVertex = tempVertices[0]; + + for (int i = 1; i < tempVertices.Count; i++) + { + minVertex = Vector3.Min(minVertex, tempVertices[i]); + maxVertex = Vector3.Max(maxVertex, tempVertices[i]); + } + + bounds = new BoundingBox(minVertex, maxVertex); + */ + return false; +} + +bool CheckCollisionBoxSphere(Vector3 minBBox, Vector3 maxBBox, Vector3 centerSphere, Vector3 radiusSphere) +{ + + return false; +} + +//BoundingBox GetCollisionArea(BoundingBox box1, BoundingBox box2) \ No newline at end of file diff --git a/src/raylib.h b/src/raylib.h index 89648ef1..d5be9990 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -63,6 +63,7 @@ //#define PLATFORM_DESKTOP // Windows, Linux or OSX //#define PLATFORM_ANDROID // Android device //#define PLATFORM_RPI // Raspberry Pi +//#define PLATFORM_WEB // HTML5 (emscripten, asm.js) // Security check in case no PLATFORM_* defined #if !defined(PLATFORM_DESKTOP) && !defined(PLATFORM_ANDROID) && !defined(PLATFORM_RPI) && !defined(PLATFORM_WEB) @@ -298,7 +299,7 @@ extern "C" { // Prevents name mangling of functions //------------------------------------------------------------------------------------ #if defined(PLATFORM_ANDROID) void InitWindow(int width, int height, struct android_app *state); // Init Android activity -#elif defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) +#elif defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB) void InitWindow(int width, int height, const char *title); // Initialize Window and OpenGL Graphics #endif @@ -311,6 +312,7 @@ void SetExitKey(int key); // Set a custom key #endif int GetScreenWidth(void); // Get current screen width int GetScreenHeight(void); // Get current screen height +int GetKeyPressed(void); // Get latest key pressed void ClearBackground(Color color); // Sets Background Color void BeginDrawing(void); // Setup drawing canvas to start drawing @@ -330,8 +332,7 @@ int GetRandomValue(int min, int max); // Returns a random Color Fade(Color color, float alpha); // Color fade-in or fade-out, alpha goes from 0.0f to 1.0f void SetupFlags(char flags); // Enable some window configurations - -void ShowLogo(void); // Activates raylib logo at startup +void ShowLogo(void); // Activates raylib logo at startup (can be done with flags) //------------------------------------------------------------------------------------ // Input Handling Functions (Module: core) @@ -410,6 +411,7 @@ Texture2D LoadTextureFromImage(Image image, bool genMipmaps); Texture2D CreateTexture(Image image, bool genMipmaps); // [DEPRECATED] Same as LoadTextureFromImage() void UnloadImage(Image image); // Unload image from CPU memory (RAM) void UnloadTexture(Texture2D texture); // Unload texture from GPU memory +void ConvertToPOT(Image *image, Color fillColor); // Convert image to POT (power-of-two) void DrawTexture(Texture2D texture, int posX, int posY, Color tint); // Draw a Texture2D void DrawTextureV(Texture2D texture, Vector2 position, Color tint); // Draw a Texture2D with position defined as Vector2 @@ -460,7 +462,7 @@ void DrawGizmoEx(Vector3 position, Vector3 rotation, float scale); Model LoadModel(const char *fileName); // Load a 3d model (.OBJ) //Model LoadModelFromRES(const char *rresName, int resId); // TODO: Load a 3d model from rRES file (raylib Resource) Model LoadHeightmap(Image heightmap, float maxHeight); // Load a heightmap image as a 3d model -Model LoadCubesmap(Image cubesmap); // Load a map image as a 3d model (cubes based) +Model LoadCubicmap(Image cubicmap); // Load a map image as a 3d model (cubes based) void UnloadModel(Model model); // Unload 3d model from memory void SetModelTexture(Model *model, Texture2D texture); // Link a texture to a model @@ -478,7 +480,7 @@ void InitAudioDevice(void); // Initialize au void CloseAudioDevice(void); // Close the audio device and context (and music stream) Sound LoadSound(char *fileName); // Load sound to memory -Sound LoadSoundFromWave(Wave wave); // Load sound from wave data +Sound LoadSoundFromWave(Wave wave); // Load sound to memory from wave data Sound LoadSoundFromRES(const char *rresName, int resId); // Load sound to memory from rRES file (raylib Resource) void UnloadSound(Sound sound); // Unload sound void PlaySound(Sound sound); // Play a sound diff --git a/src/raymath.c b/src/raymath.c index 56b79b42..ed45ee92 100644 --- a/src/raymath.c +++ b/src/raymath.c @@ -329,8 +329,6 @@ void MatrixInvert(Matrix *mat) // Calculate the invert determinant (inlined to avoid double-caching) float invDet = 1/(b00*b11 - b01*b10 + b02*b09 + b03*b08 - b04*b07 + b05*b06); - printf("%f\n", invDet); - temp.m0 = (a11*b11 - a12*b10 + a13*b09)*invDet; temp.m1 = (-a01*b11 + a02*b10 - a03*b09)*invDet; temp.m2 = (a31*b05 - a32*b04 + a33*b03)*invDet; @@ -492,6 +490,48 @@ Matrix MatrixRotate(float angleX, float angleY, float angleZ) return result; } +/* +Matrix MatrixRotate(float angle, float x, float y, float z) +{ + Matrix result = MatrixIdentity(); + + float c = cosf(angle*DEG2RAD); // cosine + float s = sinf(angle*DEG2RAD); // sine + float c1 = 1.0f - c; // 1 - c + + float m0 = result.m0, m4 = result.m4, m8 = result.m8, m12 = result.m12, + m1 = result.m1, m5 = result.m5, m9 = result.m9, m13 = result.m13, + m2 = result.m2, m6 = result.m6, m10 = result.m10, m14 = result.m14; + + // build rotation matrix + float r0 = x * x * c1 + c; + float r1 = x * y * c1 + z * s; + float r2 = x * z * c1 - y * s; + float r4 = x * y * c1 - z * s; + float r5 = y * y * c1 + c; + float r6 = y * z * c1 + x * s; + float r8 = x * z * c1 + y * s; + float r9 = y * z * c1 - x * s; + float r10= z * z * c1 + c; + + // multiply rotation matrix + result.m0 = r0*m0 + r4*m1 + r8*m2; + result.m1 = r1*m0 + r5*m1 + r9*m2; + result.m2 = r2*m0 + r6*m1 + r10*m2; + result.m4 = r0*m4 + r4*m5 + r8*m6; + result.m5 = r1*m4 + r5*m5 + r9*m6; + result.m6 = r2*m4 + r6*m5 + r10*m6; + result.m8 = r0*m8 + r4*m9 + r8*m10; + result.m9 = r1*m8 + r5*m9 + r9*m10; + result.m10 = r2*m8 + r6*m9 + r10*m10; + result.m12 = r0*m12+ r4*m13 + r8*m14; + result.m13 = r1*m12+ r5*m13 + r9*m14; + result.m14 = r2*m12+ r6*m13 + r10*m14; + + return result; +} +*/ + // Create rotation matrix from axis and angle // TODO: Test this function // NOTE: NO prototype defined! @@ -668,12 +708,11 @@ Matrix MatrixScale(float x, float y, float z) // Returns transformation matrix for a given translation, rotation and scale // NOTE: Transformation order is rotation -> scale -> translation +// NOTE: Rotation angles should come in radians Matrix MatrixTransform(Vector3 translation, Vector3 rotation, Vector3 scale) { Matrix result = MatrixIdentity(); - // TODO: Review, use DEG2RAD here? - //Matrix mRotation = MatrixRotate(rotation.x*DEG2RAD, rotation.y*DEG2RAD, rotation.z*DEG2RAD); Matrix mRotation = MatrixRotate(rotation.x, rotation.y, rotation.z); Matrix mScale = MatrixScale(scale.x, scale.y, scale.z); Matrix mTranslate = MatrixTranslate(translation.x, translation.y, translation.z); diff --git a/src/raymath.h b/src/raymath.h index 334df4f3..c8c1a26c 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -55,7 +55,7 @@ } Vector3; #endif -// Matrix type (OpenGL style 4x4 - right handed) +// Matrix type (OpenGL style 4x4 - right handed, column major) typedef struct Matrix { float m0, m4, m8, m12; float m1, m5, m9, m13; @@ -107,7 +107,7 @@ Matrix MatrixIdentity(void); // Returns identity matr Matrix MatrixAdd(Matrix left, Matrix right); // Add two matrices Matrix MatrixSubstract(Matrix left, Matrix right); // Substract two matrices (left - right) Matrix MatrixTranslate(float x, float y, float z); // Returns translation matrix -Matrix MatrixRotate(float angleX, float angleY, float angleZ); // Returns rotation matrix +Matrix MatrixRotate(float axisX, float axisY, float axisZ); // Returns rotation matrix Matrix MatrixFromAxisAngle(Vector3 axis, float angle); // Returns rotation matrix for an angle around an specified axis Matrix MatrixFromAxisAngle2(Vector3 axis, float angle); // Returns rotation matrix for an angle around an specified axis (test another implemntation) Matrix MatrixFromQuaternion(Quaternion q); // Returns rotation matrix for a given quaternion diff --git a/src/rlgl.c b/src/rlgl.c index 43052237..4f033ad1 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -169,7 +169,8 @@ static int tempBufferCount = 0; static bool useTempBuffer = false; // White texture useful for plain color polys (required by shader) -static GLuint whiteTexture; +// NOTE: It's required in shapes and models modules! +extern unsigned int whiteTexture; // Support for VAOs (OpenGL ES2 could not support VAO extensions) static bool vaoSupported = false; @@ -772,7 +773,7 @@ void rlglInit(void) #endif #if defined(GRAPHICS_API_OPENGL_ES2) - // NOTE: emscripten does not support VAOs + // NOTE: emscripten does not support VAOs natively, it uses emulation and it reduces overall performance... #if !defined(PLATFORM_WEB) glGenVertexArrays = (PFNGLGENVERTEXARRAYSOESPROC)eglGetProcAddress("glGenVertexArraysOES"); glBindVertexArray = (PFNGLBINDVERTEXARRAYOESPROC)eglGetProcAddress("glBindVertexArrayOES"); @@ -1128,6 +1129,8 @@ void rlglDrawModel(Model model, Vector3 position, Vector3 rotation, Vector3 scal #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) glUseProgram(shaderProgram); // Use our shader + VectorScale(&rotation, DEG2RAD); + // Get transform matrix (rotation -> scale -> translation) Matrix transform = MatrixTransform(position, rotation, scale); Matrix modelviewworld = MatrixMultiply(transform, modelview); @@ -1340,7 +1343,7 @@ unsigned int rlglLoadTexture(unsigned char *data, int width, int height, bool ge // Unbind current texture glBindTexture(GL_TEXTURE_2D, 0); - TraceLog(INFO, "[TEX ID %i] Texture created successfully (%i x %i)", id, width, height); + TraceLog(INFO, "[TEX ID %i] Texture created successfully (%ix%i)", id, width, height); return id; } @@ -1690,33 +1693,35 @@ static GLuint LoadShaders(char *vertexFileName, char *fragmentFileName) } // Read shader text file -static char *TextFileRead(char *fn) +static char *TextFileRead(char *fileName) { - FILE *fp; + FILE *textFile; char *text = NULL; int count=0; - if (fn != NULL) + if (fileName != NULL) { - fp = fopen(fn,"rt"); + textFile = fopen(fileName,"rt"); - if (fp != NULL) + if (textFile != NULL) { - fseek(fp, 0, SEEK_END); - count = ftell(fp); - rewind(fp); + fseek(textFile, 0, SEEK_END); + count = ftell(textFile); + rewind(textFile); if (count > 0) { text = (char *)malloc(sizeof(char) * (count+1)); - count = fread(text, sizeof(char), count, fp); + count = fread(text, sizeof(char), count, textFile); text[count] = '\0'; } - fclose(fp); + fclose(textFile); } + else TraceLog(WARNING, "[%s] Text file could not be opened", fileName); } + return text; } @@ -1992,7 +1997,7 @@ static int GenerateMipmaps(unsigned char *data, int baseWidth, int baseHeight) j++; } - TraceLog(DEBUG, "Mipmap base (%i, %i)", width, height); + TraceLog(DEBUG, "Mipmap base (%ix%i)", width, height); for (int mip = 1; mip < mipmapCount; mip++) { @@ -2063,7 +2068,7 @@ static pixel *GenNextMipmap(pixel *srcData, int srcWidth, int srcHeight) } } - TraceLog(DEBUG, "Mipmap generated successfully (%i, %i)", width, height); + TraceLog(DEBUG, "Mipmap generated successfully (%ix%i)", width, height); return mipmap; } diff --git a/src/rlgl.h b/src/rlgl.h index b1e16f3a..5fa9c486 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -72,8 +72,9 @@ #define MAX_TRIANGLES_BATCH 4096 #define MAX_QUADS_BATCH 4096 #elif defined(GRAPHICS_API_OPENGL_ES2) - // NOTE: Reduce memory sizes for embedded systems (RPI) - #define MAX_LINES_BATCH 2048 // Critical for wire shapes (sphere) + // NOTE: Reduce memory sizes for embedded systems (RPI and HTML5) + // NOTE: On HTML5 (emscripten) this is allocated on heap, by default it's only 16MB!...just take care... + #define MAX_LINES_BATCH 1024 // Critical for wire shapes (sphere) #define MAX_TRIANGLES_BATCH 2048 // Critical for some shapes (sphere) #define MAX_QUADS_BATCH 1024 // Be careful with text, every letter maps a quad #endif diff --git a/src/shapes.c b/src/shapes.c index 6fa26bee..d872eacf 100644 --- a/src/shapes.c +++ b/src/shapes.c @@ -44,7 +44,7 @@ //---------------------------------------------------------------------------------- // Global Variables Definition //---------------------------------------------------------------------------------- -// It's lonely here... +extern unsigned int whiteTexture; //---------------------------------------------------------------------------------- // Module specific Functions Declaration @@ -197,7 +197,7 @@ void DrawRectangleV(Vector2 position, Vector2 size, Color color) else if ((rlGetVersion() == OPENGL_33) || (rlGetVersion() == OPENGL_ES_20)) { // NOTE: This shape uses QUADS to avoid drawing order issues (view rlglDraw) - rlEnableTexture(1); // Default white texture + rlEnableTexture(whiteTexture); // Default white texture rlBegin(RL_QUADS); rlColor4ub(color.r, color.g, color.b, color.a); diff --git a/src/text.c b/src/text.c index bc5eb7d3..94481857 100644 --- a/src/text.c +++ b/src/text.c @@ -63,7 +63,6 @@ static SpriteFont defaultFont; // Default font provided by raylib //---------------------------------------------------------------------------------- static bool PixelIsMagenta(Color p); // Check if a pixel is magenta static int ParseImageData(Color *imgDataPixel, int imgWidth, int imgHeight, Character **charSet); // Parse image pixel data to obtain character set measures -static int GetNextPOT(int num); // Calculate next power-of-two value for a given value static SpriteFont LoadRBMF(const char *fileName); // Load a rBMF font file (raylib BitMap Font) extern void LoadDefaultFont(void); @@ -195,9 +194,10 @@ SpriteFont LoadSpriteFont(const char *fileName) Image image = LoadImage(fileName); // At this point we have a pixel array with all the data... - - TraceLog(INFO, "[%s] SpriteFont image loaded: %i x %i", fileName, image.width, image.height); - + +#if defined(PLATFORM_RPI) || defined(PLATFORM_WEB) + ConvertToPOT(&image, MAGENTA); +#endif // Process bitmap Font pixel data to get measures (Character array) // spriteFont.charSet data is filled inside the function and memory is allocated! int numChars = ParseImageData(image.pixels, image.width, image.height, &spriteFont.charSet); @@ -207,40 +207,8 @@ SpriteFont LoadSpriteFont(const char *fileName) spriteFont.numChars = numChars; - // Convert image font to POT image before conversion to texture - // NOTE: Not required, we skip this step -/* - // Just add the required amount of pixels at the right and bottom sides of image... - int potWidth = GetNextPOT(image.width); - int potHeight = GetNextPOT(image.height); - - // Check if POT texture generation is required (if texture is not already POT) - if ((potWidth != image.width) || (potHeight != image.height)) - { - Color *imgDataPixelPOT = NULL; - - // Generate POT array from NPOT data - imgDataPixelPOT = (Color *)malloc(potWidth * potHeight * sizeof(Color)); - - for (int j = 0; j < potHeight; j++) - { - for (int i = 0; i < potWidth; i++) - { - if ((j < image.height) && (i < image.width)) imgDataPixelPOT[j*potWidth + i] = image.pixels[j*image.width + i]; - else imgDataPixelPOT[j*potWidth + i] = MAGENTA; - } - } - - TraceLog(WARNING, "SpriteFont texture converted to POT: %ix%i", potWidth, potHeight); - - free(image.pixels); - - image.pixels = imgDataPixelPOT; - image.width = potWidth; - image.height = potHeight; - } -*/ spriteFont.texture = LoadTextureFromImage(image, false); // Convert loaded image to OpenGL texture + UnloadImage(image); } @@ -475,23 +443,6 @@ static int ParseImageData(Color *imgDataPixel, int imgWidth, int imgHeight, Char return index; } -// Calculate next power-of-two value for a given num -static int GetNextPOT(int num) -{ - if (num != 0) - { - num--; - num |= (num >> 1); // Or first 2 bits - num |= (num >> 2); // Or next 2 bits - num |= (num >> 4); // Or next 4 bits - num |= (num >> 8); // Or next 8 bits - num |= (num >> 16); // Or next 16 bits - num++; - } - - return num; -} - // Load a rBMF font file (raylib BitMap Font) static SpriteFont LoadRBMF(const char *fileName) { @@ -517,91 +468,96 @@ static SpriteFont LoadRBMF(const char *fileName) Image image; rbmfInfoHeader rbmfHeader; - unsigned int *rbmfFileData; - unsigned char *rbmfCharWidthData; + unsigned int *rbmfFileData = NULL; + unsigned char *rbmfCharWidthData = NULL; int charsDivisor = 1; // Every char is separated from the consecutive by a 1 pixel divisor, horizontally and vertically FILE *rbmfFile = fopen(fileName, "rb"); // Define a pointer to bitmap file and open it in read-binary mode - // TODO: Check if file could be loaded! (rbmfFile == NULL)? + if (rbmfFile == NULL) + { + TraceLog(WARNING, "[%s] rBMF font file could not be opened", fileName); + } + else + { + fread(&rbmfHeader, sizeof(rbmfInfoHeader), 1, rbmfFile); - fread(&rbmfHeader, sizeof(rbmfInfoHeader), 1, rbmfFile); + TraceLog(INFO, "[%s] Loading rBMF file, size: %ix%i, numChars: %i, charHeight: %i", fileName, rbmfHeader.imgWidth, rbmfHeader.imgHeight, rbmfHeader.numChars, rbmfHeader.charHeight); - TraceLog(INFO, "[%s] Loading rBMF file, size: %ix%i, numChars: %i, charHeight: %i", fileName, rbmfHeader.imgWidth, rbmfHeader.imgHeight, rbmfHeader.numChars, rbmfHeader.charHeight); + spriteFont.numChars = (int)rbmfHeader.numChars; - spriteFont.numChars = (int)rbmfHeader.numChars; + image.width = (int)rbmfHeader.imgWidth; + image.height = (int)rbmfHeader.imgHeight; - image.width = (int)rbmfHeader.imgWidth; - image.height = (int)rbmfHeader.imgHeight; + int numPixelBits = rbmfHeader.imgWidth * rbmfHeader.imgHeight / 32; - int numPixelBits = rbmfHeader.imgWidth * rbmfHeader.imgHeight / 32; + rbmfFileData = (unsigned int *)malloc(numPixelBits * sizeof(unsigned int)); - rbmfFileData = (unsigned int *)malloc(numPixelBits * sizeof(unsigned int)); + for(int i = 0; i < numPixelBits; i++) fread(&rbmfFileData[i], sizeof(unsigned int), 1, rbmfFile); - for(int i = 0; i < numPixelBits; i++) fread(&rbmfFileData[i], sizeof(unsigned int), 1, rbmfFile); + rbmfCharWidthData = (unsigned char *)malloc(spriteFont.numChars * sizeof(unsigned char)); - rbmfCharWidthData = (unsigned char *)malloc(spriteFont.numChars * sizeof(unsigned char)); + for(int i = 0; i < spriteFont.numChars; i++) fread(&rbmfCharWidthData[i], sizeof(unsigned char), 1, rbmfFile); - for(int i = 0; i < spriteFont.numChars; i++) fread(&rbmfCharWidthData[i], sizeof(unsigned char), 1, rbmfFile); + // Re-construct image from rbmfFileData + //----------------------------------------- + image.pixels = (Color *)malloc(image.width * image.height * sizeof(Color)); - // Re-construct image from rbmfFileData - //----------------------------------------- - image.pixels = (Color *)malloc(image.width * image.height * sizeof(Color)); + for (int i = 0; i < image.width * image.height; i++) image.pixels[i] = BLANK; // Initialize array - for (int i = 0; i < image.width * image.height; i++) image.pixels[i] = BLANK; // Initialize array + int counter = 0; // Font data elements counter - int counter = 0; // Font data elements counter - - // Fill image data (convert from bit to pixel!) - for (int i = 0; i < image.width * image.height; i += 32) - { - for (int j = 31; j >= 0; j--) + // Fill image data (convert from bit to pixel!) + for (int i = 0; i < image.width * image.height; i += 32) { - if (BIT_CHECK(rbmfFileData[counter], j)) image.pixels[i+j] = WHITE; - } + for (int j = 31; j >= 0; j--) + { + if (BIT_CHECK(rbmfFileData[counter], j)) image.pixels[i+j] = WHITE; + } - counter++; - } + counter++; + } - TraceLog(INFO, "[%s] Image reconstructed correctly, now converting it to texture", fileName); + TraceLog(INFO, "[%s] Image reconstructed correctly, now converting it to texture", fileName); - spriteFont.texture = LoadTextureFromImage(image, false); - UnloadImage(image); // Unload image data + spriteFont.texture = LoadTextureFromImage(image, false); + UnloadImage(image); // Unload image data - TraceLog(INFO, "[%s] Starting charSet reconstruction", fileName); + //TraceLog(INFO, "[%s] Starting charSet reconstruction", fileName); - // Reconstruct charSet using rbmfCharWidthData, rbmfHeader.charHeight, charsDivisor, rbmfHeader.numChars - spriteFont.charSet = (Character *)malloc(spriteFont.numChars * sizeof(Character)); // Allocate space for our character data + // Reconstruct charSet using rbmfCharWidthData, rbmfHeader.charHeight, charsDivisor, rbmfHeader.numChars + spriteFont.charSet = (Character *)malloc(spriteFont.numChars * sizeof(Character)); // Allocate space for our character data - int currentLine = 0; - int currentPosX = charsDivisor; - int testPosX = charsDivisor; + int currentLine = 0; + int currentPosX = charsDivisor; + int testPosX = charsDivisor; - for (int i = 0; i < spriteFont.numChars; i++) - { - spriteFont.charSet[i].value = (int)rbmfHeader.firstChar + i; - spriteFont.charSet[i].x = currentPosX; - spriteFont.charSet[i].y = charsDivisor + currentLine * ((int)rbmfHeader.charHeight + charsDivisor); - spriteFont.charSet[i].w = (int)rbmfCharWidthData[i]; - spriteFont.charSet[i].h = (int)rbmfHeader.charHeight; + for (int i = 0; i < spriteFont.numChars; i++) + { + spriteFont.charSet[i].value = (int)rbmfHeader.firstChar + i; + spriteFont.charSet[i].x = currentPosX; + spriteFont.charSet[i].y = charsDivisor + currentLine * ((int)rbmfHeader.charHeight + charsDivisor); + spriteFont.charSet[i].w = (int)rbmfCharWidthData[i]; + spriteFont.charSet[i].h = (int)rbmfHeader.charHeight; - testPosX += (spriteFont.charSet[i].w + charsDivisor); + testPosX += (spriteFont.charSet[i].w + charsDivisor); - if (testPosX > spriteFont.texture.width) - { - currentLine++; - currentPosX = 2 * charsDivisor + (int)rbmfCharWidthData[i]; - testPosX = currentPosX; + if (testPosX > spriteFont.texture.width) + { + currentLine++; + currentPosX = 2 * charsDivisor + (int)rbmfCharWidthData[i]; + testPosX = currentPosX; - spriteFont.charSet[i].x = charsDivisor; - spriteFont.charSet[i].y = charsDivisor + currentLine * (rbmfHeader.charHeight + charsDivisor); + spriteFont.charSet[i].x = charsDivisor; + spriteFont.charSet[i].y = charsDivisor + currentLine * (rbmfHeader.charHeight + charsDivisor); + } + else currentPosX = testPosX; } - else currentPosX = testPosX; - } - - TraceLog(INFO, "[%s] rBMF file loaded correctly as SpriteFont", fileName); + TraceLog(INFO, "[%s] rBMF file loaded correctly as SpriteFont", fileName); + } + fclose(rbmfFile); free(rbmfFileData); // Now we can free loaded data from RAM memory diff --git a/src/textures.c b/src/textures.c index ce56d3a3..f701c380 100644 --- a/src/textures.c +++ b/src/textures.c @@ -126,7 +126,7 @@ Image LoadImage(const char *fileName) image.width = imgWidth; image.height = imgHeight; - TraceLog(INFO, "[%s] Image loaded successfully", fileName); + TraceLog(INFO, "[%s] Image loaded successfully (%ix%i)", fileName, image.width, image.height); } else TraceLog(WARNING, "[%s] Image could not be loaded, file not recognized", fileName); } @@ -187,7 +187,10 @@ Image LoadImageFromRES(const char *rresName, int resId) FILE *rresFile = fopen(rresName, "rb"); - if (!rresFile) TraceLog(WARNING, "[%s] Could not open raylib resource file", rresName); + if (rresFile == NULL) + { + TraceLog(WARNING, "[%s] rRES raylib resource file could not be opened", rresName); + } else { // Read rres file (basic file check - id) @@ -337,9 +340,12 @@ Texture2D LoadTexture(const char *fileName) else { Image image = LoadImage(fileName); - + if (image.pixels != NULL) { +#if defined(PLATFORM_RPI) || defined(PLATFORM_WEB) + ConvertToPOT(&image, BLANK); +#endif texture = LoadTextureFromImage(image, false); UnloadImage(image); } @@ -425,6 +431,41 @@ void UnloadTexture(Texture2D texture) rlDeleteTextures(texture.id); } +// Convert image to POT (power-of-two) +// NOTE: Requirement on OpenGL ES 2.0 (RPI, HTML5) +void ConvertToPOT(Image *image, Color fillColor) +{ + // Just add the required amount of pixels at the right and bottom sides of image... + int potWidth = GetNextPOT(image->width); + int potHeight = GetNextPOT(image->height); + + // Check if POT texture generation is required (if texture is not already POT) + if ((potWidth != image->width) || (potHeight != image->height)) + { + Color *imgDataPixelPOT = NULL; + + // Generate POT array from NPOT data + imgDataPixelPOT = (Color *)malloc(potWidth * potHeight * sizeof(Color)); + + for (int j = 0; j < potHeight; j++) + { + for (int i = 0; i < potWidth; i++) + { + if ((j < image->height) && (i < image->width)) imgDataPixelPOT[j*potWidth + i] = image->pixels[j*image->width + i]; + else imgDataPixelPOT[j*potWidth + i] = fillColor; + } + } + + TraceLog(WARNING, "Image converted to POT: (%ix%i) -> (%ix%i)", image->width, image->height, potWidth, potHeight); + + free(image->pixels); + + image->pixels = imgDataPixelPOT; + image->width = potWidth; + image->height = potHeight; + } +} + // Draw a Texture2D void DrawTexture(Texture2D texture, int posX, int posY, Color tint) { @@ -559,7 +600,7 @@ static ImageEx LoadDDS(const char *fileName) if (ddsFile == NULL) { - TraceLog(WARNING, "DDS File could not be opened"); + TraceLog(WARNING, "[%s] DDS image file could not be opened", fileName); } else { @@ -570,7 +611,7 @@ static ImageEx LoadDDS(const char *fileName) if (strncmp(filecode, "DDS ", 4) != 0) { - TraceLog(WARNING, "DDS File does not seem to be valid"); + TraceLog(WARNING, "[%s] DDS file does not seem to be a valid image", fileName); fclose(ddsFile); } else @@ -705,7 +746,7 @@ static ImageEx LoadPKM(const char *fileName) if (pkmFile == NULL) { - TraceLog(WARNING, "[%s] PKM File could not be opened", fileName); + TraceLog(WARNING, "[%s] PKM image file could not be opened", fileName); } else { @@ -716,7 +757,7 @@ static ImageEx LoadPKM(const char *fileName) if (strncmp(filecode, "PKM ", 4) != 0) { - TraceLog(WARNING, "[%s] PKM File does not seem to be valid", fileName); + TraceLog(WARNING, "[%s] PKM file does not seem to be a valid image", fileName); fclose(pkmFile); } else diff --git a/src/utils.c b/src/utils.c index 27b72870..c3c20b47 100644 --- a/src/utils.c +++ b/src/utils.c @@ -133,18 +133,25 @@ void WriteBitmap(const char *fileName, unsigned char *imgData, int width, int he FILE *bmpFile = fopen(fileName, "wb"); // Define a pointer to bitmap file and open it in write-binary mode - // NOTE: fwrite parameters are: data pointer, size in bytes of each element to be written, number of elements, file-to-write pointer - fwrite(bmpFileHeader, sizeof(unsigned char), 14, bmpFile); // Write BMP file header data - fwrite(bmpInfoHeader, sizeof(unsigned char), 40, bmpFile); // Write BMP info header data - - // Write pixel data to file - for (int y = 0; y < height ; y++) + if (bmpFile == NULL) + { + TraceLog(WARNING, "[%s] BMP file could not be created", fileName); + } + else { - for (int x = 0; x < width; x++) + // NOTE: fwrite parameters are: data pointer, size in bytes of each element to be written, number of elements, file-to-write pointer + fwrite(bmpFileHeader, sizeof(unsigned char), 14, bmpFile); // Write BMP file header data + fwrite(bmpInfoHeader, sizeof(unsigned char), 40, bmpFile); // Write BMP info header data + + // Write pixel data to file + for (int y = 0; y < height ; y++) { - fputc(imgData[(x*4)+2 + (y*width*4)], bmpFile); - fputc(imgData[(x*4)+1 + (y*width*4)], bmpFile); - fputc(imgData[(x*4) + (y*width*4)], bmpFile); + for (int x = 0; x < width; x++) + { + fputc(imgData[(x*4)+2 + (y*width*4)], bmpFile); + fputc(imgData[(x*4)+1 + (y*width*4)], bmpFile); + fputc(imgData[(x*4) + (y*width*4)], bmpFile); + } } } @@ -264,6 +271,23 @@ const char *GetExtension(const char *fileName) return (dot + 1); } +// Calculate next power-of-two value for a given num +int GetNextPOT(int num) +{ + if (num != 0) + { + num--; + num |= (num >> 1); // Or first 2 bits + num |= (num >> 2); // Or next 2 bits + num |= (num >> 4); // Or next 4 bits + num |= (num >> 8); // Or next 8 bits + num |= (num >> 16); // Or next 16 bits + num++; + } + + return num; +} + //---------------------------------------------------------------------------------- // Module specific Functions Definition //---------------------------------------------------------------------------------- diff --git a/src/utils.h b/src/utils.h index 784c7926..882aebf6 100644 --- a/src/utils.h +++ b/src/utils.h @@ -77,6 +77,7 @@ void WritePNG(const char *fileName, unsigned char *imgData, int width, int heigh void TraceLog(int msgType, const char *text, ...); // Outputs a trace log message const char *GetExtension(const char *fileName); // Returns extension of a filename +int GetNextPOT(int num); // Calculate next power-of-two value for a given num #if defined(PLATFORM_ANDROID) void InitAssetManager(AAssetManager *manager); // Initialize asset manager from android app -- cgit v1.2.3