Merge branch 'master' of https://github.com/raysan5/raylib into pure
This commit is contained in:
commit
dbfc10ca72
20 changed files with 1873 additions and 908 deletions
|
|
@ -23,6 +23,7 @@ endif()
|
|||
# Used as public API to be included into other projects
|
||||
set(raylib_public_headers
|
||||
raylib.h
|
||||
rcamera.h
|
||||
rlgl.h
|
||||
raymath.h
|
||||
)
|
||||
|
|
@ -90,16 +91,7 @@ if (BUILD_SHARED_LIBS)
|
|||
set_property(TARGET raylib PROPERTY C_VISIBILITY_PRESET hidden)
|
||||
endif ()
|
||||
|
||||
|
||||
# If building as a static lib *AND* using internal GLFW we
|
||||
# need to set it up as a PRIVATE import so cmake doesn't complain
|
||||
# it isn't declared on an install rule
|
||||
if (INTERNAL_GLFW AND BUILD_SHARED_LIBS)
|
||||
target_link_libraries(raylib PRIVATE glfw)
|
||||
endif()
|
||||
|
||||
target_link_libraries(raylib PUBLIC "${LIBS_PRIVATE}")
|
||||
|
||||
target_link_libraries(raylib "${LIBS_PRIVATE}")
|
||||
|
||||
# Sets some compile time definitions for the pre-processor
|
||||
# If CUSTOMIZE_BUILD option is on you will not use config.h by default
|
||||
|
|
|
|||
10
src/Makefile
10
src/Makefile
|
|
@ -61,11 +61,10 @@
|
|||
#------------------------------------------------------------------------------------------------
|
||||
# Define target platform
|
||||
PLATFORM ?= PLATFORM_DESKTOP
|
||||
|
||||
ifeq ($(PLATFORM), PLATFORM_DESKTOP)
|
||||
TARGET_PLATFORM = PLATFORM_DESKTOP_GLFW
|
||||
TARGET_PLATFORM = PLATFORM_DESKTOP_GLFW
|
||||
else
|
||||
TARGET_PLATFORM = $(PLATFORM)
|
||||
TARGET_PLATFORM = $(PLATFORM)
|
||||
endif
|
||||
|
||||
# Define required raylib variables
|
||||
|
|
@ -122,7 +121,6 @@ SDL_INCLUDE_PATH ?= $(RAYLIB_SRC_PATH)/external/SDL2/include
|
|||
SDL_LIBRARY_PATH ?= $(RAYLIB_SRC_PATH)/external/SDL2/lib
|
||||
SDL_LIBRARIES ?= -lSDL2 -lSDL2main
|
||||
|
||||
|
||||
# Determine if the file has root access (only required to install raylib)
|
||||
# "whoami" prints the name of the user that calls him (so, if it is the root user, "whoami" prints "root")
|
||||
ROOT = $(shell whoami)
|
||||
|
|
@ -664,8 +662,8 @@ raylib: $(OBJS)
|
|||
ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW))
|
||||
# Compile raylib libray for web
|
||||
#$(CC) $(OBJS) -r -o $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).bc
|
||||
$(AR) rcs $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).a $(OBJS)
|
||||
@echo "raylib library generated (lib$(RAYLIB_LIB_NAME).a)!"
|
||||
$(AR) rcs $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).web.a $(OBJS)
|
||||
@echo "raylib library generated (lib$(RAYLIB_LIB_NAME).web.a)!"
|
||||
else
|
||||
ifeq ($(RAYLIB_LIBTYPE),SHARED)
|
||||
ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW PLATFORM_DESKTOP_SDL PLATFORM_DESKTOP_RGFW))
|
||||
|
|
|
|||
|
|
@ -151,6 +151,8 @@
|
|||
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS 7
|
||||
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS 8
|
||||
#endif
|
||||
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_INSTANCE_TX 9
|
||||
|
||||
|
||||
// Default shader vertex attribute names to set location points
|
||||
// NOTE: When a new shader is loaded, the following locations are tried to be set for convenience
|
||||
|
|
|
|||
661
src/external/RGFW.h
vendored
661
src/external/RGFW.h
vendored
File diff suppressed because it is too large
Load diff
|
|
@ -627,7 +627,7 @@ int SetGamepadMappings(const char *mappings)
|
|||
// Set gamepad vibration
|
||||
void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "GamepadSetVibration() not implemented on target platform");
|
||||
TRACELOG(LOG_WARNING, "SetGamepadVibration() not implemented on target platform");
|
||||
}
|
||||
|
||||
// Set mouse position XY
|
||||
|
|
@ -699,7 +699,7 @@ void PollInputEvents(void)
|
|||
|
||||
// Poll Events (registered events) until we reach TIMEOUT which indicates there are no events left to poll
|
||||
// NOTE: Activity is paused if not enabled (platform.appEnabled)
|
||||
while ((pollResult = ALooper_pollOnce(platform.appEnabled? 0 : -1, NULL, &pollEvents, (void**)&platform.source)) > ALOOPER_POLL_TIMEOUT)
|
||||
while ((pollResult = ALooper_pollOnce(platform.appEnabled? 0 : -1, NULL, &pollEvents, ((void **)&platform.source)) > ALOOPER_POLL_TIMEOUT))
|
||||
{
|
||||
// Process this event
|
||||
if (platform.source != NULL) platform.source->process(platform.app, platform.source);
|
||||
|
|
@ -786,7 +786,7 @@ int InitPlatform(void)
|
|||
while (!CORE.Window.ready)
|
||||
{
|
||||
// Process events until we reach TIMEOUT, which indicates no more events queued.
|
||||
while ((pollResult = ALooper_pollOnce(0, NULL, &pollEvents, (void**)&platform.source)) > ALOOPER_POLL_TIMEOUT)
|
||||
while ((pollResult = ALooper_pollOnce(0, NULL, &pollEvents, ((void **)&platform.source)) > ALOOPER_POLL_TIMEOUT))
|
||||
{
|
||||
// Process this event
|
||||
if (platform.source != NULL) platform.source->process(platform.app, platform.source);
|
||||
|
|
@ -1226,7 +1226,7 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
|
|||
return 1; // Handled gamepad button
|
||||
}
|
||||
|
||||
KeyboardKey key = (keycode > 0 && keycode < KEYCODE_MAP_SIZE)? mapKeycode[keycode] : KEY_NULL;
|
||||
KeyboardKey key = ((keycode > 0) && (keycode < KEYCODE_MAP_SIZE))? mapKeycode[keycode] : KEY_NULL;
|
||||
if (key != KEY_NULL)
|
||||
{
|
||||
// Save current key and its state
|
||||
|
|
|
|||
|
|
@ -322,7 +322,7 @@ void SetWindowState(unsigned int flags)
|
|||
}
|
||||
|
||||
// State change: FLAG_FULLSCREEN_MODE
|
||||
if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) != (flags & FLAG_FULLSCREEN_MODE))
|
||||
if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) != (flags & FLAG_FULLSCREEN_MODE) && ((flags & FLAG_FULLSCREEN_MODE) > 0))
|
||||
{
|
||||
ToggleFullscreen(); // NOTE: Window state flag updated inside function
|
||||
}
|
||||
|
|
@ -1088,7 +1088,7 @@ int SetGamepadMappings(const char *mappings)
|
|||
// Set gamepad vibration
|
||||
void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "GamepadSetVibration() not available on target platform");
|
||||
TRACELOG(LOG_WARNING, "SetGamepadVibration() not available on target platform");
|
||||
}
|
||||
|
||||
// Set mouse position XY
|
||||
|
|
|
|||
|
|
@ -129,6 +129,7 @@ static bool RGFW_disableCursor = false;
|
|||
static const unsigned short keyMappingRGFW[] = {
|
||||
[RGFW_KEY_NULL] = KEY_NULL,
|
||||
[RGFW_Return] = KEY_ENTER,
|
||||
[RGFW_Return] = KEY_ENTER,
|
||||
[RGFW_Apostrophe] = KEY_APOSTROPHE,
|
||||
[RGFW_Comma] = KEY_COMMA,
|
||||
[RGFW_Minus] = KEY_MINUS,
|
||||
|
|
@ -168,7 +169,6 @@ static const unsigned short keyMappingRGFW[] = {
|
|||
[RGFW_SuperL] = KEY_LEFT_SUPER,
|
||||
#ifndef RGFW_MACOS
|
||||
[RGFW_ShiftR] = KEY_RIGHT_SHIFT,
|
||||
|
||||
[RGFW_AltR] = KEY_RIGHT_ALT,
|
||||
#endif
|
||||
[RGFW_Space] = KEY_SPACE,
|
||||
|
|
@ -496,7 +496,7 @@ void SetWindowIcons(Image *images, int count)
|
|||
// Set title for window
|
||||
void SetWindowTitle(const char *title)
|
||||
{
|
||||
RGFW_window_setName(platform.window, (char*)title);
|
||||
RGFW_window_setName(platform.window, (char *)title);
|
||||
CORE.Window.title = title;
|
||||
}
|
||||
|
||||
|
|
@ -553,9 +553,9 @@ void SetWindowFocused(void)
|
|||
void *GetWindowHandle(void)
|
||||
{
|
||||
#ifdef RGFW_WEBASM
|
||||
return (void*)platform.window->src.ctx;
|
||||
return (void *)platform.window->src.ctx;
|
||||
#else
|
||||
return (void*)platform.window->src.window;
|
||||
return (void *)platform.window->src.window;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -598,7 +598,7 @@ Vector2 GetMonitorPosition(int monitor)
|
|||
{
|
||||
RGFW_monitor *mons = RGFW_getMonitors();
|
||||
|
||||
return (Vector2){(float)mons[monitor].rect.x, (float)mons[monitor].rect.y};
|
||||
return (Vector2){ (float)mons[monitor].rect.x, (float)mons[monitor].rect.y };
|
||||
}
|
||||
|
||||
// Get selected monitor width (currently used by monitor)
|
||||
|
|
@ -620,7 +620,7 @@ int GetMonitorHeight(int monitor)
|
|||
// Get selected monitor physical width in millimetres
|
||||
int GetMonitorPhysicalWidth(int monitor)
|
||||
{
|
||||
RGFW_monitor* mons = RGFW_getMonitors();
|
||||
RGFW_monitor *mons = RGFW_getMonitors();
|
||||
|
||||
return mons[monitor].physW;
|
||||
}
|
||||
|
|
@ -665,7 +665,7 @@ Vector2 GetWindowScaleDPI(void)
|
|||
// Set clipboard text content
|
||||
void SetClipboardText(const char *text)
|
||||
{
|
||||
RGFW_writeClipboard(text, (u32)strlen(text));
|
||||
RGFW_writeClipboard(text, strlen(text));
|
||||
}
|
||||
|
||||
// Get clipboard text content
|
||||
|
|
@ -685,19 +685,25 @@ const char *GetClipboardText(void)
|
|||
# define WINGDI_ALREADY_INCLUDED
|
||||
# include "../external/win32_clipboard.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Get clipboard image
|
||||
Image GetClipboardImage(void)
|
||||
{
|
||||
Image image = {0};
|
||||
Image image = { 0 };
|
||||
unsigned long long int dataSize = 0;
|
||||
void* fileData = NULL;
|
||||
void *fileData = NULL;
|
||||
|
||||
#ifdef _WIN32
|
||||
int width, height;
|
||||
fileData = (void*)Win32GetClipboardImageData(&width, &height, &dataSize);
|
||||
#if defined(SUPPORT_CLIPBOARD_IMAGE)
|
||||
#if defined(_WIN32)
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
fileData = (void *)Win32GetClipboardImageData(&width, &height, &dataSize);
|
||||
|
||||
if (fileData == NULL) TRACELOG(LOG_WARNING, "Clipboard image: Couldn't get clipboard data");
|
||||
else image = LoadImageFromMemory(".bmp", fileData, dataSize);
|
||||
#else
|
||||
TRACELOG(LOG_WARNING, "Clipboard image: PLATFORM_DESKTOP_RGFW doesn't implement `GetClipboardImage` for this OS");
|
||||
TRACELOG(LOG_WARNING, "Clipboard image: PLATFORM_DESKTOP_RGFW doesn't implement GetClipboardImage() for this OS");
|
||||
#endif
|
||||
|
||||
if (fileData == NULL)
|
||||
|
|
@ -742,9 +748,7 @@ void EnableCursor(void)
|
|||
void DisableCursor(void)
|
||||
{
|
||||
RGFW_disableCursor = true;
|
||||
|
||||
RGFW_window_mouseHold(platform.window, RGFW_AREA(0, 0));
|
||||
|
||||
HideCursor();
|
||||
}
|
||||
|
||||
|
|
@ -794,6 +798,12 @@ int SetGamepadMappings(const char *mappings)
|
|||
return 0;
|
||||
}
|
||||
|
||||
// Set gamepad vibration
|
||||
void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "SetGamepadVibration() not available on target platform");
|
||||
}
|
||||
|
||||
// Set mouse position XY
|
||||
void SetMousePosition(int x, int y)
|
||||
{
|
||||
|
|
@ -857,7 +867,6 @@ void PollInputEvents(void)
|
|||
// Register previous mouse position
|
||||
|
||||
// Reset last gamepad button/axis registered state
|
||||
|
||||
for (int i = 0; (i < 4) && (i < MAX_GAMEPADS); i++)
|
||||
{
|
||||
// Check if gamepad is available
|
||||
|
|
@ -1164,35 +1173,20 @@ int InitPlatform(void)
|
|||
|
||||
if ((CORE.Window.flags & FLAG_WINDOW_UNDECORATED) > 0) flags |= RGFW_NO_BORDER;
|
||||
if ((CORE.Window.flags & FLAG_WINDOW_RESIZABLE) == 0) flags |= RGFW_NO_RESIZE;
|
||||
|
||||
if ((CORE.Window.flags & FLAG_WINDOW_TRANSPARENT) > 0) flags |= RGFW_TRANSPARENT_WINDOW;
|
||||
|
||||
if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0) flags |= RGFW_FULLSCREEN;
|
||||
|
||||
// NOTE: Some OpenGL context attributes must be set before window creation
|
||||
|
||||
// Check selection OpenGL version
|
||||
if (rlGetVersion() == RL_OPENGL_21)
|
||||
{
|
||||
RGFW_setGLVersion(RGFW_GL_CORE, 2, 1);
|
||||
}
|
||||
else if (rlGetVersion() == RL_OPENGL_33)
|
||||
{
|
||||
RGFW_setGLVersion(RGFW_GL_CORE, 3, 3);
|
||||
}
|
||||
else if (rlGetVersion() == RL_OPENGL_43)
|
||||
{
|
||||
RGFW_setGLVersion(RGFW_GL_CORE, 4, 1);
|
||||
}
|
||||
if (rlGetVersion() == RL_OPENGL_21) RGFW_setGLVersion(RGFW_GL_CORE, 2, 1);
|
||||
else if (rlGetVersion() == RL_OPENGL_33) RGFW_setGLVersion(RGFW_GL_CORE, 3, 3);
|
||||
else if (rlGetVersion() == RL_OPENGL_43) RGFW_setGLVersion(RGFW_GL_CORE, 4, 1);
|
||||
|
||||
if (CORE.Window.flags & FLAG_MSAA_4X_HINT)
|
||||
{
|
||||
RGFW_setGLSamples(4);
|
||||
}
|
||||
if (CORE.Window.flags & FLAG_MSAA_4X_HINT) RGFW_setGLSamples(4);
|
||||
|
||||
platform.window = RGFW_createWindow(CORE.Window.title, RGFW_RECT(0, 0, CORE.Window.screen.width, CORE.Window.screen.height), flags);
|
||||
|
||||
|
||||
#ifndef PLATFORM_WEB_RGFW
|
||||
RGFW_area screenSize = RGFW_getScreenSize();
|
||||
CORE.Window.display.width = screenSize.w;
|
||||
|
|
@ -1201,10 +1195,8 @@ int InitPlatform(void)
|
|||
CORE.Window.display.width = CORE.Window.screen.width;
|
||||
CORE.Window.display.height = CORE.Window.screen.height;
|
||||
#endif
|
||||
/*
|
||||
I think this is needed by Raylib now ?
|
||||
If so, rcore_destkop_sdl should be updated too
|
||||
*/
|
||||
// TODO: Is this needed by raylib now?
|
||||
// If so, rcore_desktop_sdl should be updated too
|
||||
//SetupFramebuffer(CORE.Window.display.width, CORE.Window.display.height);
|
||||
|
||||
if (CORE.Window.flags & FLAG_VSYNC_HINT) RGFW_window_swapInterval(platform.window, 1);
|
||||
|
|
@ -1244,7 +1236,7 @@ int InitPlatform(void)
|
|||
// Load OpenGL extensions
|
||||
// NOTE: GL procedures address loader is required to load extensions
|
||||
//----------------------------------------------------------------------------
|
||||
rlLoadExtensions((void*)RGFW_getProcAddress);
|
||||
rlLoadExtensions((void *)RGFW_getProcAddress);
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
// TODO: Initialize input events system
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
* Custom flag for rcore on target platform -not used-
|
||||
*
|
||||
* DEPENDENCIES:
|
||||
* - SDL 2 or SLD 3 (main library): Windowing and inputs management
|
||||
* - SDL 2 or SDL 3 (main library): Windowing and inputs management
|
||||
* - gestures: Gestures system for touch-ready devices (or simulated from mouse inputs)
|
||||
*
|
||||
*
|
||||
|
|
@ -68,7 +68,7 @@
|
|||
#define MAX_CLIPBOARD_BUFFER_LENGTH 1024 // Size of the clipboard buffer used on GetClipboardText()
|
||||
#endif
|
||||
|
||||
#if ((defined(SDL_MAJOR_VERSION) && SDL_MAJOR_VERSION == 3) && (defined(SDL_MINOR_VERSION) && SDL_MINOR_VERSION >= 1))
|
||||
#if ((defined(SDL_MAJOR_VERSION) && (SDL_MAJOR_VERSION == 3)) && (defined(SDL_MINOR_VERSION) && (SDL_MINOR_VERSION >= 1)))
|
||||
#ifndef PLATFORM_DESKTOP_SDL3
|
||||
#define PLATFORM_DESKTOP_SDL3
|
||||
#endif
|
||||
|
|
@ -405,7 +405,7 @@ int SDL_GetNumTouchFingers(SDL_TouchID touchID)
|
|||
|
||||
// Since SDL2 doesn't have this function we leave a stub
|
||||
// SDL_GetClipboardData function is available since SDL 3.1.3. (e.g. SDL3)
|
||||
void* SDL_GetClipboardData(const char *mime_type, size_t *size)
|
||||
void *SDL_GetClipboardData(const char *mime_type, size_t *size)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "Getting clipboard data that is not text is only available in SDL3");
|
||||
|
||||
|
|
@ -497,20 +497,21 @@ void ToggleBorderlessWindowed(void)
|
|||
void MaximizeWindow(void)
|
||||
{
|
||||
SDL_MaximizeWindow(platform.window);
|
||||
CORE.Window.flags |= FLAG_WINDOW_MAXIMIZED;
|
||||
if ((CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) == 0) CORE.Window.flags |= FLAG_WINDOW_MAXIMIZED;
|
||||
}
|
||||
|
||||
// Set window state: minimized
|
||||
void MinimizeWindow(void)
|
||||
{
|
||||
SDL_MinimizeWindow(platform.window);
|
||||
CORE.Window.flags |= FLAG_WINDOW_MINIMIZED;
|
||||
if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) == 0) CORE.Window.flags |= FLAG_WINDOW_MINIMIZED;
|
||||
}
|
||||
|
||||
// Set window state: not minimized/maximized
|
||||
void RestoreWindow(void)
|
||||
{
|
||||
SDL_ShowWindow(platform.window);
|
||||
SDL_RestoreWindow(platform.window);
|
||||
// CORE.Window.flags will be removed on PollInputEvents()
|
||||
}
|
||||
|
||||
// Set window configuration state using flags
|
||||
|
|
@ -1426,7 +1427,7 @@ void PollInputEvents(void)
|
|||
|
||||
// Window events are also polled (Minimized, maximized, close...)
|
||||
|
||||
#ifndef PLATFORM_DESKTOP_SDL3
|
||||
#ifndef PLATFORM_DESKTOP_SDL3
|
||||
// SDL3 states:
|
||||
// The SDL_WINDOWEVENT_* events have been moved to top level events,
|
||||
// and SDL_WINDOWEVENT has been removed.
|
||||
|
|
@ -1436,7 +1437,7 @@ void PollInputEvents(void)
|
|||
{
|
||||
switch (event.window.event)
|
||||
{
|
||||
#endif
|
||||
#endif
|
||||
case SDL_WINDOWEVENT_RESIZED:
|
||||
case SDL_WINDOWEVENT_SIZE_CHANGED:
|
||||
{
|
||||
|
|
@ -1448,7 +1449,24 @@ void PollInputEvents(void)
|
|||
CORE.Window.currentFbo.width = width;
|
||||
CORE.Window.currentFbo.height = height;
|
||||
CORE.Window.resizedLastFrame = true;
|
||||
|
||||
#ifndef PLATFORM_DESKTOP_SDL3
|
||||
// Manually detect if the window was maximized (due to SDL2 restore being unreliable on some platforms) to remove the FLAG_WINDOW_MAXIMIZED accordingly
|
||||
if ((CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) > 0)
|
||||
{
|
||||
int borderTop = 0;
|
||||
int borderLeft = 0;
|
||||
int borderBottom = 0;
|
||||
int borderRight = 0;
|
||||
SDL_GetWindowBordersSize(platform.window, &borderTop, &borderLeft, &borderBottom, &borderRight);
|
||||
SDL_Rect usableBounds;
|
||||
SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(platform.window), &usableBounds);
|
||||
|
||||
if ((width + borderLeft + borderRight != usableBounds.w) && (height + borderTop + borderBottom != usableBounds.h)) CORE.Window.flags &= ~FLAG_WINDOW_MAXIMIZED;
|
||||
}
|
||||
#endif
|
||||
} break;
|
||||
|
||||
case SDL_WINDOWEVENT_ENTER:
|
||||
{
|
||||
CORE.Input.Mouse.cursorOnScreen = true;
|
||||
|
|
@ -1457,16 +1475,49 @@ void PollInputEvents(void)
|
|||
{
|
||||
CORE.Input.Mouse.cursorOnScreen = false;
|
||||
} break;
|
||||
case SDL_WINDOWEVENT_HIDDEN:
|
||||
|
||||
case SDL_WINDOWEVENT_MINIMIZED:
|
||||
case SDL_WINDOWEVENT_FOCUS_LOST:
|
||||
case SDL_WINDOWEVENT_SHOWN:
|
||||
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
||||
{
|
||||
if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) == 0) CORE.Window.flags |= FLAG_WINDOW_MINIMIZED;
|
||||
} break;
|
||||
case SDL_WINDOWEVENT_MAXIMIZED:
|
||||
{
|
||||
if ((CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) == 0) CORE.Window.flags |= FLAG_WINDOW_MAXIMIZED;
|
||||
} break;
|
||||
case SDL_WINDOWEVENT_RESTORED:
|
||||
#if defined(PLATFORM_DESKTOP_SDL3)
|
||||
break;
|
||||
#else
|
||||
{
|
||||
if ((SDL_GetWindowFlags(platform.window) & SDL_WINDOW_MINIMIZED) == 0)
|
||||
{
|
||||
if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0) CORE.Window.flags &= ~FLAG_WINDOW_MINIMIZED;
|
||||
}
|
||||
|
||||
#ifdef PLATFORM_DESKTOP_SDL3
|
||||
if ((SDL_GetWindowFlags(platform.window) & SDL_WINDOW_MAXIMIZED) == 0)
|
||||
{
|
||||
if ((CORE.Window.flags & SDL_WINDOW_MAXIMIZED) > 0) CORE.Window.flags &= ~SDL_WINDOW_MAXIMIZED;
|
||||
}
|
||||
#endif
|
||||
} break;
|
||||
|
||||
case SDL_WINDOWEVENT_HIDDEN:
|
||||
{
|
||||
if ((CORE.Window.flags & FLAG_WINDOW_HIDDEN) == 0) CORE.Window.flags |= FLAG_WINDOW_HIDDEN;
|
||||
} break;
|
||||
case SDL_WINDOWEVENT_SHOWN:
|
||||
{
|
||||
if ((CORE.Window.flags & FLAG_WINDOW_HIDDEN) > 0) CORE.Window.flags &= ~FLAG_WINDOW_HIDDEN;
|
||||
} break;
|
||||
|
||||
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
||||
{
|
||||
if ((CORE.Window.flags & FLAG_WINDOW_UNFOCUSED) > 0) CORE.Window.flags &= ~FLAG_WINDOW_UNFOCUSED;
|
||||
} break;
|
||||
case SDL_WINDOWEVENT_FOCUS_LOST:
|
||||
{
|
||||
if ((CORE.Window.flags & FLAG_WINDOW_UNFOCUSED) == 0) CORE.Window.flags |= FLAG_WINDOW_UNFOCUSED;
|
||||
} break;
|
||||
|
||||
#ifndef PLATFORM_DESKTOP_SDL3
|
||||
default: break;
|
||||
}
|
||||
} break;
|
||||
|
|
@ -1971,7 +2022,7 @@ void ClosePlatform(void)
|
|||
// Scancode to keycode mapping
|
||||
static KeyboardKey ConvertScancodeToKey(SDL_Scancode sdlScancode)
|
||||
{
|
||||
if (sdlScancode >= 0 && sdlScancode < SCANCODE_MAPPED_NUM)
|
||||
if ((sdlScancode >= 0) && (sdlScancode < SCANCODE_MAPPED_NUM))
|
||||
{
|
||||
return mapScancodeToKey[sdlScancode];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -622,7 +622,7 @@ int SetGamepadMappings(const char *mappings)
|
|||
// Set gamepad vibration
|
||||
void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "GamepadSetVibration() not implemented on target platform");
|
||||
TRACELOG(LOG_WARNING, "SetGamepadVibration() not implemented on target platform");
|
||||
}
|
||||
|
||||
// Set mouse position XY
|
||||
|
|
@ -1529,7 +1529,7 @@ static void ConfigureEvdevDevice(char *device)
|
|||
platform.absRange.height = absinfo[ABS_Y].info.maximum - absinfo[ABS_Y].info.minimum;
|
||||
}
|
||||
}
|
||||
else if (isGamepad && !isMouse && !isKeyboard && platform.gamepadCount < MAX_GAMEPADS)
|
||||
else if (isGamepad && !isMouse && !isKeyboard && (platform.gamepadCount < MAX_GAMEPADS))
|
||||
{
|
||||
deviceKindStr = "gamepad";
|
||||
int index = platform.gamepadCount++;
|
||||
|
|
@ -1893,7 +1893,7 @@ static int FindExactConnectorMode(const drmModeConnector *connector, uint width,
|
|||
|
||||
TRACELOG(LOG_TRACE, "DISPLAY: DRM Mode %d %ux%u@%u %s", i, mode->hdisplay, mode->vdisplay, mode->vrefresh, (mode->flags & DRM_MODE_FLAG_INTERLACE)? "interlaced" : "progressive");
|
||||
|
||||
if ((mode->flags & DRM_MODE_FLAG_INTERLACE) && (!allowInterlaced)) continue;
|
||||
if ((mode->flags & DRM_MODE_FLAG_INTERLACE) && !allowInterlaced) continue;
|
||||
|
||||
if ((mode->hdisplay == width) && (mode->vdisplay == height) && (mode->vrefresh == fps)) return i;
|
||||
}
|
||||
|
|
@ -1923,7 +1923,7 @@ static int FindNearestConnectorMode(const drmModeConnector *connector, uint widt
|
|||
continue;
|
||||
}
|
||||
|
||||
if ((mode->flags & DRM_MODE_FLAG_INTERLACE) && (!allowInterlaced))
|
||||
if ((mode->flags & DRM_MODE_FLAG_INTERLACE) && !allowInterlaced)
|
||||
{
|
||||
TRACELOG(LOG_TRACE, "DISPLAY: DRM shouldn't choose an interlaced mode");
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -381,6 +381,12 @@ int SetGamepadMappings(const char *mappings)
|
|||
return 0;
|
||||
}
|
||||
|
||||
// Set gamepad vibration
|
||||
void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "SetGamepadVibration() not implemented on target platform");
|
||||
}
|
||||
|
||||
// Set mouse position XY
|
||||
void SetMousePosition(int x, int y)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -319,7 +319,7 @@ void ToggleBorderlessWindowed(void)
|
|||
// Set window state: maximized, if resizable
|
||||
void MaximizeWindow(void)
|
||||
{
|
||||
if (glfwGetWindowAttrib(platform.handle, GLFW_RESIZABLE) == GLFW_TRUE && !(CORE.Window.flags & FLAG_WINDOW_MAXIMIZED))
|
||||
if ((glfwGetWindowAttrib(platform.handle, GLFW_RESIZABLE) == GLFW_TRUE) && !(CORE.Window.flags & FLAG_WINDOW_MAXIMIZED))
|
||||
{
|
||||
platform.unmaximizedWidth = CORE.Window.screen.width;
|
||||
platform.unmaximizedHeight = CORE.Window.screen.height;
|
||||
|
|
@ -342,7 +342,7 @@ void MinimizeWindow(void)
|
|||
// Set window state: not minimized/maximized
|
||||
void RestoreWindow(void)
|
||||
{
|
||||
if (glfwGetWindowAttrib(platform.handle, GLFW_RESIZABLE) == GLFW_TRUE && (CORE.Window.flags & FLAG_WINDOW_MAXIMIZED))
|
||||
if ((glfwGetWindowAttrib(platform.handle, GLFW_RESIZABLE) == GLFW_TRUE) && (CORE.Window.flags & FLAG_WINDOW_MAXIMIZED))
|
||||
{
|
||||
if (platform.unmaximizedWidth && platform.unmaximizedHeight) glfwSetWindowSize(platform.handle, platform.unmaximizedWidth, platform.unmaximizedHeight);
|
||||
|
||||
|
|
@ -1664,10 +1664,10 @@ static EM_BOOL EmscriptenResizeCallback(int eventType, const EmscriptenUiEvent *
|
|||
int height = EM_ASM_INT( return window.innerHeight; );
|
||||
|
||||
if (width < (int)CORE.Window.screenMin.width) width = CORE.Window.screenMin.width;
|
||||
else if (width > (int)CORE.Window.screenMax.width && CORE.Window.screenMax.width > 0) width = CORE.Window.screenMax.width;
|
||||
else if ((width > (int)CORE.Window.screenMax.width) && (CORE.Window.screenMax.width > 0)) width = CORE.Window.screenMax.width;
|
||||
|
||||
if (height < (int)CORE.Window.screenMin.height) height = CORE.Window.screenMin.height;
|
||||
else if (height > (int)CORE.Window.screenMax.height && CORE.Window.screenMax.height > 0) height = CORE.Window.screenMax.height;
|
||||
else if ((height > (int)CORE.Window.screenMax.height) && (CORE.Window.screenMax.height > 0)) height = CORE.Window.screenMax.height;
|
||||
|
||||
emscripten_set_canvas_element_size("#canvas", width, height);
|
||||
|
||||
|
|
@ -1722,7 +1722,7 @@ static EM_BOOL EmscriptenGamepadCallback(int eventType, const EmscriptenGamepadE
|
|||
for (int i = 0; i < gamepadEvent->numButtons; ++i) TRACELOGD("Button %d: Digital: %d, Analog: %g", i, gamepadEvent->digitalButton[i], gamepadEvent->analogButton[i]);
|
||||
*/
|
||||
|
||||
if ((gamepadEvent->connected) && (gamepadEvent->index < MAX_GAMEPADS))
|
||||
if (gamepadEvent->connected && (gamepadEvent->index < MAX_GAMEPADS))
|
||||
{
|
||||
CORE.Input.Gamepad.ready[gamepadEvent->index] = true;
|
||||
sprintf(CORE.Input.Gamepad.name[gamepadEvent->index], "%s", gamepadEvent->id);
|
||||
|
|
|
|||
25
src/raudio.c
25
src/raudio.c
|
|
@ -801,10 +801,10 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int
|
|||
wave.sampleRate = wav.sampleRate;
|
||||
wave.sampleSize = 16;
|
||||
wave.channels = wav.channels;
|
||||
wave.data = (short *)RL_MALLOC(wave.frameCount*wave.channels*sizeof(short));
|
||||
wave.data = (short *)RL_MALLOC((size_t)wave.frameCount*wave.channels*sizeof(short));
|
||||
|
||||
// NOTE: We are forcing conversion to 16bit sample size on reading
|
||||
drwav_read_pcm_frames_s16(&wav, wav.totalPCMFrameCount, wave.data);
|
||||
drwav_read_pcm_frames_s16(&wav, wave.frameCount, wave.data);
|
||||
}
|
||||
else TRACELOG(LOG_WARNING, "WAVE: Failed to load WAV data");
|
||||
|
||||
|
|
@ -1550,7 +1550,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
|
|||
else if ((strcmp(fileType, ".ogg") == 0) || (strcmp(fileType, ".OGG") == 0))
|
||||
{
|
||||
// Open ogg audio stream
|
||||
stb_vorbis* ctxOgg = stb_vorbis_open_memory((const unsigned char *)data, dataSize, NULL, NULL);
|
||||
stb_vorbis *ctxOgg = stb_vorbis_open_memory((const unsigned char *)data, dataSize, NULL, NULL);
|
||||
|
||||
if (ctxOgg != NULL)
|
||||
{
|
||||
|
|
@ -2461,23 +2461,18 @@ static ma_uint32 ReadAudioBufferFramesInMixingFormat(AudioBuffer *audioBuffer, f
|
|||
|
||||
float *runningFramesOut = framesOut + (totalOutputFramesProcessed*audioBuffer->converter.channelsOut);
|
||||
|
||||
/* At this point we can convert the data to our mixing format. */
|
||||
ma_uint64 inputFramesProcessedThisIteration = ReadAudioBufferFramesInInternalFormat(audioBuffer, inputBuffer, (ma_uint32)inputFramesToProcessThisIteration); /* Safe cast. */
|
||||
// At this point we can convert the data to our mixing format
|
||||
ma_uint64 inputFramesProcessedThisIteration = ReadAudioBufferFramesInInternalFormat(audioBuffer, inputBuffer, (ma_uint32)inputFramesToProcessThisIteration);
|
||||
ma_uint64 outputFramesProcessedThisIteration = outputFramesToProcessThisIteration;
|
||||
ma_data_converter_process_pcm_frames(&audioBuffer->converter, inputBuffer, &inputFramesProcessedThisIteration, runningFramesOut, &outputFramesProcessedThisIteration);
|
||||
|
||||
totalOutputFramesProcessed += (ma_uint32)outputFramesProcessedThisIteration; /* Safe cast. */
|
||||
totalOutputFramesProcessed += (ma_uint32)outputFramesProcessedThisIteration; // Safe cast
|
||||
|
||||
if (inputFramesProcessedThisIteration < inputFramesToProcessThisIteration)
|
||||
{
|
||||
break; /* Ran out of input data. */
|
||||
}
|
||||
if (inputFramesProcessedThisIteration < inputFramesToProcessThisIteration) break; // Ran out of input data
|
||||
|
||||
/* This should never be hit, but will add it here for safety. Ensures we get out of the loop when no input nor output frames are processed. */
|
||||
if (inputFramesProcessedThisIteration == 0 && outputFramesProcessedThisIteration == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
// This should never be hit, but added here for safety
|
||||
// Ensures we get out of the loop when no input nor output frames are processed
|
||||
if ((inputFramesProcessedThisIteration == 0) && (outputFramesProcessedThisIteration == 0)) break;
|
||||
}
|
||||
|
||||
return totalOutputFramesProcessed;
|
||||
|
|
|
|||
133
src/raylib.h
133
src/raylib.h
|
|
@ -801,7 +801,8 @@ typedef enum {
|
|||
SHADER_LOC_MAP_BRDF, // Shader location: sampler2d texture: brdf
|
||||
SHADER_LOC_VERTEX_BONEIDS, // Shader location: vertex attribute: boneIds
|
||||
SHADER_LOC_VERTEX_BONEWEIGHTS, // Shader location: vertex attribute: boneWeights
|
||||
SHADER_LOC_BONE_MATRICES // Shader location: array of matrices uniform: boneMatrices
|
||||
SHADER_LOC_BONE_MATRICES, // Shader location: array of matrices uniform: boneMatrices
|
||||
SHADER_LOC_VERTEX_INSTANCE_TX // Shader location: vertex attribute: instanceTransform
|
||||
} ShaderLocationIndex;
|
||||
|
||||
#define SHADER_LOC_MAP_DIFFUSE SHADER_LOC_MAP_ALBEDO
|
||||
|
|
@ -817,6 +818,10 @@ typedef enum {
|
|||
SHADER_UNIFORM_IVEC2, // Shader uniform type: ivec2 (2 int)
|
||||
SHADER_UNIFORM_IVEC3, // Shader uniform type: ivec3 (3 int)
|
||||
SHADER_UNIFORM_IVEC4, // Shader uniform type: ivec4 (4 int)
|
||||
SHADER_UNIFORM_UINT, // Shader uniform type: unsigned int
|
||||
SHADER_UNIFORM_UIVEC2, // Shader uniform type: uivec2 (2 unsigned int)
|
||||
SHADER_UNIFORM_UIVEC3, // Shader uniform type: uivec3 (3 unsigned int)
|
||||
SHADER_UNIFORM_UIVEC4, // Shader uniform type: uivec4 (4 unsigned int)
|
||||
SHADER_UNIFORM_SAMPLER2D // Shader uniform type: sampler2d
|
||||
} ShaderUniformDataType;
|
||||
|
||||
|
|
@ -1150,20 +1155,19 @@ RLAPI unsigned char *CompressData(const unsigned char *data, int dataSize, int *
|
|||
RLAPI unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize); // Decompress data (DEFLATE algorithm), memory must be MemFree()
|
||||
RLAPI char *EncodeDataBase64(const unsigned char *data, int dataSize, int *outputSize); // Encode data to Base64 string, memory must be MemFree()
|
||||
RLAPI unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize); // Decode Base64 string data, memory must be MemFree()
|
||||
RLAPI unsigned int ComputeCRC32(unsigned char *data, int dataSize); // Compute CRC32 hash code
|
||||
RLAPI unsigned int *ComputeMD5(unsigned char *data, int dataSize); // Compute MD5 hash code, returns static int[4] (16 bytes)
|
||||
RLAPI unsigned int *ComputeSHA1(unsigned char *data, int dataSize); // Compute SHA1 hash code, returns static int[5] (20 bytes)
|
||||
|
||||
RLAPI unsigned int ComputeCRC32(unsigned char *data, int dataSize); // Compute CRC32 hash code
|
||||
RLAPI unsigned int *ComputeMD5(unsigned char *data, int dataSize); // Compute MD5 hash code, returns static int[4] (16 bytes)
|
||||
RLAPI unsigned int *ComputeSHA1(unsigned char *data, int dataSize); // Compute SHA1 hash code, returns static int[5] (20 bytes)
|
||||
|
||||
// Automation events functionality
|
||||
RLAPI AutomationEventList LoadAutomationEventList(const char *fileName); // Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS
|
||||
RLAPI void UnloadAutomationEventList(AutomationEventList list); // Unload automation events list from file
|
||||
RLAPI bool ExportAutomationEventList(AutomationEventList list, const char *fileName); // Export automation events list as text file
|
||||
RLAPI void SetAutomationEventList(AutomationEventList *list); // Set automation event list to record to
|
||||
RLAPI void SetAutomationEventBaseFrame(int frame); // Set automation event internal base frame to start recording
|
||||
RLAPI void StartAutomationEventRecording(void); // Start recording automation events (AutomationEventList must be set)
|
||||
RLAPI void StopAutomationEventRecording(void); // Stop recording automation events
|
||||
RLAPI void PlayAutomationEvent(AutomationEvent event); // Play a recorded automation event
|
||||
RLAPI AutomationEventList LoadAutomationEventList(const char *fileName); // Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS
|
||||
RLAPI void UnloadAutomationEventList(AutomationEventList list); // Unload automation events list from file
|
||||
RLAPI bool ExportAutomationEventList(AutomationEventList list, const char *fileName); // Export automation events list as text file
|
||||
RLAPI void SetAutomationEventList(AutomationEventList *list); // Set automation event list to record to
|
||||
RLAPI void SetAutomationEventBaseFrame(int frame); // Set automation event internal base frame to start recording
|
||||
RLAPI void StartAutomationEventRecording(void); // Start recording automation events (AutomationEventList must be set)
|
||||
RLAPI void StopAutomationEventRecording(void); // Stop recording automation events
|
||||
RLAPI void PlayAutomationEvent(AutomationEvent event); // Play a recorded automation event
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Input Handling Functions (Module: core)
|
||||
|
|
@ -1177,19 +1181,20 @@ RLAPI bool IsKeyReleased(int key); // Check if a key
|
|||
RLAPI bool IsKeyUp(int key); // Check if a key is NOT being pressed
|
||||
RLAPI int GetKeyPressed(void); // Get key pressed (keycode), call it multiple times for keys queued, returns 0 when the queue is empty
|
||||
RLAPI int GetCharPressed(void); // Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty
|
||||
RLAPI const char *GetKeyName(int key); // Get name of a QWERTY key on the current keyboard layout (eg returns string 'q' for KEY_A on an AZERTY keyboard)
|
||||
RLAPI void SetExitKey(int key); // Set a custom key to exit program (default is ESC)
|
||||
|
||||
// Input-related functions: gamepads
|
||||
RLAPI bool IsGamepadAvailable(int gamepad); // Check if a gamepad is available
|
||||
RLAPI const char *GetGamepadName(int gamepad); // Get gamepad internal name id
|
||||
RLAPI bool IsGamepadButtonPressed(int gamepad, int button); // Check if a gamepad button has been pressed once
|
||||
RLAPI bool IsGamepadButtonDown(int gamepad, int button); // Check if a gamepad button is being pressed
|
||||
RLAPI bool IsGamepadButtonReleased(int gamepad, int button); // Check if a gamepad button has been released once
|
||||
RLAPI bool IsGamepadButtonUp(int gamepad, int button); // Check if a gamepad button is NOT being pressed
|
||||
RLAPI int GetGamepadButtonPressed(void); // Get the last gamepad button pressed
|
||||
RLAPI int GetGamepadAxisCount(int gamepad); // Get gamepad axis count for a gamepad
|
||||
RLAPI float GetGamepadAxisMovement(int gamepad, int axis); // Get axis movement value for a gamepad axis
|
||||
RLAPI int SetGamepadMappings(const char *mappings); // Set internal gamepad mappings (SDL_GameControllerDB)
|
||||
RLAPI bool IsGamepadAvailable(int gamepad); // Check if a gamepad is available
|
||||
RLAPI const char *GetGamepadName(int gamepad); // Get gamepad internal name id
|
||||
RLAPI bool IsGamepadButtonPressed(int gamepad, int button); // Check if a gamepad button has been pressed once
|
||||
RLAPI bool IsGamepadButtonDown(int gamepad, int button); // Check if a gamepad button is being pressed
|
||||
RLAPI bool IsGamepadButtonReleased(int gamepad, int button); // Check if a gamepad button has been released once
|
||||
RLAPI bool IsGamepadButtonUp(int gamepad, int button); // Check if a gamepad button is NOT being pressed
|
||||
RLAPI int GetGamepadButtonPressed(void); // Get the last gamepad button pressed
|
||||
RLAPI int GetGamepadAxisCount(int gamepad); // Get gamepad axis count for a gamepad
|
||||
RLAPI float GetGamepadAxisMovement(int gamepad, int axis); // Get axis movement value for a gamepad axis
|
||||
RLAPI int SetGamepadMappings(const char *mappings); // Set internal gamepad mappings (SDL_GameControllerDB)
|
||||
RLAPI void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration); // Set gamepad vibration for both motors (duration in seconds)
|
||||
|
||||
// Input-related functions: mouse
|
||||
|
|
@ -1218,19 +1223,19 @@ RLAPI int GetTouchPointCount(void); // Get number of t
|
|||
//------------------------------------------------------------------------------------
|
||||
// Gestures and Touch Handling Functions (Module: rgestures)
|
||||
//------------------------------------------------------------------------------------
|
||||
RLAPI void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags
|
||||
RLAPI bool IsGestureDetected(unsigned int gesture); // Check if a gesture have been detected
|
||||
RLAPI int GetGestureDetected(void); // Get latest detected gesture
|
||||
RLAPI float GetGestureHoldDuration(void); // Get gesture hold time in seconds
|
||||
RLAPI Vector2 GetGestureDragVector(void); // Get gesture drag vector
|
||||
RLAPI float GetGestureDragAngle(void); // Get gesture drag angle
|
||||
RLAPI Vector2 GetGesturePinchVector(void); // Get gesture pinch delta
|
||||
RLAPI float GetGesturePinchAngle(void); // Get gesture pinch angle
|
||||
RLAPI void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags
|
||||
RLAPI bool IsGestureDetected(unsigned int gesture); // Check if a gesture have been detected
|
||||
RLAPI int GetGestureDetected(void); // Get latest detected gesture
|
||||
RLAPI float GetGestureHoldDuration(void); // Get gesture hold time in seconds
|
||||
RLAPI Vector2 GetGestureDragVector(void); // Get gesture drag vector
|
||||
RLAPI float GetGestureDragAngle(void); // Get gesture drag angle
|
||||
RLAPI Vector2 GetGesturePinchVector(void); // Get gesture pinch delta
|
||||
RLAPI float GetGesturePinchAngle(void); // Get gesture pinch angle
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Camera System Functions (Module: rcamera)
|
||||
//------------------------------------------------------------------------------------
|
||||
RLAPI void UpdateCamera(Camera *camera, int mode); // Update camera position for selected mode
|
||||
RLAPI void UpdateCamera(Camera *camera, int mode); // Update camera position for selected mode
|
||||
RLAPI void UpdateCameraPro(Camera *camera, Vector3 movement, Vector3 rotation, float zoom); // Update camera movement/rotation
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
|
|
@ -1239,9 +1244,9 @@ RLAPI void UpdateCameraPro(Camera *camera, Vector3 movement, Vector3 rotation, f
|
|||
// Set texture and rectangle to be used on shapes drawing
|
||||
// NOTE: It can be useful when using basic shapes and one single font,
|
||||
// defining a font char white rectangle would allow drawing everything in a single draw call
|
||||
RLAPI void SetShapesTexture(Texture2D texture, Rectangle source); // Set texture and rectangle to be used on shapes drawing
|
||||
RLAPI Texture2D GetShapesTexture(void); // Get texture that is used for shapes drawing
|
||||
RLAPI Rectangle GetShapesTextureRectangle(void); // Get texture source rectangle that is used for shapes drawing
|
||||
RLAPI void SetShapesTexture(Texture2D texture, Rectangle source); // Set texture and rectangle to be used on shapes drawing
|
||||
RLAPI Texture2D GetShapesTexture(void); // Get texture that is used for shapes drawing
|
||||
RLAPI Rectangle GetShapesTextureRectangle(void); // Get texture source rectangle that is used for shapes drawing
|
||||
|
||||
// Basic shapes drawing functions
|
||||
RLAPI void DrawPixel(int posX, int posY, Color color); // Draw a pixel using geometry [Can be slow, use with care]
|
||||
|
|
@ -1283,11 +1288,11 @@ RLAPI void DrawPolyLines(Vector2 center, int sides, float radius, float rotation
|
|||
RLAPI void DrawPolyLinesEx(Vector2 center, int sides, float radius, float rotation, float lineThick, Color color); // Draw a polygon outline of n sides with extended parameters
|
||||
|
||||
// Splines drawing functions
|
||||
RLAPI void DrawSplineLinear(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Linear, minimum 2 points
|
||||
RLAPI void DrawSplineBasis(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: B-Spline, minimum 4 points
|
||||
RLAPI void DrawSplineCatmullRom(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Catmull-Rom, minimum 4 points
|
||||
RLAPI void DrawSplineBezierQuadratic(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Quadratic Bezier, minimum 3 points (1 control point): [p1, c2, p3, c4...]
|
||||
RLAPI void DrawSplineBezierCubic(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Cubic Bezier, minimum 4 points (2 control points): [p1, c2, c3, p4, c5, c6...]
|
||||
RLAPI void DrawSplineLinear(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Linear, minimum 2 points
|
||||
RLAPI void DrawSplineBasis(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: B-Spline, minimum 4 points
|
||||
RLAPI void DrawSplineCatmullRom(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Catmull-Rom, minimum 4 points
|
||||
RLAPI void DrawSplineBezierQuadratic(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Quadratic Bezier, minimum 3 points (1 control point): [p1, c2, p3, c4...]
|
||||
RLAPI void DrawSplineBezierCubic(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Cubic Bezier, minimum 4 points (2 control points): [p1, c2, c3, p4, c5, c6...]
|
||||
RLAPI void DrawSplineSegmentLinear(Vector2 p1, Vector2 p2, float thick, Color color); // Draw spline segment: Linear, 2 points
|
||||
RLAPI void DrawSplineSegmentBasis(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float thick, Color color); // Draw spline segment: B-Spline, 4 points
|
||||
RLAPI void DrawSplineSegmentCatmullRom(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float thick, Color color); // Draw spline segment: Catmull-Rom, 4 points
|
||||
|
|
@ -1486,15 +1491,15 @@ RLAPI GlyphInfo GetGlyphInfo(Font font, int codepoint);
|
|||
RLAPI Rectangle GetGlyphAtlasRec(Font font, int codepoint); // Get glyph rectangle in font atlas for a codepoint (unicode character), fallback to '?' if not found
|
||||
|
||||
// Text codepoints management functions (unicode characters)
|
||||
RLAPI char *LoadUTF8(const int *codepoints, int length); // Load UTF-8 text encoded from codepoints array
|
||||
RLAPI void UnloadUTF8(char *text); // Unload UTF-8 text encoded from codepoints array
|
||||
RLAPI int *LoadCodepoints(const char *text, int *count); // Load all codepoints from a UTF-8 text string, codepoints count returned by parameter
|
||||
RLAPI void UnloadCodepoints(int *codepoints); // Unload codepoints data from memory
|
||||
RLAPI int GetCodepointCount(const char *text); // Get total number of codepoints in a UTF-8 encoded string
|
||||
RLAPI int GetCodepoint(const char *text, int *codepointSize); // Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
|
||||
RLAPI int GetCodepointNext(const char *text, int *codepointSize); // Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
|
||||
RLAPI int GetCodepointPrevious(const char *text, int *codepointSize); // Get previous codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
|
||||
RLAPI const char *CodepointToUTF8(int codepoint, int *utf8Size); // Encode one codepoint into UTF-8 byte array (array length returned as parameter)
|
||||
RLAPI char *LoadUTF8(const int *codepoints, int length); // Load UTF-8 text encoded from codepoints array
|
||||
RLAPI void UnloadUTF8(char *text); // Unload UTF-8 text encoded from codepoints array
|
||||
RLAPI int *LoadCodepoints(const char *text, int *count); // Load all codepoints from a UTF-8 text string, codepoints count returned by parameter
|
||||
RLAPI void UnloadCodepoints(int *codepoints); // Unload codepoints data from memory
|
||||
RLAPI int GetCodepointCount(const char *text); // Get total number of codepoints in a UTF-8 encoded string
|
||||
RLAPI int GetCodepoint(const char *text, int *codepointSize); // Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
|
||||
RLAPI int GetCodepointNext(const char *text, int *codepointSize); // Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
|
||||
RLAPI int GetCodepointPrevious(const char *text, int *codepointSize); // Get previous codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
|
||||
RLAPI const char *CodepointToUTF8(int codepoint, int *utf8Size); // Encode one codepoint into UTF-8 byte array (array length returned as parameter)
|
||||
|
||||
// Text strings management functions (no UTF-8 strings, only byte chars)
|
||||
// NOTE: Some strings allocate memory internally for returned strings, just be careful!
|
||||
|
|
@ -1509,14 +1514,14 @@ RLAPI const char *TextJoin(const char **textList, int count, const char *delimit
|
|||
RLAPI const char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings
|
||||
RLAPI void TextAppend(char *text, const char *append, int *position); // Append text at specific position and move cursor!
|
||||
RLAPI int TextFindIndex(const char *text, const char *find); // Find first text occurrence within a string
|
||||
RLAPI const char *TextToUpper(const char *text); // Get upper case version of provided string
|
||||
RLAPI const char *TextToLower(const char *text); // Get lower case version of provided string
|
||||
RLAPI const char *TextToPascal(const char *text); // Get Pascal case notation version of provided string
|
||||
RLAPI const char *TextToSnake(const char *text); // Get Snake case notation version of provided string
|
||||
RLAPI const char *TextToCamel(const char *text); // Get Camel case notation version of provided string
|
||||
RLAPI const char *TextToUpper(const char *text); // Get upper case version of provided string
|
||||
RLAPI const char *TextToLower(const char *text); // Get lower case version of provided string
|
||||
RLAPI const char *TextToPascal(const char *text); // Get Pascal case notation version of provided string
|
||||
RLAPI const char *TextToSnake(const char *text); // Get Snake case notation version of provided string
|
||||
RLAPI const char *TextToCamel(const char *text); // Get Camel case notation version of provided string
|
||||
|
||||
RLAPI int TextToInteger(const char *text); // Get integer value from text (negative values not supported)
|
||||
RLAPI float TextToFloat(const char *text); // Get float value from text (negative values not supported)
|
||||
RLAPI int TextToInteger(const char *text); // Get integer value from text
|
||||
RLAPI float TextToFloat(const char *text); // Get float value from text
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Basic 3d Shapes Drawing Functions (Module: models)
|
||||
|
|
@ -1609,14 +1614,14 @@ RLAPI void UnloadModelAnimations(ModelAnimation *animations, int animCount);
|
|||
RLAPI bool IsModelAnimationValid(Model model, ModelAnimation anim); // Check model animation skeleton match
|
||||
|
||||
// Collision detection functions
|
||||
RLAPI bool CheckCollisionSpheres(Vector3 center1, float radius1, Vector3 center2, float radius2); // Check collision between two spheres
|
||||
RLAPI bool CheckCollisionBoxes(BoundingBox box1, BoundingBox box2); // Check collision between two bounding boxes
|
||||
RLAPI bool CheckCollisionBoxSphere(BoundingBox box, Vector3 center, float radius); // Check collision between box and sphere
|
||||
RLAPI RayCollision GetRayCollisionSphere(Ray ray, Vector3 center, float radius); // Get collision info between ray and sphere
|
||||
RLAPI RayCollision GetRayCollisionBox(Ray ray, BoundingBox box); // Get collision info between ray and box
|
||||
RLAPI RayCollision GetRayCollisionMesh(Ray ray, Mesh mesh, Matrix transform); // Get collision info between ray and mesh
|
||||
RLAPI RayCollision GetRayCollisionTriangle(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3); // Get collision info between ray and triangle
|
||||
RLAPI RayCollision GetRayCollisionQuad(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4); // Get collision info between ray and quad
|
||||
RLAPI bool CheckCollisionSpheres(Vector3 center1, float radius1, Vector3 center2, float radius2); // Check collision between two spheres
|
||||
RLAPI bool CheckCollisionBoxes(BoundingBox box1, BoundingBox box2); // Check collision between two bounding boxes
|
||||
RLAPI bool CheckCollisionBoxSphere(BoundingBox box, Vector3 center, float radius); // Check collision between box and sphere
|
||||
RLAPI RayCollision GetRayCollisionSphere(Ray ray, Vector3 center, float radius); // Get collision info between ray and sphere
|
||||
RLAPI RayCollision GetRayCollisionBox(Ray ray, BoundingBox box); // Get collision info between ray and box
|
||||
RLAPI RayCollision GetRayCollisionMesh(Ray ray, Mesh mesh, Matrix transform); // Get collision info between ray and mesh
|
||||
RLAPI RayCollision GetRayCollisionTriangle(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3); // Get collision info between ray and triangle
|
||||
RLAPI RayCollision GetRayCollisionQuad(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4); // Get collision info between ray and quad
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Audio Loading and Playing Functions (Module: audio)
|
||||
|
|
|
|||
|
|
@ -328,8 +328,9 @@ RMAPI float Vector2DistanceSqr(Vector2 v1, Vector2 v2)
|
|||
return result;
|
||||
}
|
||||
|
||||
// Calculate angle between two vectors
|
||||
// NOTE: Angle is calculated from origin point (0, 0)
|
||||
// Calculate the signed angle from v1 to v2, relative to the origin (0, 0)
|
||||
// NOTE: Coordinate system convention: positive X right, positive Y down,
|
||||
// positive angles appear clockwise, and negative angles appear counterclockwise
|
||||
RMAPI float Vector2Angle(Vector2 v1, Vector2 v2)
|
||||
{
|
||||
float result = 0.0f;
|
||||
|
|
@ -2664,12 +2665,12 @@ inline const Vector2& operator *= (Vector2& lhs, const Matrix& rhs)
|
|||
|
||||
inline Vector2 operator / (const Vector2& lhs, const float& rhs)
|
||||
{
|
||||
return Vector2Scale(lhs, 1.0f / rhs);
|
||||
return Vector2Scale(lhs, 1.0f/rhs);
|
||||
}
|
||||
|
||||
inline const Vector2& operator /= (Vector2& lhs, const float& rhs)
|
||||
{
|
||||
lhs = Vector2Scale(lhs, 1.0f / rhs);
|
||||
lhs = Vector2Scale(lhs, 1.0f/rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
|
|
@ -2758,12 +2759,12 @@ inline const Vector3& operator *= (Vector3& lhs, const Matrix& rhs)
|
|||
|
||||
inline Vector3 operator / (const Vector3& lhs, const float& rhs)
|
||||
{
|
||||
return Vector3Scale(lhs, 1.0f / rhs);
|
||||
return Vector3Scale(lhs, 1.0f/rhs);
|
||||
}
|
||||
|
||||
inline const Vector3& operator /= (Vector3& lhs, const float& rhs)
|
||||
{
|
||||
lhs = Vector3Scale(lhs, 1.0f / rhs);
|
||||
lhs = Vector3Scale(lhs, 1.0f/rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
|
|
@ -2842,12 +2843,12 @@ inline const Vector4& operator *= (Vector4& lhs, const Vector4& rhs)
|
|||
|
||||
inline Vector4 operator / (const Vector4& lhs, const float& rhs)
|
||||
{
|
||||
return Vector4Scale(lhs, 1.0f / rhs);
|
||||
return Vector4Scale(lhs, 1.0f/rhs);
|
||||
}
|
||||
|
||||
inline const Vector4& operator /= (Vector4& lhs, const float& rhs)
|
||||
{
|
||||
lhs = Vector4Scale(lhs, 1.0f / rhs);
|
||||
lhs = Vector4Scale(lhs, 1.0f/rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ RLAPI void CameraPitch(Camera *camera, float angle, bool lockView, bool rotateAr
|
|||
RLAPI void CameraRoll(Camera *camera, float angle);
|
||||
|
||||
RLAPI Matrix GetCameraViewMatrix(Camera *camera);
|
||||
RLAPI Matrix GetCameraProjectionMatrix(Camera* camera, float aspect);
|
||||
RLAPI Matrix GetCameraProjectionMatrix(Camera *camera, float aspect);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
|
|
|
|||
39
src/rcore.c
39
src/rcore.c
|
|
@ -1355,6 +1355,7 @@ Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode)
|
|||
shader.locs[SHADER_LOC_VERTEX_COLOR] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR);
|
||||
shader.locs[SHADER_LOC_VERTEX_BONEIDS] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS);
|
||||
shader.locs[SHADER_LOC_VERTEX_BONEWEIGHTS] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS);
|
||||
shader.locs[SHADER_LOC_VERTEX_INSTANCE_TX] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_INSTANCE_TX);
|
||||
|
||||
// Get handles to GLSL uniform locations (vertex shader)
|
||||
shader.locs[SHADER_LOC_MATRIX_MVP] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_MVP);
|
||||
|
|
@ -2071,7 +2072,7 @@ const char *GetDirectoryPath(const char *filePath)
|
|||
|
||||
// In case provided path does not contain a root drive letter (C:\, D:\) nor leading path separator (\, /),
|
||||
// we add the current directory path to dirPath
|
||||
if (filePath[1] != ':' && filePath[0] != '\\' && filePath[0] != '/')
|
||||
if ((filePath[1] != ':') && (filePath[0] != '\\') && (filePath[0] != '/'))
|
||||
{
|
||||
// For security, we set starting path to current directory,
|
||||
// obtained path will be concatenated to this
|
||||
|
|
@ -2774,7 +2775,8 @@ unsigned int *ComputeMD5(unsigned char *data, int dataSize)
|
|||
|
||||
// Compute SHA-1 hash code
|
||||
// NOTE: Returns a static int[5] array (20 bytes)
|
||||
unsigned int *ComputeSHA1(unsigned char *data, int dataSize) {
|
||||
unsigned int *ComputeSHA1(unsigned char *data, int dataSize)
|
||||
{
|
||||
#define ROTATE_LEFT(x, c) (((x) << (c)) | ((x) >> (32 - (c))))
|
||||
|
||||
static unsigned int hash[5] = { 0 }; // Hash to be returned
|
||||
|
|
@ -2809,17 +2811,16 @@ unsigned int *ComputeSHA1(unsigned char *data, int dataSize) {
|
|||
{
|
||||
// Break chunk into sixteen 32-bit words w[j], 0 <= j <= 15
|
||||
unsigned int w[80] = {0};
|
||||
for (int i = 0; i < 16; i++) {
|
||||
w[i] = (msg[offset + (i * 4) + 0] << 24) |
|
||||
(msg[offset + (i * 4) + 1] << 16) |
|
||||
(msg[offset + (i * 4) + 2] << 8) |
|
||||
(msg[offset + (i * 4) + 3]);
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
w[i] = (msg[offset + (i*4) + 0] << 24) |
|
||||
(msg[offset + (i*4) + 1] << 16) |
|
||||
(msg[offset + (i*4) + 2] << 8) |
|
||||
(msg[offset + (i*4) + 3]);
|
||||
}
|
||||
|
||||
// Message schedule: extend the sixteen 32-bit words into eighty 32-bit words:
|
||||
for (int i = 16; i < 80; ++i) {
|
||||
w[i] = ROTATE_LEFT(w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16], 1);
|
||||
}
|
||||
for (int i = 16; i < 80; i++) w[i] = ROTATE_LEFT(w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16], 1);
|
||||
|
||||
// Initialize hash value for this chunk
|
||||
unsigned int a = hash[0];
|
||||
|
|
@ -2833,16 +2834,23 @@ unsigned int *ComputeSHA1(unsigned char *data, int dataSize) {
|
|||
unsigned int f = 0;
|
||||
unsigned int k = 0;
|
||||
|
||||
if (i < 20) {
|
||||
if (i < 20)
|
||||
{
|
||||
f = (b & c) | ((~b) & d);
|
||||
k = 0x5A827999;
|
||||
} else if (i < 40) {
|
||||
}
|
||||
else if (i < 40)
|
||||
{
|
||||
f = b ^ c ^ d;
|
||||
k = 0x6ED9EBA1;
|
||||
} else if (i < 60) {
|
||||
}
|
||||
else if (i < 60)
|
||||
{
|
||||
f = (b & c) | (b & d) | (c & d);
|
||||
k = 0x8F1BBCDC;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
f = b ^ c ^ d;
|
||||
k = 0xCA62C1D6;
|
||||
}
|
||||
|
|
@ -3324,7 +3332,8 @@ float GetGamepadAxisMovement(int gamepad, int axis)
|
|||
{
|
||||
float value = (axis == GAMEPAD_AXIS_LEFT_TRIGGER || axis == GAMEPAD_AXIS_RIGHT_TRIGGER)? -1.0f : 0.0f;
|
||||
|
||||
if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (axis < MAX_GAMEPAD_AXIS)) {
|
||||
if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (axis < MAX_GAMEPAD_AXIS))
|
||||
{
|
||||
float movement = value < 0.0f ? CORE.Input.Gamepad.axisState[gamepad][axis] : fabsf(CORE.Input.Gamepad.axisState[gamepad][axis]);
|
||||
|
||||
if (movement > value) value = CORE.Input.Gamepad.axisState[gamepad][axis];
|
||||
|
|
|
|||
25
src/rlgl.h
25
src/rlgl.h
|
|
@ -355,6 +355,9 @@
|
|||
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS 8
|
||||
#endif
|
||||
#endif
|
||||
#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_INSTANCE_TX
|
||||
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_INSTANCE_TX 9
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Types and Structures Definition
|
||||
|
|
@ -998,6 +1001,9 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad
|
|||
#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS
|
||||
#define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS "vertexBoneWeights" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS
|
||||
#endif
|
||||
#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_INSTANCE_TX
|
||||
#define RL_DEFAULT_SHADER_ATTRIB_NAME_INSTANCE_TX "instanceTransform" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_INSTANCE_TX
|
||||
#endif
|
||||
|
||||
#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_MVP
|
||||
#define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix
|
||||
|
|
@ -1884,16 +1890,6 @@ void rlActiveDrawBuffers(int count)
|
|||
else
|
||||
{
|
||||
unsigned int buffers[8] = {
|
||||
#if defined(GRAPHICS_API_OPENGL_ES3)
|
||||
GL_COLOR_ATTACHMENT0_EXT,
|
||||
GL_COLOR_ATTACHMENT1_EXT,
|
||||
GL_COLOR_ATTACHMENT2_EXT,
|
||||
GL_COLOR_ATTACHMENT3_EXT,
|
||||
GL_COLOR_ATTACHMENT4_EXT,
|
||||
GL_COLOR_ATTACHMENT5_EXT,
|
||||
GL_COLOR_ATTACHMENT6_EXT,
|
||||
GL_COLOR_ATTACHMENT7_EXT,
|
||||
#else
|
||||
GL_COLOR_ATTACHMENT0,
|
||||
GL_COLOR_ATTACHMENT1,
|
||||
GL_COLOR_ATTACHMENT2,
|
||||
|
|
@ -1902,14 +1898,9 @@ void rlActiveDrawBuffers(int count)
|
|||
GL_COLOR_ATTACHMENT5,
|
||||
GL_COLOR_ATTACHMENT6,
|
||||
GL_COLOR_ATTACHMENT7,
|
||||
#endif
|
||||
};
|
||||
|
||||
#if defined(GRAPHICS_API_OPENGL_ES3)
|
||||
glDrawBuffersEXT(count, buffers);
|
||||
#else
|
||||
glDrawBuffers(count, buffers);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else TRACELOG(LOG_WARNING, "GL: One color buffer active by default");
|
||||
|
|
@ -3310,6 +3301,7 @@ unsigned int rlLoadTexture(const void *data, int width, int height, int format,
|
|||
// Activate Trilinear filtering if mipmaps are available
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, mipmapCount); // user defined mip count would break without this.
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -3959,7 +3951,7 @@ void rlDrawVertexArrayElements(int offset, int count, const void *buffer)
|
|||
void rlDrawVertexArrayInstanced(int offset, int count, int instances)
|
||||
{
|
||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||
glDrawArraysInstanced(GL_TRIANGLES, 0, count, instances);
|
||||
glDrawArraysInstanced(GL_TRIANGLES, offset, count, instances);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -4216,6 +4208,7 @@ unsigned int rlLoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId)
|
|||
glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR, RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR);
|
||||
glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT, RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT);
|
||||
glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2, RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2);
|
||||
glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_INSTANCE_TX, RL_DEFAULT_SHADER_ATTRIB_NAME_INSTANCE_TX);
|
||||
|
||||
#ifdef RL_SUPPORT_MESH_GPU_SKINNING
|
||||
glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS, RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS);
|
||||
|
|
|
|||
238
src/rmodels.c
238
src/rmodels.c
|
|
@ -96,9 +96,9 @@
|
|||
#endif
|
||||
|
||||
#if defined(SUPPORT_MESH_GENERATION)
|
||||
#define PAR_MALLOC(T, N) ((T*)RL_MALLOC(N*sizeof(T)))
|
||||
#define PAR_CALLOC(T, N) ((T*)RL_CALLOC(N*sizeof(T), 1))
|
||||
#define PAR_REALLOC(T, BUF, N) ((T*)RL_REALLOC(BUF, sizeof(T)*(N)))
|
||||
#define PAR_MALLOC(T, N) ((T *)RL_MALLOC(N*sizeof(T)))
|
||||
#define PAR_CALLOC(T, N) ((T *)RL_CALLOC(N*sizeof(T), 1))
|
||||
#define PAR_REALLOC(T, BUF, N) ((T *)RL_REALLOC(BUF, sizeof(T)*(N)))
|
||||
#define PAR_FREE RL_FREE
|
||||
|
||||
#if defined(_MSC_VER) // Disable some MSVC warning
|
||||
|
|
@ -1734,12 +1734,12 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i
|
|||
// no faster, since we're transferring all the transform matrices anyway
|
||||
instancesVboId = rlLoadVertexBuffer(instanceTransforms, instances*sizeof(float16), false);
|
||||
|
||||
// Instances transformation matrices are send to shader attribute location: SHADER_LOC_MATRIX_MODEL
|
||||
// Instances transformation matrices are sent to shader attribute location: SHADER_LOC_VERTEX_INSTANCE_TX
|
||||
for (unsigned int i = 0; i < 4; i++)
|
||||
{
|
||||
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_MATRIX_MODEL] + i);
|
||||
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_MATRIX_MODEL] + i, 4, RL_FLOAT, 0, sizeof(Matrix), i*sizeof(Vector4));
|
||||
rlSetVertexAttributeDivisor(material.shader.locs[SHADER_LOC_MATRIX_MODEL] + i, 1);
|
||||
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_INSTANCE_TX] + i);
|
||||
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_INSTANCE_TX] + i, 4, RL_FLOAT, 0, sizeof(Matrix), i*sizeof(Vector4));
|
||||
rlSetVertexAttributeDivisor(material.shader.locs[SHADER_LOC_VERTEX_INSTANCE_TX] + i, 1);
|
||||
}
|
||||
|
||||
rlDisableVertexBuffer();
|
||||
|
|
@ -2270,50 +2270,73 @@ void UpdateModelAnimationBones(Model model, ModelAnimation anim, int frame)
|
|||
{
|
||||
if (frame >= anim.frameCount) frame = frame%anim.frameCount;
|
||||
|
||||
// Get first mesh which have bones
|
||||
int firstMeshWithBones = -1;
|
||||
|
||||
for (int i = 0; i < model.meshCount; i++)
|
||||
{
|
||||
if (model.meshes[i].boneMatrices)
|
||||
{
|
||||
assert(model.meshes[i].boneCount == anim.boneCount);
|
||||
|
||||
for (int boneId = 0; boneId < model.meshes[i].boneCount; boneId++)
|
||||
if (firstMeshWithBones == -1)
|
||||
{
|
||||
Vector3 inTranslation = model.bindPose[boneId].translation;
|
||||
Quaternion inRotation = model.bindPose[boneId].rotation;
|
||||
Vector3 inScale = model.bindPose[boneId].scale;
|
||||
firstMeshWithBones = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 outTranslation = anim.framePoses[frame][boneId].translation;
|
||||
Quaternion outRotation = anim.framePoses[frame][boneId].rotation;
|
||||
Vector3 outScale = anim.framePoses[frame][boneId].scale;
|
||||
// Update all bones and boneMatrices of first mesh with bones.
|
||||
for (int boneId = 0; boneId < anim.boneCount; boneId++)
|
||||
{
|
||||
Vector3 inTranslation = model.bindPose[boneId].translation;
|
||||
Quaternion inRotation = model.bindPose[boneId].rotation;
|
||||
Vector3 inScale = model.bindPose[boneId].scale;
|
||||
|
||||
Vector3 invTranslation = Vector3RotateByQuaternion(Vector3Negate(inTranslation), QuaternionInvert(inRotation));
|
||||
Quaternion invRotation = QuaternionInvert(inRotation);
|
||||
Vector3 invScale = Vector3Divide((Vector3){ 1.0f, 1.0f, 1.0f }, inScale);
|
||||
Vector3 outTranslation = anim.framePoses[frame][boneId].translation;
|
||||
Quaternion outRotation = anim.framePoses[frame][boneId].rotation;
|
||||
Vector3 outScale = anim.framePoses[frame][boneId].scale;
|
||||
|
||||
Vector3 boneTranslation = Vector3Add(
|
||||
Vector3RotateByQuaternion(Vector3Multiply(outScale, invTranslation),
|
||||
outRotation), outTranslation);
|
||||
Quaternion boneRotation = QuaternionMultiply(outRotation, invRotation);
|
||||
Vector3 boneScale = Vector3Multiply(outScale, invScale);
|
||||
Quaternion invRotation = QuaternionInvert(inRotation);
|
||||
Vector3 invTranslation = Vector3RotateByQuaternion(Vector3Negate(inTranslation), invRotation);
|
||||
Vector3 invScale = Vector3Divide((Vector3){ 1.0f, 1.0f, 1.0f }, inScale);
|
||||
|
||||
Matrix boneMatrix = MatrixMultiply(MatrixMultiply(
|
||||
QuaternionToMatrix(boneRotation),
|
||||
MatrixTranslate(boneTranslation.x, boneTranslation.y, boneTranslation.z)),
|
||||
MatrixScale(boneScale.x, boneScale.y, boneScale.z));
|
||||
Vector3 boneTranslation = Vector3Add(Vector3RotateByQuaternion(
|
||||
Vector3Multiply(outScale, invTranslation), outRotation), outTranslation);
|
||||
Quaternion boneRotation = QuaternionMultiply(outRotation, invRotation);
|
||||
Vector3 boneScale = Vector3Multiply(outScale, invScale);
|
||||
|
||||
model.meshes[i].boneMatrices[boneId] = boneMatrix;
|
||||
Matrix boneMatrix = MatrixMultiply(MatrixMultiply(
|
||||
QuaternionToMatrix(boneRotation),
|
||||
MatrixTranslate(boneTranslation.x, boneTranslation.y, boneTranslation.z)),
|
||||
MatrixScale(boneScale.x, boneScale.y, boneScale.z));
|
||||
|
||||
model.meshes[firstMeshWithBones].boneMatrices[boneId] = boneMatrix;
|
||||
}
|
||||
|
||||
// Update remaining meshes with bones
|
||||
// NOTE: Using deep copy because shallow copy results in double free with 'UnloadModel()'
|
||||
if (firstMeshWithBones != -1)
|
||||
{
|
||||
for (int i = firstMeshWithBones + 1; i < model.meshCount; i++)
|
||||
{
|
||||
if (model.meshes[i].boneMatrices)
|
||||
{
|
||||
memcpy(model.meshes[i].boneMatrices,
|
||||
model.meshes[firstMeshWithBones].boneMatrices,
|
||||
model.meshes[i].boneCount*sizeof(model.meshes[i].boneMatrices[0]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// at least 2x speed up vs the old method
|
||||
// at least 2x speed up vs the old method
|
||||
// Update model animated vertex data (positions and normals) for a given frame
|
||||
// NOTE: Updated data is uploaded to GPU
|
||||
void UpdateModelAnimation(Model model, ModelAnimation anim, int frame)
|
||||
{
|
||||
UpdateModelAnimationBones(model,anim,frame);
|
||||
|
||||
for (int m = 0; m < model.meshCount; m++)
|
||||
{
|
||||
Mesh mesh = model.meshes[m];
|
||||
|
|
@ -2322,8 +2345,12 @@ void UpdateModelAnimation(Model model, ModelAnimation anim, int frame)
|
|||
int boneId = 0;
|
||||
int boneCounter = 0;
|
||||
float boneWeight = 0.0;
|
||||
bool updated = false; // Flag to check when anim vertex information is updated
|
||||
bool updated = false; // Flag to check when anim vertex information is updated
|
||||
const int vValues = mesh.vertexCount*3;
|
||||
|
||||
// Skip if missing bone data, causes segfault without on some models
|
||||
if ((mesh.boneWeights == NULL) || (mesh.boneIds == NULL)) continue;
|
||||
|
||||
for (int vCounter = 0; vCounter < vValues; vCounter += 3)
|
||||
{
|
||||
mesh.animVertices[vCounter] = 0;
|
||||
|
|
@ -2335,35 +2362,39 @@ void UpdateModelAnimation(Model model, ModelAnimation anim, int frame)
|
|||
mesh.animNormals[vCounter + 1] = 0;
|
||||
mesh.animNormals[vCounter + 2] = 0;
|
||||
}
|
||||
// Iterates over 4 bones per vertex
|
||||
|
||||
// Iterates over 4 bones per vertex
|
||||
for (int j = 0; j < 4; j++, boneCounter++)
|
||||
{
|
||||
boneWeight = mesh.boneWeights[boneCounter];
|
||||
boneId = mesh.boneIds[boneCounter];
|
||||
|
||||
// Early stop when no transformation will be applied
|
||||
if (boneWeight == 0.0f) continue;
|
||||
animVertex = (Vector3){ mesh.vertices[vCounter], mesh.vertices[vCounter + 1], mesh.vertices[vCounter + 2] };
|
||||
animVertex = Vector3Transform(animVertex,model.meshes[m].boneMatrices[boneId]);
|
||||
mesh.animVertices[vCounter] += animVertex.x * boneWeight;
|
||||
mesh.animVertices[vCounter+1] += animVertex.y * boneWeight;
|
||||
mesh.animVertices[vCounter+2] += animVertex.z * boneWeight;
|
||||
mesh.animVertices[vCounter] += animVertex.x*boneWeight;
|
||||
mesh.animVertices[vCounter+1] += animVertex.y*boneWeight;
|
||||
mesh.animVertices[vCounter+2] += animVertex.z*boneWeight;
|
||||
updated = true;
|
||||
|
||||
// Normals processing
|
||||
// NOTE: We use meshes.baseNormals (default normal) to calculate meshes.normals (animated normals)
|
||||
if (mesh.normals != NULL)
|
||||
if ((mesh.normals != NULL) && (mesh.animNormals != NULL ))
|
||||
{
|
||||
animNormal = (Vector3){ mesh.normals[vCounter], mesh.normals[vCounter + 1], mesh.normals[vCounter + 2] };
|
||||
animNormal = Vector3Transform(animNormal,model.meshes[m].boneMatrices[boneId]);
|
||||
animNormal = Vector3Transform(animNormal, MatrixTranspose(MatrixInvert(model.meshes[m].boneMatrices[boneId])));
|
||||
mesh.animNormals[vCounter] += animNormal.x*boneWeight;
|
||||
mesh.animNormals[vCounter + 1] += animNormal.y*boneWeight;
|
||||
mesh.animNormals[vCounter + 2] += animNormal.z*boneWeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (updated)
|
||||
{
|
||||
rlUpdateVertexBuffer(mesh.vboId[0], mesh.animVertices, mesh.vertexCount*3*sizeof(float), 0); // Update vertex position
|
||||
rlUpdateVertexBuffer(mesh.vboId[2], mesh.animNormals, mesh.vertexCount*3*sizeof(float), 0); // Update vertex normals
|
||||
if (mesh.normals != NULL) rlUpdateVertexBuffer(mesh.vboId[2], mesh.animNormals, mesh.vertexCount*3*sizeof(float), 0); // Update vertex normals
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2725,11 +2756,11 @@ Mesh GenMeshCube(float width, float height, float length)
|
|||
#else // Use par_shapes library to generate cube mesh
|
||||
/*
|
||||
// Platonic solids:
|
||||
par_shapes_mesh* par_shapes_create_tetrahedron(); // 4 sides polyhedron (pyramid)
|
||||
par_shapes_mesh* par_shapes_create_cube(); // 6 sides polyhedron (cube)
|
||||
par_shapes_mesh* par_shapes_create_octahedron(); // 8 sides polyhedron (diamond)
|
||||
par_shapes_mesh* par_shapes_create_dodecahedron(); // 12 sides polyhedron
|
||||
par_shapes_mesh* par_shapes_create_icosahedron(); // 20 sides polyhedron
|
||||
par_shapes_mesh *par_shapes_create_tetrahedron(); // 4 sides polyhedron (pyramid)
|
||||
par_shapes_mesh *par_shapes_create_cube(); // 6 sides polyhedron (cube)
|
||||
par_shapes_mesh *par_shapes_create_octahedron(); // 8 sides polyhedron (diamond)
|
||||
par_shapes_mesh *par_shapes_create_dodecahedron(); // 12 sides polyhedron
|
||||
par_shapes_mesh *par_shapes_create_icosahedron(); // 20 sides polyhedron
|
||||
*/
|
||||
// Platonic solid generation: cube (6 sides)
|
||||
// NOTE: No normals/texcoords generated by default
|
||||
|
|
@ -3840,7 +3871,7 @@ void DrawBillboardPro(Camera camera, Texture2D texture, Rectangle source, Vector
|
|||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
points[i] = Vector3Subtract(points[i], origin3D);
|
||||
if (rotation != 0.0) points[i] = Vector3RotateByAxisAngle(points[i], forward, rotation * DEG2RAD);
|
||||
if (rotation != 0.0) points[i] = Vector3RotateByAxisAngle(points[i], forward, rotation*DEG2RAD);
|
||||
points[i] = Vector3Add(points[i], position);
|
||||
}
|
||||
|
||||
|
|
@ -4049,7 +4080,7 @@ RayCollision GetRayCollisionMesh(Ray ray, Mesh mesh, Matrix transform)
|
|||
for (int i = 0; i < triangleCount; i++)
|
||||
{
|
||||
Vector3 a, b, c;
|
||||
Vector3* vertdata = (Vector3*)mesh.vertices;
|
||||
Vector3 *vertdata = (Vector3 *)mesh.vertices;
|
||||
|
||||
if (mesh.indices)
|
||||
{
|
||||
|
|
@ -4190,30 +4221,27 @@ static void BuildPoseFromParentJoints(BoneInfo *bones, int boneCount, Transform
|
|||
static Model LoadOBJ(const char *fileName)
|
||||
{
|
||||
tinyobj_attrib_t objAttributes = { 0 };
|
||||
tinyobj_shape_t* objShapes = NULL;
|
||||
tinyobj_shape_t *objShapes = NULL;
|
||||
unsigned int objShapeCount = 0;
|
||||
|
||||
tinyobj_material_t* objMaterials = NULL;
|
||||
tinyobj_material_t *objMaterials = NULL;
|
||||
unsigned int objMaterialCount = 0;
|
||||
|
||||
Model model = { 0 };
|
||||
model.transform = MatrixIdentity();
|
||||
|
||||
char* fileText = LoadFileText(fileName);
|
||||
char *fileText = LoadFileText(fileName);
|
||||
|
||||
if (fileText == NULL)
|
||||
{
|
||||
TRACELOG(LOG_ERROR, "MODEL Unable to read obj file %s", fileName);
|
||||
TRACELOG(LOG_ERROR, "MODEL: [%s] Unable to read obj file", fileName);
|
||||
return model;
|
||||
}
|
||||
|
||||
char currentDir[1024] = { 0 };
|
||||
strcpy(currentDir, GetWorkingDirectory()); // Save current working directory
|
||||
const char* workingDir = GetDirectoryPath(fileName); // Switch to OBJ directory for material path correctness
|
||||
if (CHDIR(workingDir) != 0)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to change working directory", workingDir);
|
||||
}
|
||||
const char *workingDir = GetDirectoryPath(fileName); // Switch to OBJ directory for material path correctness
|
||||
if (CHDIR(workingDir) != 0) TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to change working directory", workingDir);
|
||||
|
||||
unsigned int dataSize = (unsigned int)strlen(fileText);
|
||||
|
||||
|
|
@ -4222,7 +4250,7 @@ static Model LoadOBJ(const char *fileName)
|
|||
|
||||
if (ret != TINYOBJ_SUCCESS)
|
||||
{
|
||||
TRACELOG(LOG_ERROR, "MODEL Unable to read obj data %s", fileName);
|
||||
TRACELOG(LOG_ERROR, "MODEL: Unable to read obj data %s", fileName);
|
||||
return model;
|
||||
}
|
||||
|
||||
|
|
@ -4233,52 +4261,51 @@ static Model LoadOBJ(const char *fileName)
|
|||
int lastMaterial = -1;
|
||||
unsigned int meshIndex = 0;
|
||||
|
||||
// count meshes
|
||||
// Count meshes
|
||||
unsigned int nextShapeEnd = objAttributes.num_face_num_verts;
|
||||
|
||||
// see how many verts till the next shape
|
||||
|
||||
// See how many verts till the next shape
|
||||
if (objShapeCount > 1) nextShapeEnd = objShapes[nextShape].face_offset;
|
||||
|
||||
// walk all the faces
|
||||
// Walk all the faces
|
||||
for (unsigned int faceId = 0; faceId < objAttributes.num_faces; faceId++)
|
||||
{
|
||||
if (faceId >= nextShapeEnd)
|
||||
{
|
||||
// try to find the last vert in the next shape
|
||||
// Try to find the last vert in the next shape
|
||||
nextShape++;
|
||||
if (nextShape < objShapeCount) nextShapeEnd = objShapes[nextShape].face_offset;
|
||||
else nextShapeEnd = objAttributes.num_face_num_verts; // this is actually the total number of face verts in the file, not faces
|
||||
else nextShapeEnd = objAttributes.num_face_num_verts; // This is actually the total number of face verts in the file, not faces
|
||||
meshIndex++;
|
||||
}
|
||||
else if (lastMaterial != -1 && objAttributes.material_ids[faceId] != lastMaterial)
|
||||
else if ((lastMaterial != -1) && (objAttributes.material_ids[faceId] != lastMaterial))
|
||||
{
|
||||
meshIndex++;// if this is a new material, we need to allocate a new mesh
|
||||
meshIndex++; // If this is a new material, we need to allocate a new mesh
|
||||
}
|
||||
|
||||
lastMaterial = objAttributes.material_ids[faceId];
|
||||
faceVertIndex += objAttributes.face_num_verts[faceId];
|
||||
}
|
||||
|
||||
// allocate the base meshes and materials
|
||||
// Allocate the base meshes and materials
|
||||
model.meshCount = meshIndex + 1;
|
||||
model.meshes = (Mesh*)MemAlloc(sizeof(Mesh) * model.meshCount);
|
||||
model.meshes = (Mesh *)MemAlloc(sizeof(Mesh)*model.meshCount);
|
||||
|
||||
if (objMaterialCount > 0)
|
||||
{
|
||||
model.materialCount = objMaterialCount;
|
||||
model.materials = (Material*)MemAlloc(sizeof(Material) * objMaterialCount);
|
||||
model.materials = (Material *)MemAlloc(sizeof(Material)*objMaterialCount);
|
||||
}
|
||||
else // we must allocate at least one material
|
||||
else // We must allocate at least one material
|
||||
{
|
||||
model.materialCount = 1;
|
||||
model.materials = (Material*)MemAlloc(sizeof(Material) * 1);
|
||||
model.materials = (Material *)MemAlloc(sizeof(Material)*1);
|
||||
}
|
||||
|
||||
model.meshMaterial = (int*)MemAlloc(sizeof(int) * model.meshCount);
|
||||
model.meshMaterial = (int *)MemAlloc(sizeof(int)*model.meshCount);
|
||||
|
||||
// see how many verts are in each mesh
|
||||
unsigned int* localMeshVertexCounts = (unsigned int*)MemAlloc(sizeof(unsigned int) * model.meshCount);
|
||||
// See how many verts are in each mesh
|
||||
unsigned int *localMeshVertexCounts = (unsigned int *)MemAlloc(sizeof(unsigned int)*model.meshCount);
|
||||
|
||||
faceVertIndex = 0;
|
||||
nextShapeEnd = objAttributes.num_face_num_verts;
|
||||
|
|
@ -4287,23 +4314,22 @@ static Model LoadOBJ(const char *fileName)
|
|||
unsigned int localMeshVertexCount = 0;
|
||||
|
||||
nextShape = 1;
|
||||
if (objShapeCount > 1)
|
||||
nextShapeEnd = objShapes[nextShape].face_offset;
|
||||
if (objShapeCount > 1) nextShapeEnd = objShapes[nextShape].face_offset;
|
||||
|
||||
// walk all the faces
|
||||
// Walk all the faces
|
||||
for (unsigned int faceId = 0; faceId < objAttributes.num_faces; faceId++)
|
||||
{
|
||||
bool newMesh = false; // do we need a new mesh?
|
||||
bool newMesh = false; // Do we need a new mesh?
|
||||
if (faceId >= nextShapeEnd)
|
||||
{
|
||||
// try to find the last vert in the next shape
|
||||
// Try to find the last vert in the next shape
|
||||
nextShape++;
|
||||
if (nextShape < objShapeCount) nextShapeEnd = objShapes[nextShape].face_offset;
|
||||
else nextShapeEnd = objAttributes.num_face_num_verts; // this is actually the total number of face verts in the file, not faces
|
||||
|
||||
newMesh = true;
|
||||
}
|
||||
else if (lastMaterial != -1 && objAttributes.material_ids[faceId] != lastMaterial)
|
||||
else if ((lastMaterial != -1) && (objAttributes.material_ids[faceId] != lastMaterial))
|
||||
{
|
||||
newMesh = true;
|
||||
}
|
||||
|
|
@ -4321,50 +4347,52 @@ static Model LoadOBJ(const char *fileName)
|
|||
faceVertIndex += objAttributes.face_num_verts[faceId];
|
||||
localMeshVertexCount += objAttributes.face_num_verts[faceId];
|
||||
}
|
||||
|
||||
localMeshVertexCounts[meshIndex] = localMeshVertexCount;
|
||||
|
||||
for (int i = 0; i < model.meshCount; i++)
|
||||
{
|
||||
// allocate the buffers for each mesh
|
||||
// Allocate the buffers for each mesh
|
||||
unsigned int vertexCount = localMeshVertexCounts[i];
|
||||
|
||||
model.meshes[i].vertexCount = vertexCount;
|
||||
model.meshes[i].triangleCount = vertexCount / 3;
|
||||
model.meshes[i].triangleCount = vertexCount/3;
|
||||
|
||||
model.meshes[i].vertices = (float*)MemAlloc(sizeof(float) * vertexCount * 3);
|
||||
model.meshes[i].normals = (float*)MemAlloc(sizeof(float) * vertexCount * 3);
|
||||
model.meshes[i].texcoords = (float*)MemAlloc(sizeof(float) * vertexCount * 2);
|
||||
model.meshes[i].colors = (unsigned char*)MemAlloc(sizeof(unsigned char) * vertexCount * 4);
|
||||
model.meshes[i].vertices = (float *)MemAlloc(sizeof(float)*vertexCount*3);
|
||||
model.meshes[i].normals = (float *)MemAlloc(sizeof(float)*vertexCount*3);
|
||||
model.meshes[i].texcoords = (float *)MemAlloc(sizeof(float)*vertexCount*2);
|
||||
model.meshes[i].colors = (unsigned char *)MemAlloc(sizeof(unsigned char)*vertexCount*4);
|
||||
}
|
||||
|
||||
MemFree(localMeshVertexCounts);
|
||||
localMeshVertexCounts = NULL;
|
||||
|
||||
// fill meshes
|
||||
// Fill meshes
|
||||
faceVertIndex = 0;
|
||||
|
||||
nextShapeEnd = objAttributes.num_face_num_verts;
|
||||
|
||||
// see how many verts till the next shape
|
||||
// See how many verts till the next shape
|
||||
nextShape = 1;
|
||||
if (objShapeCount > 1) nextShapeEnd = objShapes[nextShape].face_offset;
|
||||
lastMaterial = -1;
|
||||
meshIndex = 0;
|
||||
localMeshVertexCount = 0;
|
||||
|
||||
// walk all the faces
|
||||
// Walk all the faces
|
||||
for (unsigned int faceId = 0; faceId < objAttributes.num_faces; faceId++)
|
||||
{
|
||||
bool newMesh = false; // do we need a new mesh?
|
||||
bool newMesh = false; // Do we need a new mesh?
|
||||
if (faceId >= nextShapeEnd)
|
||||
{
|
||||
// try to find the last vert in the next shape
|
||||
// Try to find the last vert in the next shape
|
||||
nextShape++;
|
||||
if (nextShape < objShapeCount) nextShapeEnd = objShapes[nextShape].face_offset;
|
||||
else nextShapeEnd = objAttributes.num_face_num_verts; // this is actually the total number of face verts in the file, not faces
|
||||
else nextShapeEnd = objAttributes.num_face_num_verts; // This is actually the total number of face verts in the file, not faces
|
||||
newMesh = true;
|
||||
}
|
||||
// if this is a new material, we need to allocate a new mesh
|
||||
|
||||
// If this is a new material, we need to allocate a new mesh
|
||||
if (lastMaterial != -1 && objAttributes.material_ids[faceId] != lastMaterial) newMesh = true;
|
||||
lastMaterial = objAttributes.material_ids[faceId];
|
||||
|
||||
|
|
@ -4375,8 +4403,7 @@ static Model LoadOBJ(const char *fileName)
|
|||
}
|
||||
|
||||
int matId = 0;
|
||||
if (lastMaterial >= 0 && lastMaterial < (int)objMaterialCount)
|
||||
matId = lastMaterial;
|
||||
if ((lastMaterial >= 0) && (lastMaterial < (int)objMaterialCount)) matId = lastMaterial;
|
||||
|
||||
model.meshMaterial[meshIndex] = matId;
|
||||
|
||||
|
|
@ -4386,19 +4413,15 @@ static Model LoadOBJ(const char *fileName)
|
|||
int normalIndex = objAttributes.faces[faceVertIndex].vn_idx;
|
||||
int texcordIndex = objAttributes.faces[faceVertIndex].vt_idx;
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
model.meshes[meshIndex].vertices[localMeshVertexCount * 3 + i] = objAttributes.vertices[vertIndex * 3 + i];
|
||||
for (int i = 0; i < 3; i++) model.meshes[meshIndex].vertices[localMeshVertexCount*3 + i] = objAttributes.vertices[vertIndex*3 + i];
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
model.meshes[meshIndex].normals[localMeshVertexCount * 3 + i] = objAttributes.normals[normalIndex * 3 + i];
|
||||
for (int i = 0; i < 3; i++) model.meshes[meshIndex].normals[localMeshVertexCount*3 + i] = objAttributes.normals[normalIndex*3 + i];
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
model.meshes[meshIndex].texcoords[localMeshVertexCount * 2 + i] = objAttributes.texcoords[texcordIndex * 2 + i];
|
||||
for (int i = 0; i < 2; i++) model.meshes[meshIndex].texcoords[localMeshVertexCount*2 + i] = objAttributes.texcoords[texcordIndex*2 + i];
|
||||
|
||||
model.meshes[meshIndex].texcoords[localMeshVertexCount * 2 + 1] = 1.0f - model.meshes[meshIndex].texcoords[localMeshVertexCount * 2 + 1];
|
||||
model.meshes[meshIndex].texcoords[localMeshVertexCount*2 + 1] = 1.0f - model.meshes[meshIndex].texcoords[localMeshVertexCount*2 + 1];
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
model.meshes[meshIndex].colors[localMeshVertexCount * 4 + i] = 255;
|
||||
for (int i = 0; i < 4; i++) model.meshes[meshIndex].colors[localMeshVertexCount*4 + i] = 255;
|
||||
|
||||
faceVertIndex++;
|
||||
localMeshVertexCount++;
|
||||
|
|
@ -4412,8 +4435,7 @@ static Model LoadOBJ(const char *fileName)
|
|||
tinyobj_shapes_free(objShapes, objShapeCount);
|
||||
tinyobj_materials_free(objMaterials, objMaterialCount);
|
||||
|
||||
for (int i = 0; i < model.meshCount; i++)
|
||||
UploadMesh(model.meshes + i, true);
|
||||
for (int i = 0; i < model.meshCount; i++) UploadMesh(model.meshes + i, true);
|
||||
|
||||
// Restore current working directory
|
||||
if (CHDIR(currentDir) != 0)
|
||||
|
|
@ -5069,6 +5091,8 @@ static Image LoadImageFromCgltfImage(cgltf_image *cgltfImage, const char *texPat
|
|||
{
|
||||
Image image = { 0 };
|
||||
|
||||
if (cgltfImage == NULL) return image;
|
||||
|
||||
if (cgltfImage->uri != NULL) // Check if image data is provided as an uri (base64 or path)
|
||||
{
|
||||
if ((strlen(cgltfImage->uri) > 5) &&
|
||||
|
|
@ -5110,7 +5134,7 @@ static Image LoadImageFromCgltfImage(cgltf_image *cgltfImage, const char *texPat
|
|||
image = LoadImage(TextFormat("%s/%s", texPath, cgltfImage->uri));
|
||||
}
|
||||
}
|
||||
else if (cgltfImage->buffer_view->buffer->data != NULL) // Check if image is provided as data buffer
|
||||
else if (cgltfImage->buffer_view != NULL && cgltfImage->buffer_view->buffer->data != NULL) // Check if image is provided as data buffer
|
||||
{
|
||||
unsigned char *data = RL_MALLOC(cgltfImage->buffer_view->size);
|
||||
int offset = (int)cgltfImage->buffer_view->offset;
|
||||
|
|
@ -5664,7 +5688,7 @@ static Model LoadGLTF(const char *fileName)
|
|||
}
|
||||
|
||||
// Load primitive indices data (if provided)
|
||||
if (mesh->primitives[p].indices != NULL)
|
||||
if ((mesh->primitives[p].indices != NULL) && (mesh->primitives[p].indices->buffer_view != NULL))
|
||||
{
|
||||
cgltf_accessor *attribute = mesh->primitives[p].indices;
|
||||
|
||||
|
|
@ -5681,7 +5705,7 @@ static Model LoadGLTF(const char *fileName)
|
|||
else if (attribute->component_type == cgltf_component_type_r_8u)
|
||||
{
|
||||
// Init raylib mesh indices to copy glTF attribute data
|
||||
model.meshes[meshIndex].indices = RL_MALLOC(attribute->count * sizeof(unsigned short));
|
||||
model.meshes[meshIndex].indices = RL_MALLOC(attribute->count*sizeof(unsigned short));
|
||||
LOAD_ATTRIBUTE_CAST(attribute, 1, unsigned char, model.meshes[meshIndex].indices, unsigned short)
|
||||
|
||||
}
|
||||
|
|
@ -5736,7 +5760,7 @@ static Model LoadGLTF(const char *fileName)
|
|||
|
||||
for (int i = 0; i < model.boneCount; i++)
|
||||
{
|
||||
cgltf_node* node = skin.joints[i];
|
||||
cgltf_node *node = skin.joints[i];
|
||||
cgltf_float worldTransform[16];
|
||||
cgltf_node_transform_world(node, worldTransform);
|
||||
Matrix worldMatrix = {
|
||||
|
|
|
|||
14
src/rtext.c
14
src/rtext.c
|
|
@ -247,7 +247,11 @@ extern void LoadFontDefault(void)
|
|||
// we must consider data as little-endian order (alpha + gray)
|
||||
((unsigned short *)imFont.data)[i + j] = 0xffff;
|
||||
}
|
||||
else ((unsigned short *)imFont.data)[i + j] = 0x00ff;
|
||||
else
|
||||
{
|
||||
((unsigned char *)imFont.data)[(i + j)*sizeof(short)] = 0xFF;
|
||||
((unsigned char *)imFont.data)[(i + j)*sizeof(short) + 1] = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
counter++;
|
||||
|
|
@ -1282,7 +1286,7 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
|
|||
{
|
||||
Vector2 textSize = { 0 };
|
||||
|
||||
if ((isGpuReady && (font.texture.id == 0)) ||
|
||||
if ((isGpuReady && (font.texture.id == 0)) ||
|
||||
(text == NULL) || (text[0] == '\0')) return textSize; // Security check
|
||||
|
||||
int size = TextLength(text); // Get size in bytes of text
|
||||
|
|
@ -2325,9 +2329,9 @@ static Font LoadBMFont(const char *fileName)
|
|||
// Convert hexadecimal to decimal (single digit)
|
||||
static unsigned char HexToInt(char hex)
|
||||
{
|
||||
if (hex >= '0' && hex <= '9') return hex - '0';
|
||||
else if (hex >= 'a' && hex <= 'f') return hex - 'a' + 10;
|
||||
else if (hex >= 'A' && hex <= 'F') return hex - 'A' + 10;
|
||||
if ((hex >= '0') && (hex <= '9')) return hex - '0';
|
||||
else if ((hex >= 'a') && (hex <= 'f')) return hex - 'a' + 10;
|
||||
else if ((hex >= 'A') && (hex <= 'F')) return hex - 'A' + 10;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -829,25 +829,22 @@ Image GenImageGradientLinear(int width, int height, int direction, Color start,
|
|||
|
||||
// Calculate how far the top-left pixel is along the gradient direction from the center of said gradient
|
||||
float startingPos = 0.5f - (cosDir*width/2) - (sinDir*height/2);
|
||||
// With directions that lie in the first or third quadrant (i.e. from top-left to
|
||||
// With directions that lie in the first or third quadrant (i.e. from top-left to
|
||||
// bottom-right or vice-versa), pixel (0, 0) is the farthest point on the gradient
|
||||
// (i.e. the pixel which should become one of the gradient's ends color); while for
|
||||
// directions that lie in the second or fourth quadrant, that point is pixel (width, 0).
|
||||
float maxPosValue =
|
||||
((signbit(sinDir) != 0) == (signbit(cosDir) != 0))
|
||||
? fabsf(startingPos)
|
||||
: fabsf(startingPos+width*cosDir);
|
||||
float maxPosValue = ((signbit(sinDir) != 0) == (signbit(cosDir) != 0))? fabsf(startingPos) : fabsf(startingPos + width*cosDir);
|
||||
for (int i = 0; i < width; i++)
|
||||
{
|
||||
for (int j = 0; j < height; j++)
|
||||
{
|
||||
// Calculate the relative position of the pixel along the gradient direction
|
||||
float pos = (startingPos + (i*cosDir + j*sinDir)) / maxPosValue;
|
||||
float pos = (startingPos + (i*cosDir + j*sinDir))/maxPosValue;
|
||||
|
||||
float factor = pos;
|
||||
factor = (factor > 1.0f)? 1.0f : factor; // Clamp to [-1,1]
|
||||
factor = (factor < -1.0f)? -1.0f : factor; // Clamp to [-1,1]
|
||||
factor = factor / 2 + 0.5f;
|
||||
factor = factor/2.0f + 0.5f;
|
||||
|
||||
// Generate the color for this pixel
|
||||
pixels[j*width + i].r = (int)((float)end.r*factor + (float)start.r*(1.0f - factor));
|
||||
|
|
@ -1007,7 +1004,8 @@ Image GenImagePerlinNoise(int width, int height, int offsetX, int offsetY, float
|
|||
{
|
||||
Color *pixels = (Color *)RL_MALLOC(width*height*sizeof(Color));
|
||||
|
||||
float aspectRatio = (float)width / (float)height;
|
||||
float aspectRatio = (float)width/(float)height;
|
||||
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
for (int x = 0; x < width; x++)
|
||||
|
|
@ -3567,7 +3565,7 @@ void ImageDrawLineEx(Image *dst, Vector2 start, Vector2 end, int thick, Color co
|
|||
ImageDrawLine(dst, x1, y1, x2, y2, color);
|
||||
|
||||
// Determine if the line is more horizontal or vertical
|
||||
if (dx != 0 && abs(dy/dx) < 1)
|
||||
if ((dx != 0) && (abs(dy/dx) < 1))
|
||||
{
|
||||
// Line is more horizontal
|
||||
// Calculate half the width of the line
|
||||
|
|
@ -4206,8 +4204,10 @@ TextureCubemap LoadTextureCubemap(Image image, int layout)
|
|||
ImageFormat(&faces, image.format);
|
||||
|
||||
Image mipmapped = ImageCopy(image);
|
||||
#if defined(SUPPORT_IMAGE_MANIPULATION)
|
||||
ImageMipmaps(&mipmapped);
|
||||
ImageMipmaps(&faces);
|
||||
#endif
|
||||
|
||||
// NOTE: Image formatting does not work with compressed textures
|
||||
|
||||
|
|
@ -5387,7 +5387,7 @@ static float HalfToFloat(unsigned short x)
|
|||
const unsigned int e = (x & 0x7C00) >> 10; // Exponent
|
||||
const unsigned int m = (x & 0x03FF) << 13; // Mantissa
|
||||
const float fm = (float)m;
|
||||
const unsigned int v = (*(unsigned int*)&fm) >> 23; // Evil log2 bit hack to count leading zeros in denormalized format
|
||||
const unsigned int v = (*(unsigned int *)&fm) >> 23; // Evil log2 bit hack to count leading zeros in denormalized format
|
||||
const unsigned int r = (x & 0x8000) << 16 | (e != 0)*((e + 112) << 23 | m) | ((e == 0)&(m != 0))*((v - 37) << 23 | ((m << (150 - v)) & 0x007FE000)); // sign : normalized : denormalized
|
||||
|
||||
result = *(float *)&r;
|
||||
|
|
@ -5400,7 +5400,7 @@ static unsigned short FloatToHalf(float x)
|
|||
{
|
||||
unsigned short result = 0;
|
||||
|
||||
const unsigned int b = (*(unsigned int*) & x) + 0x00001000; // Round-to-nearest-even: add last bit after truncated mantissa
|
||||
const unsigned int b = (*(unsigned int *) & x) + 0x00001000; // Round-to-nearest-even: add last bit after truncated mantissa
|
||||
const unsigned int e = (b & 0x7F800000) >> 23; // Exponent
|
||||
const unsigned int m = b & 0x007FFFFF; // Mantissa; in line below: 0x007FF000 = 0x00800000-0x00001000 = decimal indicator flag - initial rounding
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue