Code gardening

This commit is contained in:
Ray
2026-03-04 01:14:26 +01:00
parent 23c06bc6f1
commit faf42366ec
23 changed files with 213 additions and 223 deletions

View File

@ -126,7 +126,7 @@
// rcore: Configuration values // rcore: Configuration values
// NOTE: Below values are alread defined inside [rcore.c] so there is no need to be // NOTE: Below values are alread defined inside [rcore.c] so there is no need to be
// redefined here, in case it must be done, just uncomment the required line and update // redefined here, in case it must be done, uncomment the required line and update
// the value; it can also be done on compilation with -DVALUE_TO_REDEFINE=128 // the value; it can also be done on compilation with -DVALUE_TO_REDEFINE=128
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
//#define MAX_TRACELOG_MSG_LENGTH 256 // Max length of one trace-log message //#define MAX_TRACELOG_MSG_LENGTH 256 // Max length of one trace-log message
@ -160,7 +160,7 @@
// rlgl: Configuration values // rlgl: Configuration values
// NOTE: Below values are alread defined inside [rlgl.h] so there is no need to be // NOTE: Below values are alread defined inside [rlgl.h] so there is no need to be
// redefined here, in case it must be done, just uncomment the required line and update // redefined here, in case it must be done, uncomment the required line and update
// the value; it can also be done on compilation with -DVALUE_TO_REDEFINE=128 // the value; it can also be done on compilation with -DVALUE_TO_REDEFINE=128
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
//#define RL_DEFAULT_BATCH_BUFFER_ELEMENTS 4096 // Default internal render batch elements limits //#define RL_DEFAULT_BATCH_BUFFER_ELEMENTS 4096 // Default internal render batch elements limits
@ -350,7 +350,7 @@
// raudio: Configuration values // raudio: Configuration values
// NOTE: Below values are alread defined inside [rlgl.h] so there is no need to be // NOTE: Below values are alread defined inside [rlgl.h] so there is no need to be
// redefined here, in case it must be done, just uncomment the required line and update // redefined here, in case it must be done, uncomment the required line and update
// the value; it can also be done on compilation with -DVALUE_TO_REDEFINE=128 // the value; it can also be done on compilation with -DVALUE_TO_REDEFINE=128
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
//#define AUDIO_DEVICE_FORMAT ma_format_f32 // Device output format (miniaudio: float-32bit) //#define AUDIO_DEVICE_FORMAT ma_format_f32 // Device output format (miniaudio: float-32bit)

2
src/external/rlsw.h vendored
View File

@ -48,7 +48,7 @@
* recommended under specific situations and only if the developers know * recommended under specific situations and only if the developers know
* what are they doing; this flag is not defined by default * what are they doing; this flag is not defined by default
* *
* rlsw capabilities could be customized just defining some internal * rlsw capabilities could be customized defining some internal
* values before library inclusion (default values listed): * values before library inclusion (default values listed):
* *
* #define SW_GL_FRAMEBUFFER_COPY_BGRA true * #define SW_GL_FRAMEBUFFER_COPY_BGRA true

View File

@ -14,7 +14,7 @@ unsigned char *Win32GetClipboardImageData(int *width, int *height, unsigned long
#include <assert.h> #include <assert.h>
// NOTE: These search for architecture is taken from "windows.h", and it's necessary to avoid including windows.h // NOTE: These search for architecture is taken from "windows.h", and it's necessary to avoid including windows.h
// and still make it compile on msvc, because import indirectly importing "winnt.h" (e.g. <minwindef.h>) can cause problems is these are not defined. // and still make it compile on msvc, because import indirectly importing "winnt.h" (e.g. <minwindef.h>) can cause problems is these are not defined
#if !defined(_X86_) && !defined(_68K_) && !defined(_MPPC_) && !defined(_IA64_) && !defined(_AMD64_) && !defined(_ARM_) && !defined(_ARM64_) && !defined(_ARM64EC_) && defined(_M_IX86) #if !defined(_X86_) && !defined(_68K_) && !defined(_MPPC_) && !defined(_IA64_) && !defined(_AMD64_) && !defined(_ARM_) && !defined(_ARM64_) && !defined(_ARM64EC_) && defined(_M_IX86)
#define _X86_ #define _X86_
#if !defined(_CHPE_X86_ARM64_) && defined(_M_HYBRID) #if !defined(_CHPE_X86_ARM64_) && defined(_M_HYBRID)

View File

@ -715,7 +715,7 @@ void PollInputEvents(void)
{ {
#if SUPPORT_GESTURES_SYSTEM #if SUPPORT_GESTURES_SYSTEM
// NOTE: Gestures update must be called every frame to reset gestures correctly // NOTE: Gestures update must be called every frame to reset gestures correctly
// because ProcessGestureEvent() is just called on an event, not every frame // because ProcessGestureEvent() is called on an event, not every frame
UpdateGestures(); UpdateGestures();
#endif #endif
@ -1055,7 +1055,7 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
InitGraphicsDevice(); InitGraphicsDevice();
// Initialize OpenGL context (states and resources) // Initialize OpenGL context (states and resources)
// NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl // NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, stored as globals in rlgl
rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height); rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
// Setup default viewport // Setup default viewport
@ -1299,7 +1299,7 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
} }
else if ((keycode == AKEYCODE_BACK) || (keycode == AKEYCODE_MENU)) else if ((keycode == AKEYCODE_BACK) || (keycode == AKEYCODE_MENU))
{ {
// Eat BACK_BUTTON and AKEYCODE_MENU, just do nothing... and don't let to be handled by OS! // Eat BACK_BUTTON and AKEYCODE_MENU, do nothing... and don't let to be handled by OS!
return 1; return 1;
} }
else if ((keycode == AKEYCODE_VOLUME_UP) || (keycode == AKEYCODE_VOLUME_DOWN)) else if ((keycode == AKEYCODE_VOLUME_UP) || (keycode == AKEYCODE_VOLUME_DOWN))
@ -1547,7 +1547,7 @@ FILE *__wrap_fopen(const char *fileName, const char *mode)
} }
else else
{ {
// Just do a regular open if file is not found in the assets // Do a regular open if file is not found in the assets
file = __real_fopen(TextFormat("%s/%s", platform.app->activity->internalDataPath, fileName), mode); file = __real_fopen(TextFormat("%s/%s", platform.app->activity->internalDataPath, fileName), mode);
if (file == NULL) file = __real_fopen(fileName, mode); if (file == NULL) file = __real_fopen(fileName, mode);
} }

View File

@ -837,7 +837,7 @@ int GetCurrentMonitor(void)
{ {
// In case the window is between two monitors, below logic is used // In case the window is between two monitors, below logic is used
// to try to detect the "current monitor" for that window, note that // to try to detect the "current monitor" for that window, note that
// this is probably an overengineered solution for a very side case // this is probably an overengineered solution for a side case
// trying to match SDL behaviour // trying to match SDL behaviour
int closestDist = 0x7FFFFFFF; int closestDist = 0x7FFFFFFF;
@ -1258,7 +1258,7 @@ void PollInputEvents(void)
{ {
#if SUPPORT_GESTURES_SYSTEM #if SUPPORT_GESTURES_SYSTEM
// NOTE: Gestures update must be called every frame to reset gestures correctly // NOTE: Gestures update must be called every frame to reset gestures correctly
// because ProcessGestureEvent() is just called on an event, not every frame // because ProcessGestureEvent() is called on an event, not every frame
UpdateGestures(); UpdateGestures();
#endif #endif
@ -1588,7 +1588,7 @@ int InitPlatform(void)
} }
// NOTE: GLFW 3.4+ defers initialization of the Joystick subsystem on the first call to any Joystick related functions // NOTE: GLFW 3.4+ defers initialization of the Joystick subsystem on the first call to any Joystick related functions
// Forcing this initialization here avoids doing it on PollInputEvents() called by EndDrawing() after first frame has been just drawn // Forcing this initialization here avoids doing it on PollInputEvents() called by EndDrawing() after first frame has been drawn
// The initialization will still happen and possible delays still occur, but before the window is shown, which is a nicer experience // The initialization will still happen and possible delays still occur, but before the window is shown, which is a nicer experience
// REF: https://github.com/raysan5/raylib/issues/1554 // REF: https://github.com/raysan5/raylib/issues/1554
glfwSetJoystickCallback(NULL); glfwSetJoystickCallback(NULL);

View File

@ -1198,7 +1198,7 @@ void PollInputEvents(void)
{ {
#if SUPPORT_GESTURES_SYSTEM #if SUPPORT_GESTURES_SYSTEM
// NOTE: Gestures update must be called every frame to reset gestures correctly // NOTE: Gestures update must be called every frame to reset gestures correctly
// because ProcessGestureEvent() is just called on an event, not every frame // because ProcessGestureEvent() is called on an event, not every frame
UpdateGestures(); UpdateGestures();
#endif #endif

View File

@ -49,7 +49,7 @@
#define USING_SDL3_PROJECT #define USING_SDL3_PROJECT
#endif #endif
#ifndef SDL_ENABLE_OLD_NAMES #ifndef SDL_ENABLE_OLD_NAMES
#define SDL_ENABLE_OLD_NAMES // Just in case on SDL3, some in-between compatibily is needed #define SDL_ENABLE_OLD_NAMES // In case on SDL3, some in-between compatibily is needed
#endif #endif
// SDL base library (window/rendered, input, timing... functionality) // SDL base library (window/rendered, input, timing... functionality)
#ifdef USING_SDL3_PROJECT #ifdef USING_SDL3_PROJECT
@ -1365,7 +1365,7 @@ void PollInputEvents(void)
{ {
#if SUPPORT_GESTURES_SYSTEM #if SUPPORT_GESTURES_SYSTEM
// NOTE: Gestures update must be called every frame to reset gestures correctly // NOTE: Gestures update must be called every frame to reset gestures correctly
// because ProcessGestureEvent() is just called on an event, not every frame // because ProcessGestureEvent() is called on an event, not every frame
UpdateGestures(); UpdateGestures();
#endif #endif
@ -1482,7 +1482,7 @@ void PollInputEvents(void)
#ifndef USING_VERSION_SDL3 #ifndef USING_VERSION_SDL3
// The SDL_WINDOWEVENT_* events have been moved to top level events, and SDL_WINDOWEVENT has been removed // The SDL_WINDOWEVENT_* events have been moved to top level events, and SDL_WINDOWEVENT has been removed
// In general, handling this change just means checking for the individual events instead of first checking for SDL_WINDOWEVENT // In general, handling this change means checking for the individual events instead of first checking for SDL_WINDOWEVENT
// and then checking for window events; Events >= SDL_EVENT_WINDOW_FIRST and <= SDL_EVENT_WINDOW_LAST can be compared // and then checking for window events; Events >= SDL_EVENT_WINDOW_FIRST and <= SDL_EVENT_WINDOW_LAST can be compared
// to see whether it's a window event // to see whether it's a window event
case SDL_WINDOWEVENT: case SDL_WINDOWEVENT:

View File

@ -2198,7 +2198,7 @@ static unsigned SanitizeFlags(int mode, unsigned flags)
// retry loop that continues until either the desired state is reached or the state stops changing // retry loop that continues until either the desired state is reached or the state stops changing
static void UpdateFlags(HWND hwnd, unsigned desiredFlags, int width, int height) static void UpdateFlags(HWND hwnd, unsigned desiredFlags, int width, int height)
{ {
// Flags that just apply immediately without needing any operations // Flags that apply immediately without needing any operations
CORE.Window.flags |= (desiredFlags & FLAG_MASK_NO_UPDATE); CORE.Window.flags |= (desiredFlags & FLAG_MASK_NO_UPDATE);
int vsync = (desiredFlags & FLAG_VSYNC_HINT)? 1 : 0; int vsync = (desiredFlags & FLAG_VSYNC_HINT)? 1 : 0;

View File

@ -183,14 +183,14 @@ static const int evkeyToUnicodeLUT[] = {
0, 27, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 45, 61, 8, 0, 113, 119, 101, 114, 0, 27, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 45, 61, 8, 0, 113, 119, 101, 114,
116, 121, 117, 105, 111, 112, 0, 0, 13, 0, 97, 115, 100, 102, 103, 104, 106, 107, 108, 59, 116, 121, 117, 105, 111, 112, 0, 0, 13, 0, 97, 115, 100, 102, 103, 104, 106, 107, 108, 59,
39, 96, 0, 92, 122, 120, 99, 118, 98, 110, 109, 44, 46, 47, 0, 0, 0, 32 39, 96, 0, 92, 122, 120, 99, 118, 98, 110, 109, 44, 46, 47, 0, 0, 0, 32
// LUT currently incomplete, just mapped the most essential keys // LUT currently incomplete, only mapped the most essential keys
}; };
// This is the map used to map any keycode returned from linux to a raylib code from 'raylib.h' // This is the map used to map any keycode returned from linux to a raylib code from 'raylib.h'
// NOTE: Use short here to save a little memory // NOTE: Use short here to save a little memory
static const short linuxToRaylibMap[KEYMAP_SIZE] = { static const short linuxToRaylibMap[KEYMAP_SIZE] = {
// We don't map those with designated initialization, because we would getting // Don't map with designated initialization,
// into loads of naming conflicts // it will geenrate many naming conflicts
0, 256, 49, 50, 51, 52, 53, 54, 0, 256, 49, 50, 51, 52, 53, 54,
55, 56, 57, 48, 45, 61, 259, 258, 55, 56, 57, 48, 45, 61, 259, 258,
81, 87, 69, 82, 84, 89, 85, 73, 81, 87, 69, 82, 84, 89, 85, 73,
@ -764,9 +764,9 @@ void SwapScreenBuffer()
// Attempt page flip // Attempt page flip
// NOTE: rmModePageFlip() schedules a buffer-flip for the next vblank and then notifies us about it // NOTE: rmModePageFlip() schedules a buffer-flip for the next vblank and then notifies us about it
// It takes a CRTC-id, fb-id and an arbitrary data-pointer and then schedules the page-flip // It takes a CRTC-id, fb-id and an arbitrary data-pointer and then schedules the page-flip
// This is fully asynchronous and when the page-flip happens, the DRM-fd will become readable and we can call drmHandleEvent() // This is fully asynchronous and when the page-flip happens, the DRM-fd will become readable and drmHandleEvent() can be called
// This will read all vblank/page-flip events and call our modeset_page_flip_event() callback with the data-pointer that we passed to drmModePageFlip() // This will read all vblank/page-flip events and call our modeset_page_flip_event() callback with the data-pointer passed to drmModePageFlip()
// We simply call modeset_draw_dev() then so the next frame is rendered... returns immediately // Simply call modeset_draw_dev() then so the next frame is rendered... returns immediately
if (drmModePageFlip(platform.fd, platform.crtc->crtc_id, fbId, DRM_MODE_PAGE_FLIP_EVENT, platform.prevBO)) if (drmModePageFlip(platform.fd, platform.crtc->crtc_id, fbId, DRM_MODE_PAGE_FLIP_EVENT, platform.prevBO))
{ {
if (errno == EBUSY) errCnt[3]++; // Display busy - skip flip if (errno == EBUSY) errCnt[3]++; // Display busy - skip flip
@ -1067,7 +1067,7 @@ void PollInputEvents(void)
{ {
#if SUPPORT_GESTURES_SYSTEM #if SUPPORT_GESTURES_SYSTEM
// NOTE: Gestures update must be called every frame to reset gestures correctly // NOTE: Gestures update must be called every frame to reset gestures correctly
// because ProcessGestureEvent() is just called on an event, not every frame // because ProcessGestureEvent() is called on an event, not every frame
UpdateGestures(); UpdateGestures();
#endif #endif
@ -1089,7 +1089,7 @@ void PollInputEvents(void)
PollKeyboardEvents(); PollKeyboardEvents();
#if SUPPORT_SSH_KEYBOARD_RPI #if SUPPORT_SSH_KEYBOARD_RPI
// NOTE: Keyboard reading could be done using input_event(s) or just read from stdin, both methods are used here // NOTE: Keyboard reading could be done using input_event(s) or read from stdin, both methods are used here
// stdin reading is still used for legacy purposes, it allows keyboard input trough SSH console // stdin reading is still used for legacy purposes, it allows keyboard input trough SSH console
if (!platform.eventKeyboardMode) ProcessKeyboard(); if (!platform.eventKeyboardMode) ProcessKeyboard();
#endif #endif
@ -1225,7 +1225,7 @@ int InitPlatform(void)
if (((con->connection == DRM_MODE_CONNECTED) || (con->connection == DRM_MODE_UNKNOWNCONNECTION)) && (con->count_modes > 0)) if (((con->connection == DRM_MODE_CONNECTED) || (con->connection == DRM_MODE_UNKNOWNCONNECTION)) && (con->count_modes > 0))
{ {
#if !defined(GRAPHICS_API_OPENGL_11_SOFTWARE) #if !defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
// For hardware rendering, we need an encoder_id // For hardware rendering, an encoder_id is needed
if (con->encoder_id) if (con->encoder_id)
{ {
TRACELOG(LOG_TRACE, "DISPLAY: DRM connector %i connected with encoder", i); TRACELOG(LOG_TRACE, "DISPLAY: DRM connector %i connected with encoder", i);
@ -1234,7 +1234,7 @@ int InitPlatform(void)
} }
else TRACELOG(LOG_TRACE, "DISPLAY: DRM connector %i connected but no encoder", i); else TRACELOG(LOG_TRACE, "DISPLAY: DRM connector %i connected but no encoder", i);
#else #else
// For software rendering, we can accept even without encoder_id // For software rendering, accept even without encoder_id
TRACELOG(LOG_TRACE, "DISPLAY: DRM connector %i suitable for software rendering", i); TRACELOG(LOG_TRACE, "DISPLAY: DRM connector %i suitable for software rendering", i);
platform.connector = con; platform.connector = con;
break; break;
@ -1534,7 +1534,7 @@ int InitPlatform(void)
return -1; return -1;
} }
// At this point we need to manage render size vs screen size // At this point, manage render size vs screen size
// NOTE: This function use and modify global module variables: // NOTE: This function use and modify global module variables:
// -> CORE.Window.screen.width/CORE.Window.screen.height // -> CORE.Window.screen.width/CORE.Window.screen.height
// -> CORE.Window.render.width/CORE.Window.render.height // -> CORE.Window.render.width/CORE.Window.render.height
@ -1572,7 +1572,7 @@ int InitPlatform(void)
// NOTE: GL procedures address loader is required to load extensions // NOTE: GL procedures address loader is required to load extensions
rlLoadExtensions(eglGetProcAddress); rlLoadExtensions(eglGetProcAddress);
#else #else
// At this point we need to manage render size vs screen size // At this point, manage render size vs screen size
// NOTE: This function use and modify global module variables: // NOTE: This function use and modify global module variables:
// -> CORE.Window.screen.width/CORE.Window.screen.height // -> CORE.Window.screen.width/CORE.Window.screen.height
// -> CORE.Window.render.width/CORE.Window.render.height // -> CORE.Window.render.width/CORE.Window.render.height
@ -1596,7 +1596,7 @@ int InitPlatform(void)
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_MINIMIZED)) MinimizeWindow(); if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_MINIMIZED)) MinimizeWindow();
// If graphic device is no properly initialized, we end program // If graphic device is no properly initialized, end program
if (!CORE.Window.ready) if (!CORE.Window.ready)
{ {
TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize graphic device"); TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize graphic device");
@ -1745,7 +1745,7 @@ void ClosePlatform(void)
// Initialize Keyboard system (using standard input) // Initialize Keyboard system (using standard input)
static void InitKeyboard(void) static void InitKeyboard(void)
{ {
// NOTE: We read directly from Standard Input (stdin) - STDIN_FILENO file descriptor, // NOTE: Read directly from Standard Input (stdin) - STDIN_FILENO file descriptor,
// Reading directly from stdin will give chars already key-mapped by kernel to ASCII or UNICODE // Reading directly from stdin will give chars already key-mapped by kernel to ASCII or UNICODE
// Save terminal keyboard settings // Save terminal keyboard settings
@ -1978,8 +1978,8 @@ static void ConfigureEvdevDevice(char *device)
return; return;
} }
// At this point we have a connection to the device, but we don't yet know what the device is // At this point, a connection to the device has been stablished, but still left to know what the device is,
// It could be many things, even as simple as a power button... // it could be many things, even as simple as a power button...
//------------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------------
// Identify the device // Identify the device
@ -1990,8 +1990,8 @@ static void ConfigureEvdevDevice(char *device)
} absinfo[ABS_CNT] = { 0 }; } absinfo[ABS_CNT] = { 0 };
// These flags aren't really a one of // These flags aren't really a one of
// Some devices could have properties we assosciate with keyboards as well as properties // Some devices could have properties associated with keyboards
// we assosciate with mice // as well as properties associated with mice
bool isKeyboard = false; bool isKeyboard = false;
bool isMouse = false; bool isMouse = false;
bool isTouch = false; bool isTouch = false;
@ -2027,11 +2027,10 @@ static void ConfigureEvdevDevice(char *device)
TEST_BIT(keyBits, BTN_TOOL_FINGER) || TEST_BIT(keyBits, BTN_TOOL_FINGER) ||
TEST_BIT(keyBits, BTN_TOUCH))) isTouch = true; TEST_BIT(keyBits, BTN_TOUCH))) isTouch = true;
// Absolute mice should really only exist with VMWare, but it shouldn't // Absolute mice should really only exist with VMWare
// matter if we support them
else if (hasAbsXY && TEST_BIT(keyBits, BTN_MOUSE)) isMouse = true; else if (hasAbsXY && TEST_BIT(keyBits, BTN_MOUSE)) isMouse = true;
// If any of the common joystick axes are present, we assume it's a gamepad // If any of the common joystick axes are present, assume it's a gamepad
else else
{ {
for (int axis = (hasAbsXY? ABS_Z : ABS_X); axis < ABS_PRESSURE; axis++) for (int axis = (hasAbsXY? ABS_Z : ABS_X); axis < ABS_PRESSURE; axis++)
@ -2056,7 +2055,7 @@ static void ConfigureEvdevDevice(char *device)
{ {
ioctl(fd, EVIOCGBIT(EV_REL, sizeof(relBits)), relBits); ioctl(fd, EVIOCGBIT(EV_REL, sizeof(relBits)), relBits);
// If it has any of the gamepad or touch features we tested so far, it's not a mouse // If it has any of the gamepad or touch features tested so far, it's not a mouse
if (!isTouch && if (!isTouch &&
!isGamepad && !isGamepad &&
TEST_BIT(relBits, REL_X) && TEST_BIT(relBits, REL_X) &&
@ -2067,12 +2066,12 @@ static void ConfigureEvdevDevice(char *device)
if (TEST_BIT(evBits, EV_KEY)) if (TEST_BIT(evBits, EV_KEY))
{ {
// The first 32 keys as defined in input-event-codes.h are pretty much // The first 32 keys as defined in input-event-codes.h are pretty much
// exclusive to keyboards, so we can test them using a mask // exclusive to keyboards, so they can be tested using a mask
// Leave out the first bit to not test KEY_RESERVED // Leave out the first bit to not test KEY_RESERVED
const unsigned long mask = 0xFFFFFFFE; const unsigned long mask = 0xFFFFFFFE;
if ((keyBits[0] & mask) == mask) isKeyboard = true; if ((keyBits[0] & mask) == mask) isKeyboard = true;
// If we find any of the common gamepad buttons we assume it's a gamepad // If any of the common gamepad buttons is found, assume it's a gamepad
else else
{ {
for (int button = BTN_JOYSTICK; button < BTN_DIGI; ++button) for (int button = BTN_JOYSTICK; button < BTN_DIGI; ++button)
@ -2149,7 +2148,7 @@ static void ConfigureEvdevDevice(char *device)
if (absAxisCount > 0) if (absAxisCount > 0)
{ {
// TODO: Review GamepadAxis enum matching // TODO: Review GamepadAxis enum matching
// So gamepad axes (as in the actual linux joydev.c) are just simply enumerated // So gamepad axes (as in the actual linux joydev.c) are simply enumerated
// and (at least for some input drivers like xpat) it's convention to use // and (at least for some input drivers like xpat) it's convention to use
// ABS_X, ABX_Y for one joystick ABS_RX, ABS_RY for the other and the Z axes for the shoulder buttons // ABS_X, ABX_Y for one joystick ABS_RX, ABS_RY for the other and the Z axes for the shoulder buttons
// If these are now enumerated, it results to LJOY_X, LJOY_Y, LEFT_SHOULDERB, RJOY_X, ... // If these are now enumerated, it results to LJOY_X, LJOY_Y, LEFT_SHOULDERB, RJOY_X, ...
@ -2197,7 +2196,7 @@ static void PollKeyboardEvents(void)
if (event.type != EV_KEY) continue; if (event.type != EV_KEY) continue;
#if SUPPORT_SSH_KEYBOARD_RPI #if SUPPORT_SSH_KEYBOARD_RPI
// If the event was a key, we know a working keyboard is connected, so disable the SSH keyboard // If the event was a key, assume a working keyboard is connected, so disable the SSH keyboard
platform.eventKeyboardMode = true; platform.eventKeyboardMode = true;
#endif #endif
// Keyboard keys appear for codes 1 to 255, ignore everthing else // Keyboard keys appear for codes 1 to 255, ignore everthing else
@ -2206,7 +2205,7 @@ static void PollKeyboardEvents(void)
// Lookup the scancode in the keymap to get a keycode // Lookup the scancode in the keymap to get a keycode
keycode = linuxToRaylibMap[event.code]; keycode = linuxToRaylibMap[event.code];
// Make sure we got a valid keycode // Make sure a valid keycode is obtained
if ((keycode > 0) && (keycode < MAX_KEYBOARD_KEYS)) if ((keycode > 0) && (keycode < MAX_KEYBOARD_KEYS))
{ {
// WARNING: https://www.kernel.org/doc/Documentation/input/input.txt // WARNING: https://www.kernel.org/doc/Documentation/input/input.txt
@ -2380,8 +2379,8 @@ static void PollMouseEvents(void)
{ {
platform.touchPosition[platform.touchSlot].x = (event.value - platform.absRange.x)*CORE.Window.screen.width/platform.absRange.width; platform.touchPosition[platform.touchSlot].x = (event.value - platform.absRange.x)*CORE.Window.screen.width/platform.absRange.width;
// If this slot is active, it's a move. If not, we are just updating the buffer for when it becomes active. // If this slot is active, it's a move; If not, update the buffer for when it becomes active
// Only set to MOVE if we haven't already detected a DOWN or UP event this frame // Only set to MOVE if a DOWN or UP event has not been detected this frame
if (platform.touchActive[platform.touchSlot] && touchAction == -1) touchAction = 2; // TOUCH_ACTION_MOVE if (platform.touchActive[platform.touchSlot] && touchAction == -1) touchAction = 2; // TOUCH_ACTION_MOVE
} }
} }
@ -2392,8 +2391,8 @@ static void PollMouseEvents(void)
{ {
platform.touchPosition[platform.touchSlot].y = (event.value - platform.absRange.y)*CORE.Window.screen.height/platform.absRange.height; platform.touchPosition[platform.touchSlot].y = (event.value - platform.absRange.y)*CORE.Window.screen.height/platform.absRange.height;
// If this slot is active, it's a move. If not, we are just updating the buffer for when it becomes active. // If this slot is active, it's a move; If not, update the buffer for when it becomes active
// Only set to MOVE if we haven't already detected a DOWN or UP event this frame // Only set to MOVE if a DOWN or UP event have not been detected this frame
if (platform.touchActive[platform.touchSlot] && touchAction == -1) touchAction = 2; // TOUCH_ACTION_MOVE if (platform.touchActive[platform.touchSlot] && touchAction == -1) touchAction = 2; // TOUCH_ACTION_MOVE
} }
} }
@ -2418,7 +2417,7 @@ static void PollMouseEvents(void)
platform.touchPosition[platform.touchSlot].y = -1; platform.touchPosition[platform.touchSlot].y = -1;
platform.touchId[platform.touchSlot] = -1; platform.touchId[platform.touchSlot] = -1;
// Force UP action if we haven't already set a DOWN action // Force UP action if DOWN action has not already been set
// (DOWN takes priority over UP if both happen in one frame, though rare) // (DOWN takes priority over UP if both happen in one frame, though rare)
if (touchAction != 1) touchAction = 0; // TOUCH_ACTION_UP if (touchAction != 1) touchAction = 0; // TOUCH_ACTION_UP
} }
@ -2665,7 +2664,7 @@ static int FindNearestConnectorMode(const drmModeConnector *connector, uint widt
// NOTE: Global variables CORE.Window.render.width/CORE.Window.render.height and CORE.Window.renderOffset.x/CORE.Window.renderOffset.y can be modified // NOTE: Global variables CORE.Window.render.width/CORE.Window.render.height and CORE.Window.renderOffset.x/CORE.Window.renderOffset.y can be modified
static void SetupFramebuffer(int width, int height) static void SetupFramebuffer(int width, int height)
{ {
// Calculate CORE.Window.render.width and CORE.Window.render.height, we have the display size (input params) and the desired screen size (global var) // Calculate CORE.Window.render.width and CORE.Window.render.height, using the display size (input params) and the desired screen size (global var)
if ((CORE.Window.screen.width > CORE.Window.display.width) || (CORE.Window.screen.height > CORE.Window.display.height)) if ((CORE.Window.screen.width > CORE.Window.display.width) || (CORE.Window.screen.height > CORE.Window.display.height))
{ {
TRACELOG(LOG_WARNING, "DISPLAY: Downscaling required: Screen size (%ix%i) is bigger than display size (%ix%i)", CORE.Window.screen.width, CORE.Window.screen.height, CORE.Window.display.width, CORE.Window.display.height); TRACELOG(LOG_WARNING, "DISPLAY: Downscaling required: Screen size (%ix%i) is bigger than display size (%ix%i)", CORE.Window.screen.width, CORE.Window.screen.height, CORE.Window.display.width, CORE.Window.display.height);
@ -2693,8 +2692,8 @@ static void SetupFramebuffer(int width, int height)
float scaleRatio = (float)CORE.Window.render.width/(float)CORE.Window.screen.width; float scaleRatio = (float)CORE.Window.render.width/(float)CORE.Window.screen.width;
CORE.Window.screenScale = MatrixScale(scaleRatio, scaleRatio, 1.0f); CORE.Window.screenScale = MatrixScale(scaleRatio, scaleRatio, 1.0f);
// NOTE: We render to full display resolution! // NOTE: Rendering to full display resolution,
// We just need to calculate above parameters for downscale matrix and offsets // calculate above parameters for downscale matrix and offsets
CORE.Window.render.width = CORE.Window.display.width; CORE.Window.render.width = CORE.Window.display.width;
CORE.Window.render.height = CORE.Window.display.height; CORE.Window.render.height = CORE.Window.display.height;

View File

@ -437,7 +437,7 @@ void PollInputEvents(void)
{ {
#if SUPPORT_GESTURES_SYSTEM #if SUPPORT_GESTURES_SYSTEM
// NOTE: Gestures update must be called every frame to reset gestures correctly // NOTE: Gestures update must be called every frame to reset gestures correctly
// because ProcessGestureEvent() is just called on an event, not every frame // because ProcessGestureEvent() is called on an event, not every frame
UpdateGestures(); UpdateGestures();
#endif #endif

View File

@ -407,7 +407,7 @@ void PollInputEvents(void)
{ {
#if SUPPORT_GESTURES_SYSTEM #if SUPPORT_GESTURES_SYSTEM
// NOTE: Gestures update must be called every frame to reset gestures correctly // NOTE: Gestures update must be called every frame to reset gestures correctly
// because ProcessGestureEvent() is just called on an event, not every frame // because ProcessGestureEvent() is called on an event, not every frame
UpdateGestures(); UpdateGestures();
#endif #endif

View File

@ -803,17 +803,20 @@ void SetClipboardText(const char *text)
// Async EM_JS to be able to await clickboard read asynchronous function // Async EM_JS to be able to await clickboard read asynchronous function
EM_ASYNC_JS(void, RequestClipboardData, (void), { EM_ASYNC_JS(void, RequestClipboardData, (void), {
if (navigator.clipboard && window.isSecureContext) { if (navigator.clipboard && window.isSecureContext)
{
let items = await navigator.clipboard.read(); let items = await navigator.clipboard.read();
for (const item of items) { for (const item of items)
{
// Check if this item contains plain text or image // Check if this item contains plain text or image
if (item.types.includes("text/plain")) { if (item.types.includes("text/plain"))
{
const blob = await item.getType("text/plain"); const blob = await item.getType("text/plain");
const text = await blob.text(); const text = await blob.text();
window._lastClipboardString = text; window._lastClipboardString = text;
} }
else if (item.types.find(t => t.startsWith("image/"))) { else if (item.types.find(t => t.startsWith("image/")))
{
const blob = await item.getType(item.types.find(t => t.startsWith("image/"))); const blob = await item.getType(item.types.find(t => t.startsWith("image/")));
const bitmap = await createImageBitmap(blob); const bitmap = await createImageBitmap(blob);
@ -831,16 +834,16 @@ EM_ASYNC_JS(void, RequestClipboardData, (void), {
window._lastImgData = imgData; window._lastImgData = imgData;
} }
} }
} else {
console.warn("Clipboard read() requires HTTPS/Localhost");
} }
else console.warn("Clipboard read() requires HTTPS/Localhost");
}); });
// Returns the string created by RequestClipboardData from JS memory to Emscripten C memory // Returns the string created by RequestClipboardData from JS memory to Emscripten C memory
EM_JS(char*, GetLastPastedText, (void), { EM_JS(char *, GetLastPastedText, (void), {
var str = window._lastClipboardString || ""; var str = window._lastClipboardString || "";
var length = lengthBytesUTF8(str) + 1; var length = lengthBytesUTF8(str) + 1;
if (length > 1) { if (length > 1)
{
var ptr = _malloc(length); var ptr = _malloc(length);
stringToUTF8(str, ptr, length); stringToUTF8(str, ptr, length);
return ptr; return ptr;
@ -849,10 +852,12 @@ EM_JS(char*, GetLastPastedText, (void), {
}); });
// Returns the image created by RequestClipboardData from JS memory to Emscripten C memory // Returns the image created by RequestClipboardData from JS memory to Emscripten C memory
EM_JS(unsigned char*, GetLastPastedImage, (int* width, int* height), { EM_JS(unsigned char *, GetLastPastedImage, (int *width, int *height), {
if (window._lastImgData) { if (window._lastImgData)
{
const data = window._lastImgData; const data = window._lastImgData;
if (data.length > 0) { if (data.length > 0)
{
const ptr = _malloc(data.length); const ptr = _malloc(data.length);
HEAPU8.set(data, ptr); HEAPU8.set(data, ptr);
@ -861,12 +866,13 @@ EM_JS(unsigned char*, GetLastPastedImage, (int* width, int* height), {
if (width) setValue(width, window._lastImgWidth, 'i32'); if (width) setValue(width, window._lastImgWidth, 'i32');
if (height) setValue(height, window._lastImgHeight, 'i32'); if (height) setValue(height, window._lastImgHeight, 'i32');
// Clear the JS buffer so we don't fetch the same image twice // Clear the JS buffer so there is no need to fetch the same image twice
window._lastImgData = null; window._lastImgData = null;
return ptr; return ptr;
} }
} }
return 0; return 0;
}); });
@ -1072,7 +1078,7 @@ void PollInputEvents(void)
{ {
#if SUPPORT_GESTURES_SYSTEM #if SUPPORT_GESTURES_SYSTEM
// NOTE: Gestures update must be called every frame to reset gestures correctly // NOTE: Gestures update must be called every frame to reset gestures correctly
// because ProcessGestureEvent() is just called on an event, not every frame // because ProcessGestureEvent() is called on an event, not every frame
UpdateGestures(); UpdateGestures();
#endif #endif

View File

@ -781,17 +781,20 @@ void SetClipboardText(const char *text)
// Async EM_JS to be able to await clickboard read asynchronous function // Async EM_JS to be able to await clickboard read asynchronous function
EM_ASYNC_JS(void, RequestClipboardData, (void), { EM_ASYNC_JS(void, RequestClipboardData, (void), {
if (navigator.clipboard && window.isSecureContext) { if (navigator.clipboard && window.isSecureContext)
{
let items = await navigator.clipboard.read(); let items = await navigator.clipboard.read();
for (const item of items) { for (const item of items)
{
// Check if this item contains plain text or image // Check if this item contains plain text or image
if (item.types.includes("text/plain")) { if (item.types.includes("text/plain"))
{
const blob = await item.getType("text/plain"); const blob = await item.getType("text/plain");
const text = await blob.text(); const text = await blob.text();
window._lastClipboardString = text; window._lastClipboardString = text;
} }
else if (item.types.find(t => t.startsWith("image/"))) { else if (item.types.find(t => t.startsWith("image/")))
{
const blob = await item.getType(item.types.find(t => t.startsWith("image/"))); const blob = await item.getType(item.types.find(t => t.startsWith("image/")));
const bitmap = await createImageBitmap(blob); const bitmap = await createImageBitmap(blob);
@ -809,16 +812,16 @@ EM_ASYNC_JS(void, RequestClipboardData, (void), {
window._lastImgData = imgData; window._lastImgData = imgData;
} }
} }
} else {
console.warn("Clipboard read() requires HTTPS/Localhost");
} }
else console.warn("Clipboard read() requires HTTPS/Localhost");
}); });
// Returns the string created by RequestClipboardData from JS memory to Emscripten C memory // Returns the string created by RequestClipboardData from JS memory to Emscripten C memory
EM_JS(char*, GetLastPastedText, (void), { EM_JS(char *, GetLastPastedText, (void), {
var str = window._lastClipboardString || ""; var str = window._lastClipboardString || "";
var length = lengthBytesUTF8(str) + 1; var length = lengthBytesUTF8(str) + 1;
if (length > 1) { if (length > 1)
{
var ptr = _malloc(length); var ptr = _malloc(length);
stringToUTF8(str, ptr, length); stringToUTF8(str, ptr, length);
return ptr; return ptr;
@ -827,10 +830,12 @@ EM_JS(char*, GetLastPastedText, (void), {
}); });
// Returns the image created by RequestClipboardData from JS memory to Emscripten C memory // Returns the image created by RequestClipboardData from JS memory to Emscripten C memory
EM_JS(unsigned char*, GetLastPastedImage, (int* width, int* height), { EM_JS(unsigned char *, GetLastPastedImage, (int *width, int *height), {
if (window._lastImgData) { if (window._lastImgData)
{
const data = window._lastImgData; const data = window._lastImgData;
if (data.length > 0) { if (data.length > 0)
{
const ptr = _malloc(data.length); const ptr = _malloc(data.length);
HEAPU8.set(data, ptr); HEAPU8.set(data, ptr);
@ -839,12 +844,13 @@ EM_JS(unsigned char*, GetLastPastedImage, (int* width, int* height), {
if (width) setValue(width, window._lastImgWidth, 'i32'); if (width) setValue(width, window._lastImgWidth, 'i32');
if (height) setValue(height, window._lastImgHeight, 'i32'); if (height) setValue(height, window._lastImgHeight, 'i32');
// Clear the JS buffer so we don't fetch the same image twice // Clear the JS buffer so there is no need to fetch the same image twice
window._lastImgData = null; window._lastImgData = null;
return ptr; return ptr;
} }
} }
return 0; return 0;
}); });
@ -1046,7 +1052,7 @@ void PollInputEvents(void)
{ {
#if SUPPORT_GESTURES_SYSTEM #if SUPPORT_GESTURES_SYSTEM
// NOTE: Gestures update must be called every frame to reset gestures correctly // NOTE: Gestures update must be called every frame to reset gestures correctly
// because ProcessGestureEvent() is just called on an event, not every frame // because ProcessGestureEvent() is called on an event, not every frame
UpdateGestures(); UpdateGestures();
#endif #endif

View File

@ -26,7 +26,7 @@
* #define SUPPORT_FILEFORMAT_XM * #define SUPPORT_FILEFORMAT_XM
* #define SUPPORT_FILEFORMAT_MOD * #define SUPPORT_FILEFORMAT_MOD
* Selected desired fileformats to be supported for loading. Some of those formats are * Selected desired fileformats to be supported for loading. Some of those formats are
* supported by default, to remove support, just comment unrequired #define in this module * supported by default, to remove support, comment unrequired #define in this module
* *
* DEPENDENCIES: * DEPENDENCIES:
* miniaudio.h - Audio device management lib (https://github.com/mackron/miniaudio) * miniaudio.h - Audio device management lib (https://github.com/mackron/miniaudio)
@ -299,7 +299,7 @@ typedef struct tagBITMAPINFOHEADER {
#endif #endif
#ifndef AUDIO_BUFFER_RESIDUAL_CAPACITY #ifndef AUDIO_BUFFER_RESIDUAL_CAPACITY
#define AUDIO_BUFFER_RESIDUAL_CAPACITY 8 // In PCM frames. For resampling and pitch shifting. #define AUDIO_BUFFER_RESIDUAL_CAPACITY 8 // In PCM frames, for resampling and pitch shifting
#endif #endif
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -406,7 +406,7 @@ static AudioData AUDIO = { // Global AUDIO context
// NOTE: Music buffer size is defined by number of samples, independent of sample size and channels number // NOTE: Music buffer size is defined by number of samples, independent of sample size and channels number
// After some math, considering a sampleRate of 48000, a buffer refill rate of 1/60 seconds and a // After some math, considering a sampleRate of 48000, a buffer refill rate of 1/60 seconds and a
// standard double-buffering system, a 4096 samples buffer has been chosen, it should be enough // standard double-buffering system, a 4096 samples buffer has been chosen, it should be enough
// In case of music-stalls, just increase this number // In case of music-stalls, increase this number
.Buffer.defaultSize = 0, .Buffer.defaultSize = 0,
.mixedProcessor = NULL .mixedProcessor = NULL
}; };
@ -601,7 +601,7 @@ AudioBuffer *LoadAudioBuffer(ma_format format, ma_uint32 channels, ma_uint32 sam
// be consumed. Any residual input frames need to be kept track of to // be consumed. Any residual input frames need to be kept track of to
// ensure there are no discontinuities. Since raylib supports pitch // ensure there are no discontinuities. Since raylib supports pitch
// shifting, which is done through resampling, a cache will always be // shifting, which is done through resampling, a cache will always be
// required. This will be kept relatively small to avoid too much wastage. // required. This will be kept relatively small to avoid too much wastage
audioBuffer->converterResidualCount = 0; audioBuffer->converterResidualCount = 0;
audioBuffer->converterResidual = (unsigned char*)RL_CALLOC(AUDIO_BUFFER_RESIDUAL_CAPACITY*ma_get_bytes_per_frame(format, channels), 1); audioBuffer->converterResidual = (unsigned char*)RL_CALLOC(AUDIO_BUFFER_RESIDUAL_CAPACITY*ma_get_bytes_per_frame(format, channels), 1);
@ -721,7 +721,7 @@ void SetAudioBufferPitch(AudioBuffer *buffer, float pitch)
if ((buffer != NULL) && (pitch > 0.0f)) if ((buffer != NULL) && (pitch > 0.0f))
{ {
ma_mutex_lock(&AUDIO.System.lock); ma_mutex_lock(&AUDIO.System.lock);
// Pitching is just an adjustment of the sample rate // Pitching is an adjustment of the sample rate
// Note that this changes the duration of the sound: // Note that this changes the duration of the sound:
// - higher pitches will make the sound faster // - higher pitches will make the sound faster
// - lower pitches make it slower // - lower pitches make it slower
@ -1046,7 +1046,7 @@ void UnloadSound(Sound sound)
void UnloadSoundAlias(Sound alias) void UnloadSoundAlias(Sound alias)
{ {
// Untrack and unload just the sound buffer, not the sample data, it is shared with the source for the alias // Untrack and unload the sound buffer, not the sample data, it is shared with the source for the alias
if (alias.stream.buffer != NULL) if (alias.stream.buffer != NULL)
{ {
UntrackAudioBuffer(alias.stream.buffer); UntrackAudioBuffer(alias.stream.buffer);
@ -2316,7 +2316,7 @@ void DetachAudioStreamProcessor(AudioStream stream, AudioCallback process)
// Add processor to audio pipeline. Order of processors is important // Add processor to audio pipeline. Order of processors is important
// Works the same way as {Attach,Detach}AudioStreamProcessor() functions, except // Works the same way as {Attach,Detach}AudioStreamProcessor() functions, except
// these two work on the already mixed output just before sending it to the sound hardware // these two work on the already mixed output before sending it to the sound hardware
void AttachAudioMixedProcessor(AudioCallback process) void AttachAudioMixedProcessor(AudioCallback process)
{ {
ma_mutex_lock(&AUDIO.System.lock); ma_mutex_lock(&AUDIO.System.lock);
@ -2397,7 +2397,7 @@ static ma_uint32 ReadAudioBufferFramesInInternalFormat(AudioBuffer *audioBuffer,
if (currentSubBufferIndex > 1) return 0; if (currentSubBufferIndex > 1) return 0;
// Another thread can update the processed state of buffers, so // Another thread can update the processed state of buffers, so
// just take a copy here to try and avoid potential synchronization problems // take a copy here to try and avoid potential synchronization problems
bool isSubBufferProcessed[2] = { 0 }; bool isSubBufferProcessed[2] = { 0 };
isSubBufferProcessed[0] = audioBuffer->isSubBufferProcessed[0]; isSubBufferProcessed[0] = audioBuffer->isSubBufferProcessed[0];
isSubBufferProcessed[1] = audioBuffer->isSubBufferProcessed[1]; isSubBufferProcessed[1] = audioBuffer->isSubBufferProcessed[1];
@ -2478,8 +2478,8 @@ static ma_uint32 ReadAudioBufferFramesInInternalFormat(AudioBuffer *audioBuffer,
static ma_uint32 ReadAudioBufferFramesInMixingFormat(AudioBuffer *audioBuffer, float *framesOut, ma_uint32 frameCount) static ma_uint32 ReadAudioBufferFramesInMixingFormat(AudioBuffer *audioBuffer, float *framesOut, ma_uint32 frameCount)
{ {
// NOTE: Continuously converting data from the AudioBuffer's internal format to the mixing format, // NOTE: Continuously converting data from the AudioBuffer's internal format to the mixing format,
// which should be defined by the output format of the data converter. // which should be defined by the output format of the data converter
// This is done until frameCount frames have been output. // This is done until frameCount frames have been output
ma_uint32 bpf = ma_get_bytes_per_frame(audioBuffer->converter.formatIn, audioBuffer->converter.channelsIn); ma_uint32 bpf = ma_get_bytes_per_frame(audioBuffer->converter.formatIn, audioBuffer->converter.channelsIn);
ma_uint8 inputBuffer[4096] = { 0 }; ma_uint8 inputBuffer[4096] = { 0 };
ma_uint32 inputBufferFrameCap = sizeof(inputBuffer)/bpf; ma_uint32 inputBufferFrameCap = sizeof(inputBuffer)/bpf;
@ -2491,34 +2491,34 @@ static ma_uint32 ReadAudioBufferFramesInMixingFormat(AudioBuffer *audioBuffer, f
ma_uint64 outputFramesToProcessThisIteration = frameCount - totalOutputFramesProcessed; ma_uint64 outputFramesToProcessThisIteration = frameCount - totalOutputFramesProcessed;
//ma_uint64 inputFramesToProcessThisIteration = 0; //ma_uint64 inputFramesToProcessThisIteration = 0;
// Process any residual input frames from the previous read first. // Process any residual input frames from the previous read first
if (audioBuffer->converterResidualCount > 0) if (audioBuffer->converterResidualCount > 0)
{ {
ma_uint64 inputFramesProcessedThisIteration = audioBuffer->converterResidualCount; ma_uint64 inputFramesProcessedThisIteration = audioBuffer->converterResidualCount;
ma_uint64 outputFramesProcessedThisIteration = outputFramesToProcessThisIteration; ma_uint64 outputFramesProcessedThisIteration = outputFramesToProcessThisIteration;
ma_data_converter_process_pcm_frames(&audioBuffer->converter, audioBuffer->converterResidual, &inputFramesProcessedThisIteration, runningFramesOut, &outputFramesProcessedThisIteration); ma_data_converter_process_pcm_frames(&audioBuffer->converter, audioBuffer->converterResidual, &inputFramesProcessedThisIteration, runningFramesOut, &outputFramesProcessedThisIteration);
// Make sure the data in the cache is consumed. This can be optimized to use a cursor instead of a memmove(). // Make sure the data in the cache is consumed, this can be optimized to use a cursor instead of a memmove()
memmove(audioBuffer->converterResidual, audioBuffer->converterResidual + inputFramesProcessedThisIteration*bpf, (size_t)(AUDIO_BUFFER_RESIDUAL_CAPACITY - inputFramesProcessedThisIteration) * bpf); memmove(audioBuffer->converterResidual, audioBuffer->converterResidual + inputFramesProcessedThisIteration*bpf, (size_t)(AUDIO_BUFFER_RESIDUAL_CAPACITY - inputFramesProcessedThisIteration)*bpf);
audioBuffer->converterResidualCount -= (ma_uint32)inputFramesProcessedThisIteration; // Safe cast audioBuffer->converterResidualCount -= (ma_uint32)inputFramesProcessedThisIteration; // Safe cast
totalOutputFramesProcessed += (ma_uint32)outputFramesProcessedThisIteration; // Safe cast totalOutputFramesProcessed += (ma_uint32)outputFramesProcessedThisIteration; // Safe cast
} }
else else
{ {
// Getting here means there are no residual frames from the previous read. Fresh data can now be // Getting here means there are no residual frames from the previous read
// pulled from the AudioBuffer and processed. // Fresh data can now be pulled from the AudioBuffer and processed
// //
// A best guess needs to be used made to determine how many input frames to pull from the // A best guess needs to be used made to determine how many input frames to pull from the buffer
// buffer. There are three possible outcomes: 1) exact; 2) underestimated; 3) overestimated. // There are three possible outcomes: 1) exact; 2) underestimated; 3) overestimated
// //
// When the guess is exactly correct or underestimated there is nothing special to handle - it'll be // When the guess is exactly correct or underestimated there is nothing special to handle,
// handled naturally by the loop. // it'll be handled naturally by the loop
// //
// When the guess is overestimated, that's when it gets more complicated. In this case, any overflow // When the guess is overestimated, that's when it gets more complicated
// needs to be stored in a buffer for later processing by the next read. // In this case, any overflow needs to be stored in a buffer for later processing by the next read
ma_uint32 estimatedInputFrameCount = (ma_uint32)(((float)audioBuffer->converter.resampler.sampleRateIn / audioBuffer->converter.resampler.sampleRateOut) * outputFramesToProcessThisIteration); ma_uint32 estimatedInputFrameCount = (ma_uint32)(((float)audioBuffer->converter.resampler.sampleRateIn / audioBuffer->converter.resampler.sampleRateOut)*outputFramesToProcessThisIteration);
if (estimatedInputFrameCount == 0) estimatedInputFrameCount = 1; // Make sure at least one input frame is read. if (estimatedInputFrameCount == 0) estimatedInputFrameCount = 1; // Make sure at least one input frame is read
if (estimatedInputFrameCount > inputBufferFrameCap) estimatedInputFrameCount = inputBufferFrameCap; if (estimatedInputFrameCount > inputBufferFrameCap) estimatedInputFrameCount = inputBufferFrameCap;
ma_uint32 inputFramesInInternalFormatCount = ReadAudioBufferFramesInInternalFormat(audioBuffer, inputBuffer, estimatedInputFrameCount); ma_uint32 inputFramesInInternalFormatCount = ReadAudioBufferFramesInInternalFormat(audioBuffer, inputBuffer, estimatedInputFrameCount);
@ -2531,17 +2531,17 @@ static ma_uint32 ReadAudioBufferFramesInMixingFormat(AudioBuffer *audioBuffer, f
if (inputFramesInInternalFormatCount > inputFramesProcessedThisIteration) if (inputFramesInInternalFormatCount > inputFramesProcessedThisIteration)
{ {
// Getting here means the estimated input frame count was overestimated. The residual needs // Getting here means the estimated input frame count was overestimated
// be stored for later use. // The residual needs be stored for later use
ma_uint64 residualFrameCount = inputFramesInInternalFormatCount - inputFramesProcessedThisIteration; ma_uint64 residualFrameCount = inputFramesInInternalFormatCount - inputFramesProcessedThisIteration;
// A safety check to make sure the capacity of the residual cache is not exceeded. // A safety check to make sure the capacity of the residual cache is not exceeded
if (residualFrameCount > AUDIO_BUFFER_RESIDUAL_CAPACITY) if (residualFrameCount > AUDIO_BUFFER_RESIDUAL_CAPACITY)
{ {
residualFrameCount = AUDIO_BUFFER_RESIDUAL_CAPACITY; residualFrameCount = AUDIO_BUFFER_RESIDUAL_CAPACITY;
} }
memcpy(audioBuffer->converterResidual, inputBuffer + inputFramesProcessedThisIteration*bpf, (size_t)(residualFrameCount * bpf)); memcpy(audioBuffer->converterResidual, inputBuffer + inputFramesProcessedThisIteration*bpf, (size_t)(residualFrameCount*bpf));
audioBuffer->converterResidualCount = (unsigned int)residualFrameCount; audioBuffer->converterResidualCount = (unsigned int)residualFrameCount;
} }
@ -2559,7 +2559,7 @@ static void OnSendAudioDataToDevice(ma_device *pDevice, void *pFramesOut, const
{ {
(void)pDevice; (void)pDevice;
// Mixing is basically just an accumulation, need to initialize the output buffer to 0 // Mixing is basically an accumulation, need to initialize the output buffer to 0
memset(pFramesOut, 0, frameCount*pDevice->playback.channels*ma_get_bytes_per_sample(pDevice->playback.format)); memset(pFramesOut, 0, frameCount*pDevice->playback.channels*ma_get_bytes_per_sample(pDevice->playback.format));
// Using a mutex here for thread-safety which makes things not real-time // Using a mutex here for thread-safety which makes things not real-time
@ -2577,7 +2577,7 @@ static void OnSendAudioDataToDevice(ma_device *pDevice, void *pFramesOut, const
{ {
if (framesRead >= frameCount) break; if (framesRead >= frameCount) break;
// Just read as much data as possible from the stream // Read as much data as possible from the stream
ma_uint32 framesToRead = (frameCount - framesRead); ma_uint32 framesToRead = (frameCount - framesRead);
while (framesToRead > 0) while (framesToRead > 0)
@ -2626,7 +2626,7 @@ static void OnSendAudioDataToDevice(ma_device *pDevice, void *pFramesOut, const
} }
else else
{ {
// Should never get here, but just for safety, // Should never get here, but for safety,
// move the cursor position back to the start and continue the loop // move the cursor position back to the start and continue the loop
audioBuffer->frameCursorPos = 0; audioBuffer->frameCursorPos = 0;
continue; continue;
@ -2651,7 +2651,7 @@ static void OnSendAudioDataToDevice(ma_device *pDevice, void *pFramesOut, const
ma_mutex_unlock(&AUDIO.System.lock); ma_mutex_unlock(&AUDIO.System.lock);
} }
// Main mixing function, pretty simple in this project, just an accumulation // Main mixing function, pretty simple in this project, only an accumulation
// NOTE: framesOut is both an input and an output, it is initially filled with zeros outside of this function // NOTE: framesOut is both an input and an output, it is initially filled with zeros outside of this function
static void MixAudioFrames(float *framesOut, const float *framesIn, ma_uint32 frameCount, AudioBuffer *buffer) static void MixAudioFrames(float *framesOut, const float *framesIn, ma_uint32 frameCount, AudioBuffer *buffer)
{ {
@ -2739,7 +2739,7 @@ static void UpdateAudioStreamInLockedState(AudioStream stream, const void *data,
} }
else else
{ {
// Just update whichever sub-buffer is processed // Update whichever sub-buffer is processed
subBufferToUpdate = (stream.buffer->isSubBufferProcessed[0])? 0 : 1; subBufferToUpdate = (stream.buffer->isSubBufferProcessed[0])? 0 : 1;
} }

View File

@ -159,7 +159,7 @@
// NOTE: Set some defines with some data types declared by raylib // NOTE: Set some defines with some data types declared by raylib
// Other modules (raymath, rlgl) also require some of those types, so, // Other modules (raymath, rlgl) also require some of those types, so,
// to be able to use those other modules as standalone (not depending on raylib) // to be able to use those other modules as standalone (not depending on raylib)
// this defines are very useful for internal check and avoid type (re)definitions // this defines are useful for internal check and avoid type (re)definitions
#define RL_COLOR_TYPE #define RL_COLOR_TYPE
#define RL_RECTANGLE_TYPE #define RL_RECTANGLE_TYPE
#define RL_VECTOR2_TYPE #define RL_VECTOR2_TYPE
@ -733,7 +733,7 @@ typedef enum {
// Gamepad buttons // Gamepad buttons
typedef enum { typedef enum {
GAMEPAD_BUTTON_UNKNOWN = 0, // Unknown button, just for error checking GAMEPAD_BUTTON_UNKNOWN = 0, // Unknown button, for error checking
GAMEPAD_BUTTON_LEFT_FACE_UP, // Gamepad left DPAD up button GAMEPAD_BUTTON_LEFT_FACE_UP, // Gamepad left DPAD up button
GAMEPAD_BUTTON_LEFT_FACE_RIGHT, // Gamepad left DPAD right button GAMEPAD_BUTTON_LEFT_FACE_RIGHT, // Gamepad left DPAD right button
GAMEPAD_BUTTON_LEFT_FACE_DOWN, // Gamepad left DPAD down button GAMEPAD_BUTTON_LEFT_FACE_DOWN, // Gamepad left DPAD down button
@ -878,7 +878,7 @@ typedef enum {
// NOTE 1: Filtering considers mipmaps if available in the texture // NOTE 1: Filtering considers mipmaps if available in the texture
// NOTE 2: Filter is accordingly set for minification and magnification // NOTE 2: Filter is accordingly set for minification and magnification
typedef enum { typedef enum {
TEXTURE_FILTER_POINT = 0, // No filter, just pixel approximation TEXTURE_FILTER_POINT = 0, // No filter, pixel approximation
TEXTURE_FILTER_BILINEAR, // Linear filtering TEXTURE_FILTER_BILINEAR, // Linear filtering
TEXTURE_FILTER_TRILINEAR, // Trilinear filtering (linear with mipmaps) TEXTURE_FILTER_TRILINEAR, // Trilinear filtering (linear with mipmaps)
TEXTURE_FILTER_ANISOTROPIC_4X, // Anisotropic filtering 4x TEXTURE_FILTER_ANISOTROPIC_4X, // Anisotropic filtering 4x

View File

@ -567,15 +567,9 @@ RMAPI Vector2 Vector2ClampValue(Vector2 v, float min, float max)
{ {
length = sqrtf(length); length = sqrtf(length);
float scale = 1; // By default, 1 as the neutral element. float scale = 1; // By default, 1 as the neutral element
if (length < min) if (length < min) scale = min/length;
{ else if (length > max) scale = max/length;
scale = min/length;
}
else if (length > max)
{
scale = max/length;
}
result.x = v.x*scale; result.x = v.x*scale;
result.y = v.y*scale; result.y = v.y*scale;
@ -1215,15 +1209,9 @@ RMAPI Vector3 Vector3ClampValue(Vector3 v, float min, float max)
{ {
length = sqrtf(length); length = sqrtf(length);
float scale = 1; // By default, 1 as the neutral element. float scale = 1; // By default, 1 as the neutral element
if (length < min) if (length < min) scale = min/length;
{ else if (length > max) scale = max/length;
scale = min/length;
}
else if (length > max)
{
scale = max/length;
}
result.x = v.x*scale; result.x = v.x*scale;
result.y = v.y*scale; result.y = v.y*scale;
@ -2574,8 +2562,8 @@ RMAPI void QuaternionToAxisAngle(Quaternion q, Vector3 *outAxis, float *outAngle
} }
else else
{ {
// This occurs when the angle is zero. // This occurs when the angle is zero
// Not a problem: just set an arbitrary normalized axis. // Not a problem, set an arbitrary normalized axis
resAxis.x = 1.0f; resAxis.x = 1.0f;
} }
@ -2702,10 +2690,10 @@ RMAPI void MatrixDecompose(Matrix mat, Vector3 *translation, Quaternion *rotatio
translation->y = mat.m13; translation->y = mat.m13;
translation->z = mat.m14; translation->z = mat.m14;
// Matrix Columns - Rotation will be extracted into here. // Matrix Columns - Rotation will be extracted into here
Vector3 matColumns[3] = { { mat.m0, mat.m4, mat.m8 }, Vector3 matColumns[3] = {{ mat.m0, mat.m4, mat.m8 },
{ mat.m1, mat.m5, mat.m9 }, { mat.m1, mat.m5, mat.m9 },
{ mat.m2, mat.m6, mat.m10 } }; { mat.m2, mat.m6, mat.m10 }};
// Shear Parameters XY, XZ, and YZ (extract and ignored) // Shear Parameters XY, XZ, and YZ (extract and ignored)
float shear[3] = { 0 }; float shear[3] = { 0 };
@ -2756,7 +2744,7 @@ RMAPI void MatrixDecompose(Matrix mat, Vector3 *translation, Quaternion *rotatio
shear[2] /= scl.z; // Correct YZ shear shear[2] /= scl.z; // Correct YZ shear
} }
// matColumns are now orthonormal in O(3). Now ensure its in SO(3) by enforcing det = 1. // matColumns are now orthonormal in O(3). Now ensure its in SO(3) by enforcing det = 1
if (Vector3DotProduct(matColumns[0], Vector3CrossProduct(matColumns[1], matColumns[2])) < 0) if (Vector3DotProduct(matColumns[0], Vector3CrossProduct(matColumns[1], matColumns[2])) < 0)
{ {
scl = Vector3Negate(scl); scl = Vector3Negate(scl);

View File

@ -365,7 +365,7 @@ void CameraPitch(Camera *camera, float angle, bool lockView, bool rotateAroundTa
if (lockView) if (lockView)
{ {
// In these camera modes, clamp the Pitch angle // In these camera modes, clamp the Pitch angle
// to allow only viewing straight up or down. // to allow only viewing straight up or down
// Clamp view up // Clamp view up
float maxAngleUp = Vector3Angle(up, targetPosition); float maxAngleUp = Vector3Angle(up, targetPosition);
@ -460,7 +460,6 @@ void UpdateCamera(Camera *camera, int mode)
if (mode == CAMERA_CUSTOM) {} if (mode == CAMERA_CUSTOM) {}
else if (mode == CAMERA_ORBITAL) else if (mode == CAMERA_ORBITAL)
{ {
// Orbital can just orbit
Matrix rotation = MatrixRotate(GetCameraUp(camera), cameraOrbitalSpeed); Matrix rotation = MatrixRotate(GetCameraUp(camera), cameraOrbitalSpeed);
Vector3 view = Vector3Subtract(camera->position, camera->target); Vector3 view = Vector3Subtract(camera->position, camera->target);
view = Vector3Transform(view, rotation); view = Vector3Transform(view, rotation);

View File

@ -1841,7 +1841,7 @@ void TakeScreenshot(const char *fileName)
// Setup window configuration flags (view FLAGS) // Setup window configuration flags (view FLAGS)
// NOTE: This function is expected to be called before window creation, // NOTE: This function is expected to be called before window creation,
// because it sets up some flags for the window creation process // because it sets up some flags for the window creation process
// To configure window states after creation, just use SetWindowState() // To configure window states after creation, use SetWindowState()
void SetConfigFlags(unsigned int flags) void SetConfigFlags(unsigned int flags)
{ {
if (CORE.Window.ready) TRACELOG(LOG_WARNING, "WINDOW: SetConfigFlags called after window initialization, Use \"SetWindowState\" to set flags instead"); if (CORE.Window.ready) TRACELOG(LOG_WARNING, "WINDOW: SetConfigFlags called after window initialization, Use \"SetWindowState\" to set flags instead");

View File

@ -43,7 +43,7 @@
* #define RLGL_ENABLE_OPENGL_DEBUG_CONTEXT * #define RLGL_ENABLE_OPENGL_DEBUG_CONTEXT
* Enable debug context (only available on OpenGL 4.3) * Enable debug context (only available on OpenGL 4.3)
* *
* rlgl capabilities could be customized just defining some internal * rlgl capabilities could be customized defining some internal
* values before library inclusion (default values listed): * values before library inclusion (default values listed):
* *
* #define RL_DEFAULT_BATCH_BUFFER_ELEMENTS 8192 // Default internal render batch elements limits * #define RL_DEFAULT_BATCH_BUFFER_ELEMENTS 8192 // Default internal render batch elements limits
@ -396,7 +396,7 @@ typedef struct rlVertexBuffer {
// Draw call type // Draw call type
// NOTE: Only texture changes register a new draw, other state-change-related elements are not // NOTE: Only texture changes register a new draw, other state-change-related elements are not
// used at this moment (vaoId, shaderId, matrices), raylib just forces a batch draw call if any // used at this moment (vaoId, shaderId, matrices), raylib forces a batch draw call if any
// of those state-change happens (this is done in core module) // of those state-change happens (this is done in core module)
typedef struct rlDrawCall { typedef struct rlDrawCall {
int mode; // Drawing mode: LINES, TRIANGLES, QUADS int mode; // Drawing mode: LINES, TRIANGLES, QUADS
@ -478,7 +478,7 @@ typedef enum {
// NOTE 1: Filtering considers mipmaps if available in the texture // NOTE 1: Filtering considers mipmaps if available in the texture
// NOTE 2: Filter is accordingly set for minification and magnification // NOTE 2: Filter is accordingly set for minification and magnification
typedef enum { typedef enum {
RL_TEXTURE_FILTER_POINT = 0, // No filter, just pixel approximation RL_TEXTURE_FILTER_POINT = 0, // No filter, pixel approximation
RL_TEXTURE_FILTER_BILINEAR, // Linear filtering RL_TEXTURE_FILTER_BILINEAR, // Linear filtering
RL_TEXTURE_FILTER_TRILINEAR, // Trilinear filtering (linear with mipmaps) RL_TEXTURE_FILTER_TRILINEAR, // Trilinear filtering (linear with mipmaps)
RL_TEXTURE_FILTER_ANISOTROPIC_4X, // Anisotropic filtering 4x RL_TEXTURE_FILTER_ANISOTROPIC_4X, // Anisotropic filtering 4x
@ -3356,7 +3356,7 @@ unsigned int rlLoadTexture(const void *data, int width, int height, int format,
} }
// Texture parameters configuration // Texture parameters configuration
// NOTE: glTexParameteri does NOT affect texture uploading, just the way it's used // NOTE: glTexParameteri does NOT affect texture uploading
#if defined(GRAPHICS_API_OPENGL_ES2) #if defined(GRAPHICS_API_OPENGL_ES2)
// NOTE: OpenGL ES 2.0 with no GL_OES_texture_npot support (i.e. WebGL) has limited NPOT support, so CLAMP_TO_EDGE must be used // NOTE: OpenGL ES 2.0 with no GL_OES_texture_npot support (i.e. WebGL) has limited NPOT support, so CLAMP_TO_EDGE must be used
if (RLGL.ExtSupported.texNPOT) if (RLGL.ExtSupported.texNPOT)
@ -3741,7 +3741,7 @@ void *rlReadTexturePixels(unsigned int id, int width, int height, int format)
// Two possible Options: // Two possible Options:
// 1 - Bind texture to color fbo attachment and glReadPixels() // 1 - Bind texture to color fbo attachment and glReadPixels()
// 2 - Create an fbo, activate it, render quad with texture, glReadPixels() // 2 - Create an fbo, activate it, render quad with texture, glReadPixels()
// Using Option 1, just need to care for texture format on retrieval // Using Option 1, care for texture format on retrieval
// NOTE: This behaviour could be conditioned by graphic driver... // NOTE: This behaviour could be conditioned by graphic driver...
unsigned int fboId = rlLoadFramebuffer(); unsigned int fboId = rlLoadFramebuffer();
@ -4199,7 +4199,7 @@ unsigned int rlLoadShaderCode(const char *vsCode, const char *fsCode)
if (fsCode != NULL) fragmentShaderId = rlCompileShader(fsCode, GL_FRAGMENT_SHADER); if (fsCode != NULL) fragmentShaderId = rlCompileShader(fsCode, GL_FRAGMENT_SHADER);
else fragmentShaderId = RLGL.State.defaultFShaderId; else fragmentShaderId = RLGL.State.defaultFShaderId;
// In case vertex and fragment shader are the default ones, no need to recompile, just assign the default shader program id // In case vertex and fragment shader are the default ones, no need to recompile, assign the default shader program id
if ((vertexShaderId == RLGL.State.defaultVShaderId) && (fragmentShaderId == RLGL.State.defaultFShaderId)) id = RLGL.State.defaultShaderId; if ((vertexShaderId == RLGL.State.defaultVShaderId) && (fragmentShaderId == RLGL.State.defaultFShaderId)) id = RLGL.State.defaultShaderId;
else if ((vertexShaderId > 0) && (fragmentShaderId > 0)) else if ((vertexShaderId > 0) && (fragmentShaderId > 0))
{ {

View File

@ -792,13 +792,9 @@ void DrawCapsule(Vector3 startPos, Vector3 endPos, float radius, int slices, int
{ {
for (int j = 0; j < slices; j++) for (int j = 0; j < slices; j++)
{ {
// Building up the rings from capCenter in the direction of the 'direction' vector computed earlier
// we build up the rings from capCenter in the direction of the 'direction' vector we computed earlier // Compute the four vertices
// as we iterate through the rings they must be placed higher above the center, the height we need is sin(angle(i))
// as we iterate through the rings they must get smaller by the cos(angle(i))
// compute the four vertices
float ringSin1 = sinf(baseSliceAngle*(j + 0))*cosf(baseRingAngle*( i + 0 )); float ringSin1 = sinf(baseSliceAngle*(j + 0))*cosf(baseRingAngle*( i + 0 ));
float ringCos1 = cosf(baseSliceAngle*(j + 0))*cosf(baseRingAngle*( i + 0 )); float ringCos1 = cosf(baseSliceAngle*(j + 0))*cosf(baseRingAngle*( i + 0 ));
Vector3 w1 = (Vector3){ Vector3 w1 = (Vector3){
@ -935,13 +931,9 @@ void DrawCapsuleWires(Vector3 startPos, Vector3 endPos, float radius, int slices
{ {
for (int j = 0; j < slices; j++) for (int j = 0; j < slices; j++)
{ {
// Building up the rings from capCenter in the direction of the 'direction' vector computed earlier
// we build up the rings from capCenter in the direction of the 'direction' vector we computed earlier // Compute the four vertices
// as we iterate through the rings they must be placed higher above the center, the height we need is sin(angle(i))
// as we iterate through the rings they must get smaller by the cos(angle(i))
// compute the four vertices
float ringSin1 = sinf(baseSliceAngle*(j + 0))*cosf(baseRingAngle*( i + 0 )); float ringSin1 = sinf(baseSliceAngle*(j + 0))*cosf(baseRingAngle*( i + 0 ));
float ringCos1 = cosf(baseSliceAngle*(j + 0))*cosf(baseRingAngle*( i + 0 )); float ringCos1 = cosf(baseSliceAngle*(j + 0))*cosf(baseRingAngle*( i + 0 ));
Vector3 w1 = (Vector3){ Vector3 w1 = (Vector3){
@ -1147,7 +1139,7 @@ Model LoadModel(const char *fileName)
// Load model from generated mesh // Load model from generated mesh
// WARNING: A shallow copy of mesh is generated, passed by value, // WARNING: A shallow copy of mesh is generated, passed by value,
// as long as struct contains pointers to data and some values, we get a copy // as long as struct contains pointers to data and some values, get a copy
// of mesh pointing to same data as original version... be careful! // of mesh pointing to same data as original version... be careful!
Model LoadModelFromMesh(Mesh mesh) Model LoadModelFromMesh(Mesh mesh)
{ {
@ -1194,7 +1186,7 @@ bool IsModelValid(Model model)
if ((model.meshes[i].boneIndices != NULL) && (model.meshes[i].vboId[7] == 0)) { result = false; break; } // Vertex boneIndices buffer not uploaded to GPU if ((model.meshes[i].boneIndices != NULL) && (model.meshes[i].vboId[7] == 0)) { result = false; break; } // Vertex boneIndices buffer not uploaded to GPU
if ((model.meshes[i].boneWeights != NULL) && (model.meshes[i].vboId[8] == 0)) { result = false; break; } // Vertex boneWeights buffer not uploaded to GPU if ((model.meshes[i].boneWeights != NULL) && (model.meshes[i].vboId[8] == 0)) { result = false; break; } // Vertex boneWeights buffer not uploaded to GPU
// NOTE: Some OpenGL versions do not support VAO, so we don't check it // NOTE: Some OpenGL versions do not support VAO, so avoid below check
//if (model.meshes[i].vaoId == 0) { result = false; break } //if (model.meshes[i].vaoId == 0) { result = false; break }
} }
@ -1211,7 +1203,7 @@ void UnloadModel(Model model)
// Unload materials maps // Unload materials maps
// NOTE: As the user could be sharing shaders and textures between models, // NOTE: As the user could be sharing shaders and textures between models,
// we don't unload the material but just free its maps, // don't unload the material but free its maps,
// the user is responsible for freeing models shaders and textures // the user is responsible for freeing models shaders and textures
for (int i = 0; i < model.materialCount; i++) RL_FREE(model.materials[i].maps); for (int i = 0; i < model.materialCount; i++) RL_FREE(model.materials[i].maps);
@ -1510,8 +1502,8 @@ void DrawMesh(Mesh mesh, Material material, Matrix transform)
} }
// Get a copy of current matrices to work with, // Get a copy of current matrices to work with,
// just in case stereo render is required, and we need to modify them // in case stereo render is required, and they need to be modified
// NOTE: At this point the modelview matrix just contains the view matrix (camera) // NOTE: At this point the modelview matrix contains the view matrix (camera)
// That's because BeginMode3D() sets it and there is no model-drawing function // That's because BeginMode3D() sets it and there is no model-drawing function
// that modifies it, all use rlPushMatrix() and rlPopMatrix() // that modifies it, all use rlPushMatrix() and rlPopMatrix()
Matrix matModel = MatrixIdentity(); Matrix matModel = MatrixIdentity();
@ -1729,8 +1721,8 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i
} }
// Get a copy of current matrices to work with, // Get a copy of current matrices to work with,
// just in case stereo render is required, and we need to modify them // in case stereo render is required, and they need to be modified
// NOTE: At this point the modelview matrix just contains the view matrix (camera) // NOTE: At this point the modelview matrix contains the view matrix (camera)
// That's because BeginMode3D() sets it and there is no model-drawing function // That's because BeginMode3D() sets it and there is no model-drawing function
// that modifies it, all use rlPushMatrix() and rlPopMatrix() // that modifies it, all use rlPushMatrix() and rlPopMatrix()
Matrix matModel = MatrixIdentity(); Matrix matModel = MatrixIdentity();
@ -1753,7 +1745,7 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i
// This could alternatively use a static VBO and either glMapBuffer() or glBufferSubData() // This could alternatively use a static VBO and either glMapBuffer() or glBufferSubData()
// It isn't clear which would be reliably faster in all cases and on all platforms, // It isn't clear which would be reliably faster in all cases and on all platforms,
// anecdotally glMapBuffer() seems very slow (syncs) while glBufferSubData() seems // anecdotally glMapBuffer() seems quite slow (syncs) while glBufferSubData() seems
// no faster, since all the transform matrices are transferred anyway // no faster, since all the transform matrices are transferred anyway
instancesVboId = rlLoadVertexBuffer(instanceTransform, instances*sizeof(float16), false); instancesVboId = rlLoadVertexBuffer(instanceTransform, instances*sizeof(float16), false);
@ -2508,7 +2500,7 @@ static void UpdateModelAnimationVertexBuffers(Model model)
bufferUpdateRequired = true; bufferUpdateRequired = true;
// Normals processing // Normals processing
// NOTE: We use meshes.baseNormals (default normal) to calculate meshes.normals (animated normals) // NOTE: Using meshes.baseNormals (default normal) to calculate meshes.normals (animated normals)
if ((mesh.normals != NULL) && (mesh.animNormals != NULL )) if ((mesh.normals != NULL) && (mesh.animNormals != NULL ))
{ {
animNormal = (Vector3){ mesh.normals[vCounter], mesh.normals[vCounter + 1], mesh.normals[vCounter + 2] }; animNormal = (Vector3){ mesh.normals[vCounter], mesh.normals[vCounter + 1], mesh.normals[vCounter + 2] };
@ -3375,7 +3367,7 @@ Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize)
Vector2 *mapTexcoords = (Vector2 *)RL_MALLOC(maxTriangles*3*sizeof(Vector2)); Vector2 *mapTexcoords = (Vector2 *)RL_MALLOC(maxTriangles*3*sizeof(Vector2));
Vector3 *mapNormals = (Vector3 *)RL_MALLOC(maxTriangles*3*sizeof(Vector3)); Vector3 *mapNormals = (Vector3 *)RL_MALLOC(maxTriangles*3*sizeof(Vector3));
// Define the 6 normals of the cube, we will combine them accordingly later... // Define the 6 normals of the cube, combined accordingly later
Vector3 n1 = { 1.0f, 0.0f, 0.0f }; Vector3 n1 = { 1.0f, 0.0f, 0.0f };
Vector3 n2 = { -1.0f, 0.0f, 0.0f }; Vector3 n2 = { -1.0f, 0.0f, 0.0f };
Vector3 n3 = { 0.0f, 1.0f, 0.0f }; Vector3 n3 = { 0.0f, 1.0f, 0.0f };
@ -3383,7 +3375,8 @@ Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize)
Vector3 n5 = { 0.0f, 0.0f, -1.0f }; Vector3 n5 = { 0.0f, 0.0f, -1.0f };
Vector3 n6 = { 0.0f, 0.0f, 1.0f }; Vector3 n6 = { 0.0f, 0.0f, 1.0f };
// NOTE: We use texture rectangles to define different textures for top-bottom-front-back-right-left (6) // NOTE: Using texture rectangles to define different
// textures for top-bottom-front-back-right-left (6)
typedef struct RectangleF { typedef struct RectangleF {
float x; float x;
float y; float y;
@ -3402,7 +3395,7 @@ Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize)
{ {
for (int x = 0; x < cubicmap.width; x++) for (int x = 0; x < cubicmap.width; x++)
{ {
// Define the 8 vertex of the cube, we will combine them accordingly later... // Define the 8 vertex of the cube, to be combined accordingly later
Vector3 v1 = { w*(x - 0.5f), h2, h*(z - 0.5f) }; Vector3 v1 = { w*(x - 0.5f), h2, h*(z - 0.5f) };
Vector3 v2 = { w*(x - 0.5f), h2, h*(z + 0.5f) }; Vector3 v2 = { w*(x - 0.5f), h2, h*(z + 0.5f) };
Vector3 v3 = { w*(x + 0.5f), h2, h*(z + 0.5f) }; Vector3 v3 = { w*(x + 0.5f), h2, h*(z + 0.5f) };
@ -3412,7 +3405,7 @@ Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize)
Vector3 v7 = { w*(x - 0.5f), 0, h*(z + 0.5f) }; Vector3 v7 = { w*(x - 0.5f), 0, h*(z + 0.5f) };
Vector3 v8 = { w*(x + 0.5f), 0, h*(z + 0.5f) }; Vector3 v8 = { w*(x + 0.5f), 0, h*(z + 0.5f) };
// We check pixel color to be WHITE -> draw full cube // Check pixel color to be WHITE -> draw full cube
if (COLOR_EQUAL(pixels[z*cubicmap.width + x], WHITE)) if (COLOR_EQUAL(pixels[z*cubicmap.width + x], WHITE))
{ {
// Define triangles and checking collateral cubes // Define triangles and checking collateral cubes
@ -3589,7 +3582,7 @@ Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize)
tcCounter += 6; tcCounter += 6;
} }
} }
// We check pixel color to be BLACK, we will only draw floor and roof // Check pixel color to be BLACK, in that case only drawing floor and roof
else if (COLOR_EQUAL(pixels[z*cubicmap.width + x], BLACK)) else if (COLOR_EQUAL(pixels[z*cubicmap.width + x], BLACK))
{ {
// Define top triangles (2 tris, 6 vertex --> v1-v2-v3, v1-v3-v4) // Define top triangles (2 tris, 6 vertex --> v1-v2-v3, v1-v3-v4)
@ -4106,8 +4099,8 @@ bool CheckCollisionSpheres(Vector3 center1, float radius1, Vector3 center2, floa
{ {
bool collision = false; bool collision = false;
// Simple way to check for collision, just checking distance between two points // Simple way to check for collision, checking distance between two points
// Unfortunately, sqrtf() is a costly operation, so we avoid it with following solution // Unfortunately, sqrtf() is a costly operation, so avoid it with following solution
/* /*
float dx = center1.x - center2.x; // X distance between centers float dx = center1.x - center2.x; // X distance between centers
float dy = center1.y - center2.y; // Y distance between centers float dy = center1.y - center2.y; // Y distance between centers
@ -4235,7 +4228,7 @@ RayCollision GetRayCollisionBox(Ray ray, BoundingBox box)
// Get vector center point->hit point // Get vector center point->hit point
collision.normal = Vector3Subtract(collision.point, collision.normal); collision.normal = Vector3Subtract(collision.point, collision.normal);
// Scale vector to unit cube // Scale vector to unit cube
// NOTE: We use an additional .01 to fix numerical errors // NOTE: Use an additional .01 to fix numerical errors
collision.normal = Vector3Scale(collision.normal, 2.01f); collision.normal = Vector3Scale(collision.normal, 2.01f);
collision.normal = Vector3Divide(collision.normal, Vector3Subtract(box.max, box.min)); collision.normal = Vector3Divide(collision.normal, Vector3Subtract(box.max, box.min));
// The relevant elements of the vector are now slightly larger than 1.0f (or smaller than -1.0f) // The relevant elements of the vector are now slightly larger than 1.0f (or smaller than -1.0f)
@ -4476,7 +4469,7 @@ static Model LoadOBJ(const char *fileName)
} }
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, a new mesh is allocated
} }
lastMaterial = objAttributes.material_ids[faceId]; lastMaterial = objAttributes.material_ids[faceId];
@ -4492,7 +4485,7 @@ static Model LoadOBJ(const char *fileName)
model.materialCount = objMaterialCount; 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 // Allocate at least one material
{ {
model.materialCount = 1; model.materialCount = 1;
model.materials = (Material *)MemAlloc(sizeof(Material)*1); model.materials = (Material *)MemAlloc(sizeof(Material)*1);
@ -4515,7 +4508,7 @@ static Model LoadOBJ(const char *fileName)
// Walk all the faces // Walk all the faces
for (unsigned int faceId = 0; faceId < objAttributes.num_faces; faceId++) for (unsigned int faceId = 0; faceId < objAttributes.num_faces; faceId++)
{ {
bool newMesh = false; // Do we need a new mesh? bool newMesh = false; // Is a new mesh required?
if (faceId >= nextShapeEnd) if (faceId >= nextShapeEnd)
{ {
// Try to find the last vert in the next shape // Try to find the last vert in the next shape
@ -4585,7 +4578,7 @@ static Model LoadOBJ(const char *fileName)
// Walk all the faces // Walk all the faces
for (unsigned int faceId = 0; faceId < objAttributes.num_faces; faceId++) for (unsigned int faceId = 0; faceId < objAttributes.num_faces; faceId++)
{ {
bool newMesh = false; // Do we need a new mesh? bool newMesh = false; // Is a new mesh required?
if (faceId >= nextShapeEnd) if (faceId >= nextShapeEnd)
{ {
// Try to find the last vert in the next shape // Try to find the last vert in the next shape
@ -4595,7 +4588,7 @@ static Model LoadOBJ(const char *fileName)
newMesh = true; newMesh = true;
} }
// If this is a new material, we need to allocate a new mesh // If this is a new material, a new mesh is allocated
if (lastMaterial != -1 && objAttributes.material_ids[faceId] != lastMaterial) newMesh = true; if (lastMaterial != -1 && objAttributes.material_ids[faceId] != lastMaterial) newMesh = true;
lastMaterial = objAttributes.material_ids[faceId]; lastMaterial = objAttributes.material_ids[faceId];
@ -4841,7 +4834,7 @@ static Model LoadIQM(const char *fileName)
model.meshes[i].indices = (unsigned short *)RL_CALLOC(model.meshes[i].triangleCount*3, sizeof(unsigned short)); model.meshes[i].indices = (unsigned short *)RL_CALLOC(model.meshes[i].triangleCount*3, sizeof(unsigned short));
#if !SUPPORT_GPU_SKINNING #if !SUPPORT_GPU_SKINNING
// Animated vertex data, what we actually process for rendering // Animated vertex data, processed for rendering
// NOTE: Animated vertex should be re-uploaded to GPU (if not using GPU skinning) // NOTE: Animated vertex should be re-uploaded to GPU (if not using GPU skinning)
model.meshes[i].animVertices = (float *)RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float)); model.meshes[i].animVertices = (float *)RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float));
model.meshes[i].animNormals = (float *)RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float)); model.meshes[i].animNormals = (float *)RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float));
@ -4861,7 +4854,7 @@ static Model LoadIQM(const char *fileName)
for (unsigned int i = imesh[m].first_triangle; i < (imesh[m].first_triangle + imesh[m].num_triangles); i++) for (unsigned int i = imesh[m].first_triangle; i < (imesh[m].first_triangle + imesh[m].num_triangles); i++)
{ {
// IQM triangles indexes are stored in counter-clockwise, but raylib processes the index in linear order, // IQM triangles indexes are stored in counter-clockwise, but raylib processes the index in linear order,
// expecting they point to the counter-clockwise vertex triangle, so we need to reverse triangle indexes // expecting they point to the counter-clockwise vertex triangle, so triangle indexes need to be reversed
// NOTE: raylib renders vertex data in counter-clockwise order (standard convention) by default // NOTE: raylib renders vertex data in counter-clockwise order (standard convention) by default
model.meshes[m].indices[tcounter + 2] = tri[i].vertex[0] - imesh[m].first_vertex; model.meshes[m].indices[tcounter + 2] = tri[i].vertex[0] - imesh[m].first_vertex;
model.meshes[m].indices[tcounter + 1] = tri[i].vertex[1] - imesh[m].first_vertex; model.meshes[m].indices[tcounter + 1] = tri[i].vertex[1] - imesh[m].first_vertex;
@ -5496,7 +5489,7 @@ static Model LoadGLTF(const char *fileName)
int primitivesCount = 0; int primitivesCount = 0;
bool dracoCompression = false; bool dracoCompression = false;
// NOTE: We will load every primitive in the glTF as a separate raylib Mesh // NOTE: Load every primitive in the glTF as a separate raylib Mesh
// Determine total number of meshes needed from the node hierarchy // Determine total number of meshes needed from the node hierarchy
for (unsigned int i = 0; i < data->nodes_count; i++) for (unsigned int i = 0; i < data->nodes_count; i++)
{ {
@ -5528,7 +5521,7 @@ static Model LoadGLTF(const char *fileName)
model.meshCount = primitivesCount; model.meshCount = primitivesCount;
model.meshes = (Mesh *)RL_CALLOC(model.meshCount, sizeof(Mesh)); model.meshes = (Mesh *)RL_CALLOC(model.meshCount, sizeof(Mesh));
// NOTE: We keep an extra slot for default material, in case some mesh requires it // NOTE: Keep an extra slot for default material, in case some mesh requires it
model.materialCount = (int)data->materials_count + 1; model.materialCount = (int)data->materials_count + 1;
model.materials = (Material *)RL_CALLOC(model.materialCount, sizeof(Material)); model.materials = (Material *)RL_CALLOC(model.materialCount, sizeof(Material));
model.materials[0] = LoadMaterialDefault(); // Load default material (index: 0) model.materials[0] = LoadMaterialDefault(); // Load default material (index: 0)
@ -5684,7 +5677,7 @@ static Model LoadGLTF(const char *fileName)
for (unsigned int p = 0; p < mesh->primitives_count; p++) for (unsigned int p = 0; p < mesh->primitives_count; p++)
{ {
// NOTE: We only support primitives defined by triangles // NOTE: Only support primitives defined by triangles
// Other alternatives: points, lines, line_strip, triangle_strip // Other alternatives: points, lines, line_strip, triangle_strip
if (mesh->primitives[p].type != cgltf_primitive_type_triangles) continue; if (mesh->primitives[p].type != cgltf_primitive_type_triangles) continue;
@ -6067,7 +6060,7 @@ static Model LoadGLTF(const char *fileName)
float *temp = (float *)RL_MALLOC(attribute->count*4*sizeof(float)); float *temp = (float *)RL_MALLOC(attribute->count*4*sizeof(float));
LOAD_ATTRIBUTE(attribute, 4, float, temp); LOAD_ATTRIBUTE(attribute, 4, float, temp);
// Convert data to raylib color data type (4 bytes), we expect the color data normalized // Convert data to raylib color data type (4 bytes), color data must be normalized
for (unsigned int c = 0; c < attribute->count*4; c++) model.meshes[meshIndex].colors[c] = (unsigned char)(temp[c]*255.0f); for (unsigned int c = 0; c < attribute->count*4; c++) model.meshes[meshIndex].colors[c] = (unsigned char)(temp[c]*255.0f);
RL_FREE(temp); RL_FREE(temp);
@ -6125,7 +6118,7 @@ static Model LoadGLTF(const char *fileName)
{ {
// The primitive actually keeps the pointer to the corresponding material, // The primitive actually keeps the pointer to the corresponding material,
// raylib instead assigns to the mesh the by its index, as loaded in model.materials array // raylib instead assigns to the mesh the by its index, as loaded in model.materials array
// To get the index, we check if material pointers match, and we assign the corresponding index, // To get the index, check if material pointers match, and assign the corresponding index,
// skipping index 0, the default material // skipping index 0, the default material
if (&data->materials[m] == mesh->primitives[p].material) if (&data->materials[m] == mesh->primitives[p].material)
{ {
@ -6187,7 +6180,7 @@ static Model LoadGLTF(const char *fileName)
{ {
bool hasJoints = false; bool hasJoints = false;
// NOTE: We only support primitives defined by triangles // NOTE: Only support primitives defined by triangles
if (mesh->primitives[p].type != cgltf_primitive_type_triangles) continue; if (mesh->primitives[p].type != cgltf_primitive_type_triangles) continue;
for (unsigned int j = 0; j < mesh->primitives[p].attributes_count; j++) for (unsigned int j = 0; j < mesh->primitives[p].attributes_count; j++)
@ -6234,7 +6227,7 @@ static Model LoadGLTF(const char *fileName)
boneIdOverflowWarning = true; boneIdOverflowWarning = true;
} }
// Despite the possible overflow, we convert data to unsigned char // Despite the possible overflow, convert data to unsigned char
model.meshes[meshIndex].boneIndices[b] = (unsigned char)temp[b]; model.meshes[meshIndex].boneIndices[b] = (unsigned char)temp[b];
} }
@ -6284,8 +6277,7 @@ static Model LoadGLTF(const char *fileName)
model.meshes[meshIndex].boneWeights = (float *)RL_CALLOC(model.meshes[meshIndex].vertexCount*4, sizeof(float)); model.meshes[meshIndex].boneWeights = (float *)RL_CALLOC(model.meshes[meshIndex].vertexCount*4, sizeof(float));
// Load 4 components of float data type into mesh.boneWeights // Load 4 components of float data type into mesh.boneWeights
// for cgltf_attribute_type_weights we have: // for cgltf_attribute_type_weights:
// - data.meshes[0] (256 vertices) // - data.meshes[0] (256 vertices)
// - 256 values, provided as cgltf_type_vec4 of float (4 byte per joint, stride 16) // - 256 values, provided as cgltf_type_vec4 of float (4 byte per joint, stride 16)
LOAD_ATTRIBUTE(attribute, 4, float, model.meshes[meshIndex].boneWeights) LOAD_ATTRIBUTE(attribute, 4, float, model.meshes[meshIndex].boneWeights)
@ -6296,9 +6288,9 @@ static Model LoadGLTF(const char *fileName)
} }
} }
// Check if we are animated, and the mesh was not given any bone assignments, but is the child of a bone node // Check if animated, and the mesh was not given any bone assignments, but is the child of a bone node
// in this case we need to fully attach all the verts to the parent bone so it will animate with the bone // in this case, all the verts need to be attached to the parent bone so it will animate with the bone
if (data->skins_count > 0 && !hasJoints && node->parent != NULL && node->parent->mesh == NULL) if ((data->skins_count > 0) && !hasJoints && (node->parent != NULL) && (node->parent->mesh == NULL))
{ {
int parentBoneId = -1; int parentBoneId = -1;
for (int joint = 0; joint < model.skeleton.boneCount; joint++) for (int joint = 0; joint < model.skeleton.boneCount; joint++)
@ -6435,7 +6427,7 @@ static bool GetPoseAtTimeGLTF(cgltf_interpolation_type interpolationType, cgltf_
} }
else if (output->type == cgltf_type_vec4) else if (output->type == cgltf_type_vec4)
{ {
// Only v4 is for rotations, so we know it's a quaternion // Only v4 is for rotations, so it's a quaternion
switch (interpolationType) switch (interpolationType)
{ {
case cgltf_interpolation_type_step: case cgltf_interpolation_type_step:
@ -6822,7 +6814,7 @@ static Model LoadM3D(const char *fileName)
} }
else TRACELOG(LOG_INFO, "MODEL: [%s] M3D data loaded successfully: %i faces/%i materials", fileName, m3d->numface, m3d->nummaterial); else TRACELOG(LOG_INFO, "MODEL: [%s] M3D data loaded successfully: %i faces/%i materials", fileName, m3d->numface, m3d->nummaterial);
// no face? this is probably just a material library // Check if face is found, if not, probably just a material library
if (!m3d->numface) if (!m3d->numface)
{ {
m3d_free(m3d); m3d_free(m3d);
@ -6841,12 +6833,12 @@ static Model LoadM3D(const char *fileName)
TRACELOG(LOG_INFO, "MODEL: No materials, putting all meshes in a default material"); TRACELOG(LOG_INFO, "MODEL: No materials, putting all meshes in a default material");
} }
// We always need a default material, so we add +1 // A default material is always required, so adding +1
model.materialCount++; model.materialCount++;
// Faces must be in non-decreasing materialid order. Verify that quickly, sorting them otherwise // Faces must be in non-decreasing materialid order. Verify that quickly, sorting them otherwise
// WARNING: Sorting is not needed, valid M3D model files should already be sorted // WARNING: Sorting is not needed, valid M3D model files should already be sorted
// Just keeping the sorting function for reference (Check PR #3363 #3385) // Keeping the sorting function for reference (Check PR #3363 #3385)
/* /*
for (a = 1; a < m3d->numface; a++) for (a = 1; a < m3d->numface; a++)
{ {
@ -6902,7 +6894,7 @@ static Model LoadM3D(const char *fileName)
mi = m3d->face[i].materialid; mi = m3d->face[i].materialid;
// Only allocate colors VertexBuffer if there's a color vertex in the model for this material batch // Only allocate colors VertexBuffer if there's a color vertex in the model for this material batch
// if all colors are fully transparent black for all verteces of this materal, then we assume no vertex colors // if all colors are fully transparent black for all verteces of this materal, then assuming no vertex colors
for (j = i, l = vcolor = 0; (j < (int)m3d->numface) && (mi == m3d->face[j].materialid); j++, l++) for (j = i, l = vcolor = 0; (j < (int)m3d->numface) && (mi == m3d->face[j].materialid); j++, l++)
{ {
if (!m3d->vertex[m3d->face[j].vertex[0]].color || if (!m3d->vertex[m3d->face[j].vertex[0]].color ||
@ -6916,11 +6908,11 @@ static Model LoadM3D(const char *fileName)
model.meshes[k].texcoords = (float *)RL_CALLOC(model.meshes[k].vertexCount*2, sizeof(float)); model.meshes[k].texcoords = (float *)RL_CALLOC(model.meshes[k].vertexCount*2, sizeof(float));
model.meshes[k].normals = (float *)RL_CALLOC(model.meshes[k].vertexCount*3, sizeof(float)); model.meshes[k].normals = (float *)RL_CALLOC(model.meshes[k].vertexCount*3, sizeof(float));
// If no map is provided, or we have colors defined, we allocate storage for vertex colors // If no map is provided, or colors are defined, allocate storage for vertex colors
// M3D specs only consider vertex colors if no material is provided, however raylib uses both and mixes the colors // M3D specs only consider vertex colors if no material is provided, however raylib uses both and mixes the colors
if ((mi == M3D_UNDEF) || vcolor) model.meshes[k].colors = (unsigned char *)RL_CALLOC(model.meshes[k].vertexCount*4, sizeof(unsigned char)); if ((mi == M3D_UNDEF) || vcolor) model.meshes[k].colors = (unsigned char *)RL_CALLOC(model.meshes[k].vertexCount*4, sizeof(unsigned char));
// If no map is provided and we allocated vertex colors, set them to white // If no map is provided and vertex colors are allocated, set them to white
if ((mi == M3D_UNDEF) && (model.meshes[k].colors != NULL)) if ((mi == M3D_UNDEF) && (model.meshes[k].colors != NULL))
{ {
for (int c = 0; c < model.meshes[k].vertexCount*4; c++) model.meshes[k].colors[c] = 255; for (int c = 0; c < model.meshes[k].vertexCount*4; c++) model.meshes[k].colors[c] = 255;
@ -6951,7 +6943,7 @@ static Model LoadM3D(const char *fileName)
model.meshes[k].vertices[l*9 + 7] = m3d->vertex[m3d->face[i].vertex[2]].y*m3d->scale; model.meshes[k].vertices[l*9 + 7] = m3d->vertex[m3d->face[i].vertex[2]].y*m3d->scale;
model.meshes[k].vertices[l*9 + 8] = m3d->vertex[m3d->face[i].vertex[2]].z*m3d->scale; model.meshes[k].vertices[l*9 + 8] = m3d->vertex[m3d->face[i].vertex[2]].z*m3d->scale;
// Without vertex color (full transparency), we use the default color // Without vertex color (full transparency), using the default color
if (model.meshes[k].colors != NULL) if (model.meshes[k].colors != NULL)
{ {
if (m3d->vertex[m3d->face[i].vertex[0]].color & 0xff000000) if (m3d->vertex[m3d->face[i].vertex[0]].color & 0xff000000)
@ -6992,7 +6984,7 @@ static Model LoadM3D(const char *fileName)
{ {
int skinid = m3d->vertex[m3d->face[i].vertex[n]].skinid; int skinid = m3d->vertex[m3d->face[i].vertex[n]].skinid;
// Check if there is a skin for this mesh, should be, just failsafe // Check if there is a skin for this mesh
if ((skinid != M3D_UNDEF) && (skinid < (int)m3d->numskin)) if ((skinid != M3D_UNDEF) && (skinid < (int)m3d->numskin))
{ {
for (j = 0; j < 4; j++) for (j = 0; j < 4; j++)
@ -7003,8 +6995,8 @@ static Model LoadM3D(const char *fileName)
} }
else else
{ {
// raylib does not handle boneless meshes with skeletal animations, so // Boneless meshes with skeletal animations are not supported, so
// we put all vertices without a bone into a special "no bone" bone // putting all vertices without a bone into a special "no bone" bone
model.meshes[k].boneIndices[l*12 + n*4] = m3d->numbone; model.meshes[k].boneIndices[l*12 + n*4] = m3d->numbone;
model.meshes[k].boneWeights[l*12 + n*4] = 1.0f; model.meshes[k].boneWeights[l*12 + n*4] = 1.0f;
} }
@ -7215,7 +7207,7 @@ static ModelAnimation *LoadModelAnimationsM3D(const char *fileName, int *animCou
bones[i].parent = -1; bones[i].parent = -1;
memcpy(bones[i].name, "NO BONE", 7); memcpy(bones[i].name, "NO BONE", 7);
// M3D stores frames at arbitrary intervals with sparse skeletons. We need full skeletons at // M3D stores frames at arbitrary intervals with sparse skeletons; Full skeletons is required at
// regular intervals, so let the M3D SDK do the heavy lifting and calculate interpolated bones // regular intervals, so let the M3D SDK do the heavy lifting and calculate interpolated bones
for (i = 0; i < animations[a].keyframeCount; i++) for (i = 0; i < animations[a].keyframeCount; i++)
{ {

View File

@ -1946,7 +1946,7 @@ void DrawSplineBezierCubic(const Vector2 *points, int pointCount, float thick, C
// Draw spline segment: Linear, 2 points // Draw spline segment: Linear, 2 points
void DrawSplineSegmentLinear(Vector2 p1, Vector2 p2, float thick, Color color) void DrawSplineSegmentLinear(Vector2 p1, Vector2 p2, float thick, Color color)
{ {
// NOTE: For the linear spline no subdivisions are used, just a single quad // NOTE: For the linear spline no subdivisions are used, only a single quad
Vector2 delta = { p2.x - p1.x, p2.y - p1.y }; Vector2 delta = { p2.x - p1.x, p2.y - p1.y };
float length = sqrtf(delta.x*delta.x + delta.y*delta.y); float length = sqrtf(delta.x*delta.x + delta.y*delta.y);

View File

@ -10,7 +10,7 @@
* #define SUPPORT_FILEFORMAT_TTF * #define SUPPORT_FILEFORMAT_TTF
* #define SUPPORT_FILEFORMAT_BDF * #define SUPPORT_FILEFORMAT_BDF
* Selected desired fileformats to be supported for loading. Some of those formats are * Selected desired fileformats to be supported for loading. Some of those formats are
* supported by default, to remove support, just comment unrequired #define in this module * supported by default, to remove support, comment unrequired #define in this module
* *
* #define TEXTSPLIT_MAX_TEXT_BUFFER_LENGTH * #define TEXTSPLIT_MAX_TEXT_BUFFER_LENGTH
* TextSplit() function static buffer max size * TextSplit() function static buffer max size
@ -157,7 +157,7 @@ extern void LoadFontDefault(void)
#define BIT_CHECK(a,b) ((a) & (1u << (b))) #define BIT_CHECK(a,b) ((a) & (1u << (b)))
// Check to see if the font for an image has alreeady been allocated, // Check to see if the font for an image has alreeady been allocated,
// and if no need to upload, then just return // and if no need to upload, then return
if (defaultFont.glyphs != NULL) return; if (defaultFont.glyphs != NULL) return;
// NOTE: Using UTF-8 encoding table for Unicode U+0000..U+00FF Basic Latin + Latin-1 Supplement // NOTE: Using UTF-8 encoding table for Unicode U+0000..U+00FF Basic Latin + Latin-1 Supplement

View File

@ -22,7 +22,7 @@
* #define SUPPORT_FILEFORMAT_PVR * #define SUPPORT_FILEFORMAT_PVR
* #define SUPPORT_FILEFORMAT_ASTC * #define SUPPORT_FILEFORMAT_ASTC
* Select desired fileformats to be supported for image data loading. Some of those formats are * Select desired fileformats to be supported for image data loading. Some of those formats are
* supported by default, to remove support, just comment unrequired #define in this module * supported by default, to remove support, comment unrequired #define in this module
* *
* #define SUPPORT_IMAGE_EXPORT * #define SUPPORT_IMAGE_EXPORT
* Support image export in multiple file formats * Support image export in multiple file formats
@ -1870,7 +1870,7 @@ void ImageToPOT(Image *image, Color fill)
if ((image->data == NULL) || (image->width == 0) || (image->height == 0)) return; if ((image->data == NULL) || (image->width == 0) || (image->height == 0)) return;
// Calculate next power-of-two values // Calculate next power-of-two values
// NOTE: Just add the required amount of pixels at the right and bottom sides of image... // NOTE: Add the required amount of pixels at the right and bottom sides of image...
int potWidth = (int)powf(2, ceilf(logf((float)image->width)/logf(2))); int potWidth = (int)powf(2, ceilf(logf((float)image->width)/logf(2)));
int potHeight = (int)powf(2, ceilf(logf((float)image->height)/logf(2))); int potHeight = (int)powf(2, ceilf(logf((float)image->height)/logf(2)));
@ -2014,7 +2014,7 @@ void ImageAlphaMask(Image *image, Image alphaMask)
Image mask = ImageCopy(alphaMask); Image mask = ImageCopy(alphaMask);
if (mask.format != PIXELFORMAT_UNCOMPRESSED_GRAYSCALE) ImageFormat(&mask, PIXELFORMAT_UNCOMPRESSED_GRAYSCALE); if (mask.format != PIXELFORMAT_UNCOMPRESSED_GRAYSCALE) ImageFormat(&mask, PIXELFORMAT_UNCOMPRESSED_GRAYSCALE);
// In case image is only grayscale, just add alpha channel // In case image is only grayscale, add alpha channel
if (image->format == PIXELFORMAT_UNCOMPRESSED_GRAYSCALE) if (image->format == PIXELFORMAT_UNCOMPRESSED_GRAYSCALE)
{ {
unsigned char *data = (unsigned char *)RL_MALLOC(image->width*image->height*2); unsigned char *data = (unsigned char *)RL_MALLOC(image->width*image->height*2);
@ -2589,7 +2589,7 @@ void ImageFlipHorizontal(Image *image)
// OPTION 1: Move pixels with memcpy() // OPTION 1: Move pixels with memcpy()
//memcpy(flippedData + (y*image->width + x)*bytesPerPixel, ((unsigned char *)image->data) + (y*image->width + (image->width - 1 - x))*bytesPerPixel, bytesPerPixel); //memcpy(flippedData + (y*image->width + x)*bytesPerPixel, ((unsigned char *)image->data) + (y*image->width + (image->width - 1 - x))*bytesPerPixel, bytesPerPixel);
// OPTION 2: Just copy data pixel by pixel // OPTION 2: Copy data pixel by pixel
for (int i = 0; i < bytesPerPixel; i++) flippedData[(y*image->width + x)*bytesPerPixel + i] = ((unsigned char *)image->data)[(y*image->width + (image->width - 1 - x))*bytesPerPixel + i]; for (int i = 0; i < bytesPerPixel; i++) flippedData[(y*image->width + x)*bytesPerPixel + i] = ((unsigned char *)image->data)[(y*image->width + (image->width - 1 - x))*bytesPerPixel + i];
} }
} }
@ -4587,10 +4587,10 @@ void DrawTexturePro(Texture2D texture, Rectangle source, Rectangle dest, Vector2
rlSetTexture(0); rlSetTexture(0);
// NOTE: Vertex position can be transformed using matrices // NOTE: Vertex position can be transformed using matrices
// but the process is way more costly than just calculating // but the process is way more costly than calculating
// the vertex positions manually, like done above // the vertex positions manually, like done above
// Old implementation is left here for educational purposes, // Old implementation is left here for educational purposes,
// just in case someone wants to do some performance test // in case someone wants to do some performance test
/* /*
rlSetTexture(texture.id); rlSetTexture(texture.id);
rlPushMatrix(); rlPushMatrix();